第66天:爬蟲利器 Beautiful Soup 之搜索文檔

2021-02-20 Python技術
Beautiful Soup 簡介

Beautiful Soup 是一個可以從 HTML 或 XML 文件中提取數據的 Python 庫,它提供了一些簡單的操作方式來幫助你處理文檔導航,查找,修改文檔等繁瑣的工作。因為使用簡單,所以 Beautiful Soup 會幫你節省不少的工作時間。

上一篇文章我們介紹了如何使用 Beautiful Soup 來遍歷文檔中的節點,這片文章我們繼續血學習如何使用 Beautiful Soup 指定文檔中搜索到你想要的內容。

Beautiful Soup 搜索文檔

同樣為了故事的順利發展,我們繼續使用之前的 HTML 文本,下文的所有例子都是基於這段文本的。

html_doc = """<html><head><title>index</title></head><body><p><b>首頁</b></p><p>我常用的網站<a href="https://www.google.com" id="google">Google</a><a href="https://www.baidu.com" id="baidu">Baidu</a><a href="https://cn.bing.com" id="bing">Bing</a></p><div><!--這是注釋內容--></div><p>...</p><p>...</p></body>"""soup = BeautifulSoup(html_doc, "lxml")

過濾器

正式講解搜索文檔之前,我們有必要了解下 Beautiful Soup 的過濾器,這些過濾器在整個搜索的 API 中都有所體現,他們可以被用在 TAG 的 name 中,屬性中,字符串中或他們的混合中。聽起來有點繞是麼,看幾個例子就懂了。

1、根據 TAG 的 name 來查找標籤,下面的例子會查找文檔中的所有 b 標籤。同時要注意統一傳入 Unicode 編碼以避免 Beautiful Soup 解析編碼出錯。

# demo 1tags = soup.find_all('b')print(tags)
#輸出結果[<b>首頁</b>]

2、如果傳入正則表達式作為參數,那麼 Beautiful Soup 會通過正則表達式的 match() 來匹配內容。

# demo 2import refor tag in soup.find_all(re.compile("^b")):    print(tag.name)
#輸出結果bodyb

3、如果傳入列表參數,那麼 Beautiful Soup 會將與列表中任一一個元素匹配的內容返回。

# demo 3for tag in soup.find_all(['a', 'b']):    print(tag)
#輸出結果<b>首頁</b><a href="https://www.google.com" id="google">Google</a><a href="https://www.baidu.com" id="baidu">Baidu</a><a href="https://cn.bing.com" id="bing">Bing</a>

4、True 可以匹配任何值,下面的例子是查找所有的 TAG 但不會返回字符串。

# demo 4for tag in soup.find_all(True):    print(tag.name, end=', ') #輸出結果html, head, title, body, p, b, p, a, a, a, div, p, p,

5、方法。我們可以定義一個方法,該方法只接受一個參數,若該方法返回 True 則表示當前元素匹配並且被找到,返回 False 意味著沒找到。下面的例子展示了查找所有同時包含 class 屬性和 id 屬性的節點。

# demo 5def has_id_class(tag):    return tag.has_attr('id') and tag.has_attr('class')
tags = soup.find_all(has_id_class)for tag in tags: print(tag) #輸出結果<a href="https://www.google.com" id="google">Google</a><a href="https://www.baidu.com" id="baidu">Baidu</a><a href="https://cn.bing.com" id="bing">Bing</a>

大部分情況字符串過濾器就可以滿足我們的需求,外加這個神奇的方法過濾器,我們就可以實現各種自定義需求了。

find_all() 函數

該函數搜索當前節點下的所有子節點,其籤名如下find_all( name , attrs , recursive , text , **kwargs )。我們可以傳入指定 TAG 的 name 來查找節點,上面已經舉過例子了,這裡不在贅述。我們來看幾個其他的用法。

1、如果我們傳入 find_all() 函數不是搜索內置的參數名,那麼搜索是就會將該參數對應到屬性上去。下文的例子表示查找 id 為 google 的節點。

搜索指定名字的屬性時可以使用的參數值包括:字符串,正則表達式,列表,True。也就是我們上文介紹過的過濾器。

# demo 6tags = soup.find_all(id='google')print(tags[0]['href'])
for tag in soup.find_all(id=True): # 查找所有包含 id 屬性的 TAG print(tag['href'])
#輸出結果https://www.google.comhttps://www.google.comhttps://www.baidu.comhttps://cn.bing.com

