一烙无、Beautiful Soup4簡(jiǎn)介
這個(gè)第三方庫(kù)可以幫助我們來(lái)處理請(qǐng)求下來(lái)的HTML頁(yè)面中的數(shù)據(jù)珠叔,如果你之前有過(guò)前端開(kāi)發(fā)的經(jīng)驗(yàn)或者是熟悉HTML標(biāo)記語(yǔ)言和CSS語(yǔ)言的話撵彻,那么基本上可以無(wú)縫對(duì)接地使用這個(gè)第三方庫(kù)來(lái)幫助你處理數(shù)據(jù)碑幅,繼而完成我們的爬蟲檐盟。
這里我們會(huì)給出Beautiful Soup4的中文文檔都许,學(xué)習(xí)Pyhton到現(xiàn)在稻薇,提供這么詳細(xì)中文文檔的第三方庫(kù),還真是不多梭稚。如果大家想詳細(xì)了解學(xué)習(xí)這個(gè)庫(kù)的話颖低,可以直接訪問(wèn)官網(wǎng)中文文檔。
但是如果你想快速掌握這個(gè)第三方庫(kù)弧烤,那么就繼續(xù)看下去吧忱屑。這篇文章會(huì)給大家介紹Beautiful Soup4常用的方法和屬性,能夠幫助你快速掌握該庫(kù)暇昂,快速將其應(yīng)用到你的項(xiàng)目中莺戒。
使用這個(gè)庫(kù)之前,需要安裝一下急波,如果你不知道如何安裝从铲,推薦大家查看博客:Pycharm配置環(huán)境及安裝第三方庫(kù)。
二澄暮、Beautiful Soup基本使用
Beautiful Soup4(后面簡(jiǎn)稱bs4)這個(gè)庫(kù)只能從HTML字符串中名段,來(lái)查找和過(guò)濾我們需要的數(shù)據(jù)阱扬,不能從本地文件中讀取數(shù)據(jù)進(jìn)行過(guò)濾。不過(guò)這對(duì)我們基本上沒(méi)有影響伸辟,因?yàn)槲覀冏雠老x的時(shí)候麻惶,大多數(shù)情況下,都是從網(wǎng)絡(luò)上直接爬取HTML頁(yè)面中的內(nèi)容信夫,然后進(jìn)行查找篩選了窃蹋,而不需存儲(chǔ)到本地文件中。
比如我們以騰訊招聘頁(yè)面中的一些數(shù)據(jù)為例静稻,首先創(chuàng)建一個(gè)字符串警没,存儲(chǔ)我們的原始數(shù)據(jù),我們接下來(lái)的方法講解振湾,也是圍繞這一字符串進(jìn)行的杀迹。實(shí)例代碼如下:
from bs4 import BeautifulSoup # 引入我們的bs4庫(kù)
html_str = """
<tbody>
<tr class="h">
<td class="l" width="374">職位名稱</td>
<td>職位類別</td>
<td>人數(shù)</td>
<td>地點(diǎn)</td>
<td>發(fā)布時(shí)間</td>
</tr>
<tr class="even">
<td class="l square"><a target="_blank" href="position_detail.php?id=44569&keywords=Python&tid=0&lid=0">MIG16-基礎(chǔ)架構(gòu)工程師(北京)</a></td>
<td>技術(shù)類</td>
<td>1</td>
<td>北京</td>
<td>2018-09-29</td>
</tr>
<tr class="odd">
<td class="l square"><a target="_blank" href="position_detail.php?id=44570&keywords=Python&tid=0&lid=0">MIG16-數(shù)據(jù)系統(tǒng)高級(jí)開(kāi)發(fā)工程師</a></td>
<td>技術(shù)類</td>
<td>1</td>
<td>北京</td>
<td>2018-09-29</td>
</tr>
<tr class="even">
<td class="l square"><a target="_blank" href="position_detail.php?id=44567&keywords=Python&tid=0&lid=0">MIG16-基礎(chǔ)架構(gòu)工程師(北京)</a></td>
<td>技術(shù)類</td>
<td>1</td>
<td>北京</td>
<td>2018-09-29</td>
</tr>
<tr class="odd">
<td class="l square"><a target="_blank" href="position_detail.php?id=44559&keywords=Python&tid=0&lid=0">18796-專項(xiàng)技術(shù)測(cè)試(深圳)</a><span class="hot"> </span></td>
<td>技術(shù)類</td>
<td>2</td>
<td>深圳</td>
<td>2018-09-29</td>
</tr>
</tbody>
"""
現(xiàn)在有了一個(gè)字符串,我們便可以將其作為參數(shù)恰梢,調(diào)用BeautifulSoup(param_1,param_2)
來(lái)生成一個(gè)Beautiful Soup對(duì)象佛南。這個(gè)時(shí)候涉及到一個(gè)解析器的知識(shí),也就是上述方法的第二個(gè)參數(shù)嵌言。解析器用來(lái)幫助我們解析文本結(jié)構(gòu)嗅回,目前主要的解析器有以下幾種:
這里推薦大家使用xlml解析器,因?yàn)樾矢摺摧茴,F(xiàn)在便可以將字符串生成Beautiful Soup對(duì)象了绵载。示例代碼如下:
bs = BeautifulSoup(html_str,'lxml')
接下來(lái),我們便以這個(gè)Beautiful Soup對(duì)象為基礎(chǔ)苛白,講解bs4庫(kù)中常用的方法和屬性娃豹。
三、Beautiful Soup常用的方法和屬性
1.find_all() 方法:
find_all()方法搜索當(dāng)前tag的所有符合過(guò)濾條件的tag子節(jié)點(diǎn)购裙。在搜索子節(jié)點(diǎn)的時(shí)候懂版,我們不僅可以制定要搜索的子節(jié)點(diǎn)的標(biāo)簽名,還可以添加過(guò)濾條件躏率,更精確的選擇我們需要的子節(jié)點(diǎn)躯畴。實(shí)例代碼如下:
- 不加過(guò)濾條件,獲取全部的tr標(biāo)簽
trs = bs.find_all('tr')
- 限制選擇標(biāo)簽的數(shù)量薇芝,獲取符合條件的前兩個(gè)tr標(biāo)簽
trs = bs.find_all('tr',limit=2)
- 選擇class為even的tr子節(jié)點(diǎn)蓬抄,注意傳入的參數(shù)是class_,不是class
trs = bs.find_all('tr',class_="even")
- 選擇class=even夯到,且id=feng的tr子節(jié)點(diǎn)
trs = bs.find_all('tr', class_="even", id="feng")
# 上述代碼等價(jià)于
trs = bs.find_all('tr', {"class": "even", "id": "feng"})
2.find() 方法:
find()方法和find_all()方法的參數(shù)和用法幾乎一樣嚷缭,只不過(guò)find()方法只選取符合條件的第一個(gè)標(biāo)簽。同時(shí),下面三條數(shù)據(jù)是等價(jià)的阅爽。
tr = bs.find("tr")
tr = bs.find_all("tr", limit=1)
tr = bs.find_all("tr")[0]
3.get_text()方法:
如果只想得到tag中包含的文本內(nèi)容,那么可以使用get_text()
方法,這個(gè)方法獲取到tag中包含的所有文版內(nèi)容包括子孫tag中的內(nèi)容,并將結(jié)果作為Unicode字符串返回路幸。
tr = bs.find_all("tr")[0]
print(tr.get_text())
# 上述代碼返回的字符串如下:
# 職位名稱
# 職位類別
# 人數(shù)
# 地點(diǎn)
# 發(fā)布時(shí)間
我們還可以傳入一個(gè)參數(shù)作為分隔符,讓獲取的字符串更好的顯示出來(lái)优床,示例代碼如下:
tr = bs.find_all("tr")[0]
print(tr.get_text("----"))
# 上述代碼返回的字符串如下:
# ----職位名稱----
# ----職位類別----
# ----人數(shù)----
# ----地點(diǎn)----
# ----發(fā)布時(shí)間----
我們還可以傳入?yún)?shù)strip=True
刪除返回的字符串左右兩邊的空格劝赔,示例代碼如下:
tr = bs.find_all("tr")[0]
print(tr.get_text("----",strip=True))
# 上述代碼返回的字符串如下:
# 職位名稱----職位類別----人數(shù)----地點(diǎn)----發(fā)布時(shí)間
4.獲取節(jié)點(diǎn)屬性的方法:
如果我們想要獲取節(jié)點(diǎn)的屬性誓焦,比如對(duì)于<a href="www.baidu.com"></a>
胆敞,我們想獲取它的href屬性值,即www.baidu.com杂伟∫撇悖或者對(duì)于其他的節(jié)點(diǎn)元素,我們想要獲取name赫粥、class观话、id等屬性值的時(shí)候,我們可以采用下面的方法:
trs = bs.find_all("a")
for tr in trs:
print(tr["href"])
5.select()方法:
通過(guò)使用bs庫(kù)中的select()
方法越平,我們可以使用CSS選擇器來(lái)選擇我們需要的標(biāo)簽频蛔。也就是說(shuō),我們可以通過(guò)標(biāo)簽名秦叛,標(biāo)簽的class晦溪、標(biāo)簽的id,通過(guò)標(biāo)簽的name挣跋、href等屬性來(lái)選擇我們的元素三圆。使用該方法返回的是一個(gè)迭代器,我們可以通過(guò)for...in...循環(huán)遍歷避咆。示例代碼如下:
# 選擇所有的p標(biāo)簽
p = bs.select("p")
# 選擇class為box的標(biāo)簽
box = bs.select(".box")
# 選擇id為text的標(biāo)簽
text = bs.select("#text")
# 選擇div中的span標(biāo)簽
span = bs.select("div span")
# 選擇div中的直接子元素img
img = bs.select("div > img")
# 通過(guò)屬性來(lái)查找標(biāo)簽舟肉,比如查找href屬性等于index.html的a節(jié)點(diǎn)
a = bs.select("a[href='index.html']")
這只是CSS選擇器的一部分,其他的CSS也是很類似的查库。如果有web前端基礎(chǔ)路媚,那么你平時(shí)如何設(shè)置節(jié)點(diǎn)元素的樣式,在這里你就按照同樣的方法選擇節(jié)點(diǎn)元素即可樊销。
6.string屬性:
如果一個(gè)節(jié)點(diǎn)只包含一個(gè)文本節(jié)點(diǎn)整慎,或者是只包含一個(gè)節(jié)點(diǎn),那么可以使用該屬性獲取該文本節(jié)點(diǎn)的文本內(nèi)容现柠,或者是這個(gè)節(jié)點(diǎn)的文本內(nèi)容院领。例如:對(duì)于<div>hahaha</div>
和<div><p>hahaha</p></div>
,使用返回的結(jié)果是一樣的够吩,示例代碼如下:
divs = bs.select("div")
for div in divs:
print(div.string)
但是如果一個(gè)節(jié)點(diǎn)下面有很多子孫節(jié)點(diǎn)比然,使用string屬性在獲取文本的時(shí)候,最終返回的是None
周循。這個(gè)時(shí)候我們應(yīng)該使用下面的屬性强法。
7.strings屬性:
如果一個(gè)節(jié)點(diǎn)下面有很多子孫節(jié)點(diǎn)万俗,我們可以使用strings屬性來(lái)獲取其子孫節(jié)點(diǎn)的所有文本。該屬性最終返回的是一個(gè)迭代器饮怯,我們可以通過(guò)for...in...
循環(huán)來(lái)遍歷闰歪。實(shí)例代碼如下:
tr = bs.select("tr")[0]
for text in tr.strings:
print(text)
# 上述代碼的結(jié)果可能是這樣的,由于換行和空格的存在蓖墅,可能會(huì)有空白文本
#
#
# 職位名稱
#
#
# 職位類別
#
#
# 人數(shù)
#
#
# 地點(diǎn)
#
#
# 發(fā)布時(shí)間
8.stripped_strings屬性:
在使用上述strings屬性獲取一個(gè)節(jié)點(diǎn)中后代文本的時(shí)候库倘,可能或出現(xiàn)換行和空格等空白文本,這樣在處理的時(shí)候會(huì)出現(xiàn)麻煩论矾,如果不想獲取換行和空格教翩,那么我們可以使用stripped_strings屬性。該屬性和strings屬性一樣贪壳,返回的也是迭代器饱亿,不能直接打印,需要使用for...in...
循環(huán)來(lái)遍歷闰靴。示例代碼如下:
tr = bs.select("tr")[0]
for text in tr.stripped_strings:
print(text)
# 過(guò)濾到空白文本彪笼,這個(gè)時(shí)候的文本是這樣的
# 職位名稱
# 職位類別
# 人數(shù)
# 地點(diǎn)
# 發(fā)布時(shí)間
9.contents屬性:
該屬性返回的是某個(gè)節(jié)點(diǎn)下的全部子元素,包括子元素的標(biāo)簽名和文本內(nèi)容蚂且。返回的數(shù)據(jù)類型是列表配猫,示例代碼如下:
feng = bs.find("tr",id="test")
print(type(feng.contents)) # 打印出來(lái)的是 <class 'list'>
for text in feng.contents:
print(text)
10.children屬性
該屬性和contents屬性的用法是一樣的,但是返回的數(shù)據(jù)類型是迭代器膘掰,示例代碼如下:
feng = bs.find("tr",id="test")
print(type(feng.children)) # 打印出來(lái)的是 <class 'list_iterator'>
for text in feng.children:
print(text)
四章姓、Beautiful Soup4中四中常見(jiàn)的對(duì)象
1.Tag對(duì)象:
Beautiful Soup中所有的標(biāo)簽都是Tag類型,并且通過(guò)bs = BeautifulSoup(html_str, 'lxml')
方法常見(jiàn)的bs對(duì)象在本質(zhì)上也是Tag類型识埋。我們我們前面說(shuō)到的find_all()
凡伊、find()
等方法,也都是Tag對(duì)象的方法窒舟。
2.BeautifulSoup對(duì)象
通過(guò)bs = BeautifulSoup(html_str, 'lxml')
方法常見(jiàn)的bs是BeautifulSoup對(duì)象系忙,BeautifulSoup繼承自Tag對(duì)象。所以我們之前說(shuō)bs在本質(zhì)上是Tag類型惠豺,而且BeautifulSoup對(duì)象的find_all()
银还、find()
也是繼承自Tag對(duì)象的。
3.NavigableString對(duì)象
該對(duì)象繼承自Python中的str對(duì)象洁墙,用起來(lái)和str一樣蛹疯,沒(méi)什么說(shuō)的。
4.Comment對(duì)象
這個(gè)對(duì)象繼承自NavigableString對(duì)象热监,也沒(méi)什么說(shuō)的捺弦。
這些知識(shí)點(diǎn)知識(shí)個(gè)人總結(jié),使我們?cè)谑褂肞ython做爬蟲的時(shí)候常用的一些方法和屬性。
如果想獲取更過(guò)的知識(shí)列吼,大家可以訪問(wèn)文章開(kāi)頭給出的Beautiful Soup4的官方文檔進(jìn)行學(xué)習(xí)幽崩。