BeautifulSoup 使用經(jīng)驗總結(jié)
BeautifulSoup 使用經(jīng)驗總結(jié)
文章目錄
BeautifulSoup 使用經(jīng)驗總結(jié)
概述
安裝
開始使用
經(jīng)驗總結(jié)
節(jié)點(diǎn)對象、名稱、屬性
節(jié)點(diǎn)的文本內(nèi)容
子節(jié)點(diǎn)
父節(jié)點(diǎn)
兄弟節(jié)點(diǎn)
搜索節(jié)點(diǎn)
使用正則表達(dá)式匹配標(biāo)簽名
使用屬性搜索
使用CSS搜索
使用文本內(nèi)容搜索
使用函數(shù)篩選
概述
處理數(shù)據(jù),總要面對 HTML 和 XML 文檔。BeautifulSoup 是一個可以從 HTML 或 XML 中提取數(shù)據(jù)的 Python 庫,功能強(qiáng)大、使用便捷,誠為樸實有華、人見人愛的數(shù)據(jù)處理工具。
安裝
自從有了 pip 這個神器,安裝就不再是問題了。BeautifulSoup 支持 Python 標(biāo)準(zhǔn)庫中的 HTML 解析器,也支持其他解析器。我建議使用更牛叉的第三方解析器 lxml——我曾經(jīng)用它處理過單個文件幾百兆字節(jié)的xml數(shù)據(jù),反應(yīng)神速,毫無遲滯感。當(dāng)然,使用系統(tǒng)已有的解析器,除了速度和效率,基本也不會有啥問題。
$ pip install beautifulsoup4 $ pip install lxml
1
2
開始使用
>>> from bs4 import BeautifulSoup >>> soup = BeautifulSoup("data", "html.parser") # 使用python內(nèi)置標(biāo)準(zhǔn)庫,速度適中,容錯性好 >>> soup = BeautifulSoup("data", "html5lib") # 以瀏覽器的方式解析文檔,容錯性最好 >>> soup = BeautifulSoup("data", ["lxml-xml"]) # lxml XML 解析器,速度快 >>> soup = BeautifulSoup("data", "lxml") # lxml HTML 解析器,速度快,容錯性好
1
2
3
4
5
如果沒有指定解析器,BeautifulSoup 會自動查找使用系統(tǒng)可用的解析器。
經(jīng)驗總結(jié)
所有的例子,均以下面的html為例。
html_doc = """
One
Two
Three

1
2
3
4
5
6
7
8
9
10
11
12
13
14
1
2
3
4
5
6
7
8
9
10
11
12
13
14
1
2
3
4
5
6
7
8
9
10
11
12
13
14
文本也是節(jié)點(diǎn),我們稱之為文本型節(jié)點(diǎn),比如p標(biāo)簽中的One,Two,Three
某個節(jié)點(diǎn)的子節(jié)點(diǎn)往往比我們看到的多,因為在那些可見的子節(jié)點(diǎn)之外的換行、空格、制表位等,也都是某節(jié)點(diǎn)的文本型子節(jié)點(diǎn)
節(jié)點(diǎn)對象、名稱、屬性
使用lxml解析器生成一個 BeautifulSoup 對象 soup,然后可以使用標(biāo)簽名得到節(jié)點(diǎn)對象:
>>> soup = BeautifulSoup(html_doc, 'lxml') >>> tag = soup.html >>> tag.name 'html' >>> tag.p.name 'p'
1
2
3
4
5
6
事實上,我們可以不用在意標(biāo)簽的父級是誰,直接從soup得到節(jié)點(diǎn)對象:
>>> soup.p.name 'p' >>> soup.img['src'] 'http://m.bai1xia.com/news/zb_users/upload/2022/05/20220530084240_53592.jpg' >>> soup.img.attrs {'class': ['photo'], 'src': 'http://m.bai1xia.com/news/zb_users/upload/2022/05/20220530084240_53592.jpg'} >>> soup.p['class'] ['intro', 'short-text'] >>> soup.div['id'] 'My gift'
1
2
3
4
5
6
7
8
9
10
很顯然,這樣的方式得到的節(jié)點(diǎn),一定是html中第一個同類型的標(biāo)簽。上面的例子還演示了如何取得節(jié)點(diǎn)對象的所有的屬性和指定屬性。當(dāng)class屬性有多個值時,返回的是一個列表,而id屬性不承認(rèn)多值。
節(jié)點(diǎn)的文本內(nèi)容
取得一個節(jié)點(diǎn)的文本內(nèi)容,有很多種方法,比如:
>>> soup.p.text 'One' >>> soup.p.getText() 'One' >>> soup.p.get_text() 'One' >>> soup.p.string 'One' >>> type(soup.p.string)
1
2
3
4
5
6
7
8
9
10
當(dāng)一個節(jié)點(diǎn)只有文本型子節(jié)點(diǎn)的時候,前三種方法的效果是完全一致的,第四種方法看上去差不多,但返回的類型是NavigableString(可遍歷的字符串)。
當(dāng)節(jié)點(diǎn)包括元素型子節(jié)點(diǎn)的時候,輸出的結(jié)果可能已經(jīng)不是我們需要的了。此時,可以使用 .strings 或者 .stripped_strings(去掉空行和多余的空格) 得到一個迭代器,遍歷即可得到我們想要的內(nèi)容。
>>> soup.div.text '\nOne\nTwo\nThree\n' >>> soup.html.text '\n\nOne\nTwo\nThree\n\n\n\n\n山東遠(yuǎn)思信息科技有限公司\n\n' >>> for item in soup.div.stripped_strings: print(item) One Two Three
1
2
3
4
5
6
7
8
9
10
子節(jié)點(diǎn)
.contents, .children,.descendants 都可以取得節(jié)點(diǎn)的子節(jié)點(diǎn),但用法各不相同:
.contents, .children 只能取得直接子節(jié)點(diǎn),.descendants 則可以遞歸取得所有子節(jié)點(diǎn)
.contents 返回的子節(jié)點(diǎn)的列表,.children,.descendants 返回的是迭代器
父節(jié)點(diǎn)
.parent 屬性來獲取某個元素的父節(jié)點(diǎn):
>>> soup.p.parent.name 'div'
1
2
.parents 屬性可以遞歸得到元素的所有父輩節(jié)點(diǎn):
>>> for parent in soup.p.parents: print(parent.name) div body html [document]
1
2
3
4
5
6
7
兄弟節(jié)點(diǎn)
可以使用 .next_sibling 和 .previous_sibling 屬性來查詢前一個或后一個兄弟節(jié)點(diǎn),但必須注意,除了可見的兄弟節(jié)點(diǎn),還可能存在換行、空格、制表位等文本型的兄弟節(jié)點(diǎn)混雜其中。
可以使用 .next_siblings 和 .previous_siblings 屬性取得當(dāng)前節(jié)點(diǎn)的前面或后面的兄弟節(jié)點(diǎn)的迭代輸出。
搜索節(jié)點(diǎn)
一般使用 find() 和 find_all() 搜索符合條件的第一個節(jié)點(diǎn)和全部節(jié)點(diǎn)的列表。
>>> soup.find('p')
One
>>> soup.find_all('img') [

1
2
3
4
使用正則表達(dá)式匹配標(biāo)簽名
搜索以d開頭的標(biāo)簽:
>>> import re >>> for tag in soup.find_all(re.compile("^d")): print(tag.name) div div
1
2
3
4
5
6
使用屬性搜索
>>> soup.find_all(id='My gift')[0].name # 查找id=My gift的節(jié)點(diǎn) 'div' >>> soup.find_all(id=True)[0].name # 查找有id屬性的節(jié)點(diǎn) 'div' >>> soup.find_all(attrs={"id":"My gift"})[0].name # 使用attrs查找 'div' >>> soup.find_all(attrs={"class":"intro short-text","align":"right"})[0].text # 使用attrs查找 'Three' >>> soup.find_all(attrs={"align":"right"})[0].text # 使用attrs查找 'Three'
1
2
3
4
5
6
7
8
9
10
使用CSS搜索
>>> soup.find_all("p", class_="intro") [
One
,Two
,Three
] >>> soup.find_all("p", class_="intro short-text") [One
,Two
,Three
] >>>1
2
3
4
5
使用文本內(nèi)容搜索
>>> soup.find_all(string="Two") ['Two'] >>> soup.find_all(string=re.compile("Th")) ['Three']
1
2
3
4
使用函數(shù)篩選
>>> def justdoit(tag): return tag.parent.has_attr('id') and tag['align']=='center' >>> soup.find_all(justdoit) [
Two
]1
2
3
4
5
HTML XML
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。