2、按照 CSS 類名搜索,但是鏢師 CSS 的關鍵字 class 在 Python 中是內置關鍵字,從 Beautiful Soup 4.1.1 版本開始,可以通過 class_  參數搜索有指定 CSS 類名的 TAG:

class_ 參數同樣接受不同類型的過濾器:字符串,正則表達式,方法,True。

# demo 7tags = soup.find_all("a", class_="website")for tag in tags:	print(tag['href'])
def has_seven_characters(css_class): return css_class is not None and len(css_class) == 7
for tag in soup.find_all(class_=has_seven_characters): print(tag['id'])
#輸出結果https://www.google.comhttps://www.baidu.comhttps://cn.bing.comgooglebaidubing

同時,因為 CSS 可以有多個值,所以我們可以分別搜索 CSS 中的每個值。

# demo 8css_soup = BeautifulSoup('<p></p>', 'lxml')tags = css_soup.find_all("p", class_="strikeout")print(tags)
#輸出結果[<p></p>]

3、不僅可以按照標籤和 CSS 來搜索整個文檔,還可以使用 text 來按照內容來搜索。同時 text 還可以配合其他屬性一起來完成搜索任務。

# demo 9tags = soup.find_all(text="Google")print("google : ", tags)
tags = soup.find_all(text=["Baidu", "Bing"])print("baidu & bing : ", tags)
tags = soup.find_all('a', text="Google")print("a[text=google] : ", tags)
#輸出結果google : ['Google']baidu & bing : ['Baidu', 'Bing']a[text=google] : [<a href="https://www.google.com" id="google">Google</a>]

4、限制返回數量

有時候文檔樹過於龐大,我們不想查查找整棵樹,只想查找指定數量的節點,或者只想查找子節點,而不想查找孫子節點,指定 limit 或者 recursive 參數即可。

# demo 10tag = soup.find_all("a", limit=1)print(tag)
tags = soup.find_all("p", recursive=False)print(tags)
#輸出結果[<a href="https://www.google.com" id="google">Google</a>][]

因為該對象的兒子節點沒有 p 標籤,所以返回的是空列表。

find() 函數

該函數只會返回一個結果,與 find_all(some_args, limit=1) 是等價的,唯一的區別就是該函數直接返回結果,而 find_all() 函數返回包含一個結果的列表。另外 find_all() 方法沒有找到目標是返回空列表, find() 方法找不到目標時,返回 None。除此之外使用上沒有其他差別。

其他函數

除了 find_all() 和 find() 外,Beautiful Soup 中還有 10 個用於搜索的 API,其中中五個用的是與 find_all() 相同的搜索參數,另外 5 個與 find() 方法的搜索參數類似,區別僅是它們搜索文檔的範圍不同。

find_parents() 和 find_parent() 用來搜索當前節點的父節點。

find_next_siblings() 和 find_next_sibling() 對在當前節點後面解析的所有兄弟節點進行迭代。

find_previous_siblings() 和 find_previous_sibling() 對在當前節點前面解析的所有兄弟節點進行迭代。

find_all_next() 和 find_next() 對當前節點之後的 TAG 和字符串進行迭代。

find_all_previous() 和 find_previous() 對當前節點之前的 TAG 和字符串進行迭代。

以上五組函數的區別僅僅是前者返回一個所有符合搜索條件的節點列表,而後者只返回第一個符合搜索條件的節點。

因為這 10 個 API 的使用和 find_all() 與 find() 大同小異,所有i這裡不在舉例,讀者可以自己探索。

CSS 選擇器

在 Tag 或 BeautifulSoup 對象的 .select() 方法中傳入字符串參數即可使用 CSS 選擇器的語法找到 TAG。

1、通過某個標籤逐層查找。

# demo 11tags = soup.select("body a")for tag in tags:	print(tag['href'])
#輸出結果https://www.google.comhttps://www.baidu.comhttps://cn.bing.com

2、查找某個標籤下的直接子標籤

# demo 12tags = soup.select("p > a")print(tags)
tags = soup.select("p > #google")print(tags)
#輸出結果[<a href="https://www.google.com" id="google">Google</a>, <a href="https://www.baidu.com" id="baidu">Baidu</a>, <a href="https://cn.bing.com" id="bing">Bing</a>][<a href="https://www.google.com" id="google">Google</a>]

3、通過 CSS 類名直接查找

# demo 13tags = soup.select(".website")for tag in tags:	print(tag.string)
#輸出結果GoogleBaiduBing

4、通過標籤的 id 屬性查找

# demo 14tags = soup.select("#google")print(tags)
#輸出結果[<a href="https://www.google.com" id="google">Google</a>]

5、通過屬性的值來查找

# demo 15tags = soup.select('a[href="https://cn.bing.com"]')print(tags)
#輸出結果[<a href="https://cn.bing.com" id="bing">Bing</a>]

Beautiful Soup 總結

本章節介紹了 Beautiful Soup 關於文檔搜索的相關操作,熟練掌握這些 API 的操作可以讓我們更快更好找到我們想要定位的節點,不要看到這麼多函數嚇怕了,其實我們只需要熟練掌握 find_all() 和 find() 兩個函數即可,其餘 API 的使用都大同小異,稍加練習即可快速上手。

代碼地址

示例代碼:https://github.com/JustDoPython/python-100-day/tree/master/day-066

參考內容

https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html#

相關焦點

  • 同事看呆了:不打開文檔,也能搜索裡邊的關鍵詞?
    如果你手頭上有幾十個甚至上百個文檔,想要在其中篩選出內容包含某一個關鍵詞的文檔,你會怎麼做呢?
  • 好聽的英文歌:《Young And Beautiful》
    2013年與電影《了不起的蓋茨比》合作的插曲《Young And Beautiful》在Billboard 200取得第22名。when I'm no longer young and beautiful當我年華老去、容顏凋零Will you still love me你還會愛我嗎?
  • 好聽的英文歌:《Life Is Beautiful》
    Life is beautifulThrough the window透過櫥窗I see you waiting我看到你在等候You are smiling你笑容綻放Cause I m coming因為我向你走來Your eyes are a story你的雙眸充滿故事An ocean
  • CNY | Feb. 18-19 | Beautiful Xinchang, beautiful hiking trails
    There are lot of hidden and beautiful hiking trails. We choose the most 2 beautiful one from our experiences. Let's enjoy the beauty of nature, travel in a safe way, be away from all the crazy crowds.
  • SEO技巧:Google高級搜索指令的應用
    在這裡跟大家分享幾個實用的Google高級搜索指令,將大大有助於提升搜索效率,快速搜索到自己所需信息。1. 雙引號把搜索詞加上雙引號,以整個短語作為搜索關鍵詞,精確匹配,而不是拆開成每個詞。星號星號(*)是用於模糊搜索,其中的*號代表任何文字。比如我們在Google裡輸入*whale,出來的結果可以匹配Baleen Whale、Whale shark等,意為搜索各種鯨魚。如下圖:
  • 辦公指南:為Word文檔巧設不同頁面方向
    該怎樣插入這唯一的橫向頁面,實現文檔中既有縱向頁面又有橫向頁面的效果呢?假設想設置第1頁為縱向,第2頁為橫向,第3頁以後為縱向:方法一:第一步:將光標定位在第2頁第一行,選擇「頁面布局-紙張方向:橫向-應用於:插入點之後-確定」;第二步:將光標定位在第3頁第一行,選擇「頁面布局-紙張方向:縱向-應用於:插入點之後-確定」。
  • The 10 Most Beautiful Women of 2016
    The former Miss World, once again make it amongst the most beautiful women of the world.喬普拉被倫敦的周刊東方之眼評為2015年「亞洲最性感的女人」。她是寶萊塢出色的演員,並多次獲獎。她是在印度最流行和備受矚目的名人之一。去年,她開始主演亞歷克斯·帕裡什ABC劇集《諜網》(Quantico),成為第一個主演美國的網絡系列劇的南亞裔女子。6. Amber Heard 艾梅柏·希爾德
  • 情報直播:第66回日本NHK紅白歌會
    從1953年的第3回開始在電視試播,並決定從這一年起將「紅白歌合戰」作為一項辭舊迎新的重要活動。當年12月31日舉辦第4屆,以後便定為每年12月31日舉辦。從第4屆開始加入現場觀眾。最初時是在內幸町的舊NHK放送會館、東京寶冢劇場、有樂町的產經大廳等會場輾轉舉辦,1973年後固定在東京澀谷的NHK音樂大廳演出至今。
  • 有故事的66號公路
    因為在20世紀,無數美國人在多次的重要時刻都不約而同踏上66號公路的徵程。66號公路起於芝加哥,終於「流奶與蜜之地」的加州太平洋沿岸,橫跨美國八個州、三個時區,全長3940公裡。66號公路的前世傳奇,始於美國冒險家霍雷肖·傑克遜(Horatio Jackson)與休厄爾·克羅克(Sewall Crocker)。
  • Python網絡爬蟲(五)- Requests和Beautiful Soup
  • 聽歌學英語:《You're Beautiful》
    因為我已經有一個計劃You''re beautiful. You''re beautiful.你是美麗的,你是美麗的You''re beautiful, it''s true.但是我們分享了這個永恆的片刻You''re beautiful. You''re beautiful.你是美麗的,你是美麗的You''re beautiful, it''s true.
  • 好聽的英文歌:《Beautiful Life》
    sorrow When everyone passed by You ain't left behind I always stand by When the sunset arrives Your world is still bright By the heart of light Cos we always strive In the beautiful
  • 技術兼福利貼:手把手教你上Google,學會基本搜索和學術搜索
    搜尋:「 酒 貴 賤 之」 ,OK ,找到的第一條資訊就是鏡花緣的這一段落:「 先生聽著:今以酒醋論之,酒價賤之,醋價貴之。因何賤之?為什貴之?真所分之,在其味之。酒昧淡之,故而賤之;醋味厚之,所以貴之。..」「 近義詞法」 的關鍵字選擇技巧範例:「 黃花閨女」 一詞中「 黃花」 是什麼意思。
  • 超好聽的英文歌:Scars To Your Beautiful
    No scars to your beautiful你的美沒有瑕疵We're stars and we're beautiful 我們如繁星般美麗動人She has dreams to be an envy, so she's starving 她夢想著被人羨慕,她每天飢腸轆轆You know
  • 私人音樂盒 38:Beautiful In White - Shane Filan
    不管你在哪 或在經歷什麼願公子收藏的私人音樂能讓你釋懷豁朗 心安喜樂 重拾信心部分歌曲在QQ音樂無法找到且一次只能插入一個音頻所以會分多次分享給大家第38期給大家分享的是愛爾蘭樂隊Westlife成員Shane Filan的Beautiful In White
  • 急救30秒:Word文檔未保存,只用一招,輕鬆找回!
    其實,還能救一救,時予教你一招,分分鐘找回原來的文檔。操作步驟:點擊【文件】-【信息】-【管理文檔】-【恢復未保存的文檔】,在備份文檔夾中找到最接近斷電時間的文檔,雙擊它打開,這樣我們意外關閉的文件就找回來了。
  • 【聽歌曲,學英語】Beautiful In White
    in white你身著白色婚紗,甚是動人And from now to my very last breath從今而後,只要我尚在人世This day I'll cherish婚禮這天都為我所珍惜You look so beautiful in white Tonight今夜,你身著白色婚紗,真的很美
  • 領66元現金這麼容易!!!
    領取66元紅包的方法↓↓↓百年之愛,世代之選淄博百憶·維羅納酒店期待您的光臨!領取66元紅包的方法↓↓↓ 部分合作商家66元紅包領取方法1、5月26日前關注該公眾號並累計轉發本文不少於8天(轉發必須對所有人可見);2、5月26號下午1點開始,憑微信到酒店一樓前臺實名領取;3、66元紅包限前300名領取,300名後可領取100元代金券1張。
  • 一直擁有:賺人熱淚的時刻,92歲老人實現心願和自己66年的髮妻最後一次握手,兩個小時後去世
    The couple, who had been married for 66 years, were both being treated at the Yingzhou People's Hospital in Ningbo, reported People's Daily Online.這對夫妻已經結婚66年,兩人都在寧波市鄞州人民醫院接受治療。
  • Pudong: Urban Soup Kitchen Deal 浦東吾伴濃湯促銷:半價珍珠薏仁雞湯配麵包
    Chicken Pearl Barley Soup 19rmbTemperatures are dipping and our spoons are ready for a hearty and warm soup