一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語(yǔ)言編程技術(shù)及教程分享平臺(tái)!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Python - python爬蟲(chóng)入門教程--HTML文本的解析庫(kù)BeautifulSoup(四)

python爬蟲(chóng)入門教程--HTML文本的解析庫(kù)BeautifulSoup(四)

2020-11-12 00:39FOOFISH Python

Beautiful Soup是python的一個(gè)庫(kù),最主要的功能是從網(wǎng)頁(yè)抓取數(shù)據(jù)。下面這篇文章主要給大家介紹了python爬蟲(chóng)之HTML文本的解析庫(kù)BeautifulSoup的相關(guān)資料,文中介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看

前言

python爬蟲(chóng)系列文章的第3篇介紹了網(wǎng)絡(luò)請(qǐng)求庫(kù)神器 Requests ,請(qǐng)求把數(shù)據(jù)返回來(lái)之后就要提取目標(biāo)數(shù)據(jù),不同的網(wǎng)站返回的內(nèi)容通常有多種不同的格式,一種是 json 格式,這類數(shù)據(jù)對(duì)開(kāi)發(fā)者來(lái)說(shuō)最友好。另一種 XML 格式的,還有一種最常見(jiàn)格式的是 HTML 文檔,今天就來(lái)講講如何從 HTML 中提取出感興趣的數(shù)據(jù)

自己寫個(gè) HTML 解析器來(lái)解析嗎?還是用正則表達(dá)式?這些都不是最好的辦法,好在,Python 社區(qū)在這方便早就有了很成熟的方案,BeautifulSoup 就是這一類問(wèn)題的克星,它專注于 HTML 文檔操作,名字來(lái)源于 Lewis Carroll 的一首同名詩(shī)歌。

BeautifulSoup 是一個(gè)用于解析 HTML 文檔的 Python 庫(kù),通過(guò) BeautifulSoup,你只需要用很少的代碼就可以提取出 HTML 中任何感興趣的內(nèi)容,此外,它還有一定的 HTML 容錯(cuò)能力,對(duì)于一個(gè)格式不完整的HTML 文檔,它也可以正確處理。

安裝 BeautifulSoup

?
1
pip install beautifulsoup4

BeautifulSoup3 被官方放棄維護(hù),你要下載最新的版本 BeautifulSoup4。

HTML 標(biāo)簽

學(xué)習(xí) BeautifulSoup4 前有必要先對(duì) HTML 文檔有一個(gè)基本認(rèn)識(shí),如下代碼,HTML 是一個(gè)樹(shù)形組織結(jié)構(gòu)。

?
1
2
3
4
5
6
7
8
9
<html>
 <head>
  <title>hello, world</title>
 </head>
 <body>
  <h1>BeautifulSoup</h1>
  <p>如何使用BeautifulSoup</p>
 <body>
</html>
  • 它由很多標(biāo)簽(Tag)組成,比如 html、head、title等等都是標(biāo)簽
  • 一個(gè)標(biāo)簽對(duì)構(gòu)成一個(gè)節(jié)點(diǎn),比如 ... 是一個(gè)根節(jié)點(diǎn)
  • 節(jié)點(diǎn)之間存在某種關(guān)系,比如 h1 和 p 互為鄰居,他們是相鄰的兄弟(sibling)節(jié)點(diǎn)
  • h1 是 body 的直接子(children)節(jié)點(diǎn),還是 html 的子孫(descendants)節(jié)點(diǎn)
  • body 是 p 的父(parent)節(jié)點(diǎn),html 是 p 的祖輩(parents)節(jié)點(diǎn)
  • 嵌套在標(biāo)簽之間的字符串是該節(jié)點(diǎn)下的一個(gè)特殊子節(jié)點(diǎn),比如 “hello, world” 也是一個(gè)節(jié)點(diǎn),只不過(guò)沒(méi)名字。

使用 BeautifulSoup

構(gòu)建一個(gè) BeautifulSoup 對(duì)象需要兩個(gè)參數(shù),第一個(gè)參數(shù)是將要解析的 HTML 文本字符串,第二個(gè)參數(shù)告訴 BeautifulSoup 使用哪個(gè)解析器來(lái)解析 HTML。

解析器負(fù)責(zé)把 HTML 解析成相關(guān)的對(duì)象,而 BeautifulSoup 負(fù)責(zé)操作數(shù)據(jù)(增刪改查)。”html.parser” 是Python內(nèi)置的解析器,”lxml” 則是一個(gè)基于c語(yǔ)言開(kāi)發(fā)的解析器,它的執(zhí)行速度更快,不過(guò)它需要額外安裝

通過(guò) BeautifulSoup 對(duì)象就可以定位到 HTML 中的任何一個(gè)標(biāo)簽節(jié)點(diǎn)。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from bs4 import BeautifulSoup
text = """
<html>
 <head>
  <title >hello, world</title>
 </head>
 <body>
  <h1>BeautifulSoup</h1>
  <p class="bold">如何使用BeautifulSoup</p>
  <p class="big" id="key1"> 第二個(gè)p標(biāo)簽</p>
  <a href="http://foofish.net" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >python</a>
 </body>
</html>
"""
soup = BeautifulSoup(text, "html.parser")
 
# title 標(biāo)簽
>>> soup.title
<title>hello, world</title>
 
# p 標(biāo)簽
>>> soup.p
<p class="bold">\u5982\u4f55\u4f7f\u7528BeautifulSoup</p>
 
# p 標(biāo)簽的內(nèi)容
>>> soup.p.string
u'\u5982\u4f55\u4f7f\u7528BeautifulSoup'

BeatifulSoup 將 HTML 抽象成為 4 類主要的數(shù)據(jù)類型,分別是Tag , NavigableString , BeautifulSoup,Comment 。每個(gè)標(biāo)簽節(jié)點(diǎn)就是一個(gè)Tag對(duì)象,NavigableString 對(duì)象一般是包裹在Tag對(duì)象中的字符串,BeautifulSoup 對(duì)象代表整個(gè) HTML 文檔。例如:

?
1
2
3
4
5
6
>>> type(soup)
<class 'bs4.BeautifulSoup'>
>>> type(soup.h1)
<class 'bs4.element.Tag'>
>>> type(soup.p.string)
<class 'bs4.element.NavigableString'>

Tag

每個(gè) Tag 都有一個(gè)名字,它對(duì)應(yīng) HTML 的標(biāo)簽名稱。

?
1
2
3
4
>>> soup.h1.name
u'h1'
>>> soup.p.name
u'p'

標(biāo)簽還可以有屬性,屬性的訪問(wèn)方式和字典是類似的,它返回一個(gè)列表對(duì)象

?
1
2
>>> soup.p['class']
[u'bold']

NavigableString

獲取標(biāo)簽中的內(nèi)容,直接使用 .stirng 即可獲取,它是一個(gè) NavigableString 對(duì)象,你可以顯式地將它轉(zhuǎn)換為 unicode 字符串。

?
1
2
3
4
5
6
7
>>> soup.p.string
u'\u5982\u4f55\u4f7f\u7528BeautifulSoup'
>>> type(soup.p.string)
<class 'bs4.element.NavigableString'>
>>> unicode_str = unicode(soup.p.string)
>>> unicode_str
u'\u5982\u4f55\u4f7f\u7528BeautifulSoup'

基本概念介紹完,現(xiàn)在可以正式進(jìn)入主題了,如何從 HTML 中找到我們關(guān)心的數(shù)據(jù)?BeautifulSoup 提供了兩種方式,一種是遍歷,另一種是搜索,通常兩者結(jié)合來(lái)完成查找任務(wù)。

遍歷文檔樹(shù)

遍歷文檔樹(shù),顧名思義,就是是從根節(jié)點(diǎn) html 標(biāo)簽開(kāi)始遍歷,直到找到目標(biāo)元素為止,遍歷的一個(gè)缺陷是,如果你要找的內(nèi)容在文檔的末尾,那么它要遍歷整個(gè)文檔才能找到它,速度上就慢了。因此還需要配合第二種方法。

通過(guò)遍歷文檔樹(shù)的方式獲取標(biāo)簽節(jié)點(diǎn)可以直接通過(guò) .標(biāo)簽名的方式獲取,例如:

獲取 body 標(biāo)簽:

?
1
2
>>> soup.body
<body>\n<h1>BeautifulSoup</h1>\n<p class="bold">\u5982\u4f55\u4f7f\u7528BeautifulSoup</p>\n</body>

獲取 p 標(biāo)簽

?
1
2
>>> soup.body.p
<p class="bold">\u5982\u4f55\u4f7f\u7528BeautifulSoup</p>

獲取 p 標(biāo)簽的內(nèi)容

?
1
2
>>> soup.body.p.string
\u5982\u4f55\u4f7f\u7528BeautifulSoup

前面說(shuō)了,內(nèi)容也是一個(gè)節(jié)點(diǎn),這里就可以用 .string 的方式得到。遍歷文檔樹(shù)的另一個(gè)缺點(diǎn)是只能獲取到與之匹配的第一個(gè)子節(jié)點(diǎn),例如,如果有兩個(gè)相鄰的 p 標(biāo)簽時(shí),第二個(gè)標(biāo)簽就沒(méi)法通過(guò) .p 的方式獲取,這是需要借用 next_sibling 屬性獲取相鄰且在后面的節(jié)點(diǎn)。此外,還有很多不怎么常用的屬性,比如:.contents 獲取所有子節(jié)點(diǎn),.parent 獲取父節(jié)點(diǎn),更多的參考請(qǐng)查看官方文檔

搜索文檔樹(shù)

搜索文檔樹(shù)是通過(guò)指定標(biāo)簽名來(lái)搜索元素,另外還可以通過(guò)指定標(biāo)簽的屬性值來(lái)精確定位某個(gè)節(jié)點(diǎn)元素,最常用的兩個(gè)方法就是 find 和 find_all。這兩個(gè)方法在 BeatifulSoup 和 Tag 對(duì)象上都可以被調(diào)用。

find_all()

?
1
find_all( name , attrs , recursive , text , **kwargs )

find_all 的返回值是一個(gè) Tag 組成的列表,方法調(diào)用非常靈活,所有的參數(shù)都是可選的。

第一個(gè)參數(shù) name 是標(biāo)簽節(jié)點(diǎn)的名字。

?
1
2
3
4
5
6
# 找到所有標(biāo)簽名為title的節(jié)點(diǎn)
>>> soup.find_all("title")
[<title>hello, world</title>]
>>> soup.find_all("p")
[<p class="bold">\xc8\xe7\xba\xce\xca\xb9\xd3\xc3BeautifulSoup</p>,
<p class="big"> \xb5\xda\xb6\xfe\xb8\xf6p\xb1\xea\xc7\xa9</p>]

第二個(gè)參數(shù)是標(biāo)簽的class屬性值

?
1
2
3
# 找到所有class屬性為big的p標(biāo)簽
>>> soup.find_all("p", "big")
[<p class="big"> \xb5\xda\xb6\xfe\xb8\xf6p\xb1\xea\xc7\xa9</p>]

等效于

?
1
2
>>> soup.find_all("p", class_="big")
[<p class="big"> \xb5\xda\xb6\xfe\xb8\xf6p\xb1\xea\xc7\xa9</p>]

因?yàn)?class 是 Python 關(guān)鍵字,所以這里指定為 class_。

kwargs 是標(biāo)簽的屬性名值對(duì),例如:查找有href屬性值為 "http://foofish.net" 的標(biāo)簽

?
1
2
>>> soup.find_all(href="http://foofish.net" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" )
[<a href="http://foofish.net" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >python</a>]

當(dāng)然,它還支持正則表達(dá)式

?
1
2
3
>>> import re
>>> soup.find_all(href=re.compile("^http"))
[<a href="http://foofish.net" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >python</a>]

屬性除了可以是具體的值、正則表達(dá)式之外,它還可以是一個(gè)布爾值(True/Flase),表示有屬性或者沒(méi)有該屬性。

?
1
2
3
4
>>> soup.find_all(id="key1")
[<p class="big" id="key1"> \xb5\xda\xb6\xfe\xb8\xf6p\xb1\xea\xc7\xa9</p>]
>>> soup.find_all(id=True)
[<p class="big" id="key1"> \xb5\xda\xb6\xfe\xb8\xf6p\xb1\xea\xc7\xa9</p>]

遍歷和搜索相結(jié)合查找,先定位到 body 標(biāo)簽,縮小搜索范圍,再?gòu)?body 中找 a 標(biāo)簽。

?
1
2
3
>>> body_tag = soup.body
>>> body_tag.find_all("a")
[<a href="http://foofish.net" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >python</a>]

find()

find 方法跟 find_all 類似,唯一不同的地方是,它返回的單個(gè) Tag 對(duì)象而非列表,如果沒(méi)找到匹配的節(jié)點(diǎn)則返回 None。如果匹配多個(gè) Tag,只返回第0個(gè)。

?
1
2
3
4
>>> body_tag.find("a")
<a href="http://foofish.net" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >python</a>
>>> body_tag.find("p")
<p class="bold">\xc8\xe7\xba\xce\xca\xb9\xd3\xc3BeautifulSoup</p>

get_text()

獲取標(biāo)簽里面內(nèi)容,除了可以使用 .string 之外,還可以使用 get_text 方法,不同的地方在于前者返回的一個(gè) NavigableString 對(duì)象,后者返回的是 unicode 類型的字符串。

?
1
2
3
4
5
6
7
8
9
10
11
12
>>> p1 = body_tag.find('p').get_text()
>>> type(p1)
<type 'unicode'>
>>> p1
u'\xc8\xe7\xba\xce\xca\xb9\xd3\xc3BeautifulSoup'
 
>>> p2 = body_tag.find("p").string
>>> type(p2)
<class 'bs4.element.NavigableString'>
>>> p2
u'\xc8\xe7\xba\xce\xca\xb9\xd3\xc3BeautifulSoup'
>>>

實(shí)際場(chǎng)景中我們一般使用 get_text 方法獲取標(biāo)簽中的內(nèi)容。

總結(jié)

BeatifulSoup 是一個(gè)用于操作 HTML 文檔的 Python 庫(kù),初始化 BeatifulSoup 時(shí),需要指定 HTML 文檔字符串和具體的解析器。BeatifulSoup 有3類常用的數(shù)據(jù)類型,分別是 Tag、NavigableString、和 BeautifulSoup。查找 HTML元素有兩種方式,分別是遍歷文檔樹(shù)和搜索文檔樹(shù),通常快速獲取數(shù)據(jù)需要二者結(jié)合。

好了,以上就是關(guān)于這篇文章的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家學(xué)習(xí)或者使用python能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)服務(wù)器之家的支持。

原文鏈接:https://foofish.net/crawler-beautifulsoup.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 99久久国产综合精品1尤物 | 亚洲99久久无色码中文字幕 | 精品高潮呻吟99AV无码视频 | 五月婷婷在线免费观看 | 香蕉久久一区二区三区啪啪 | 久久综合亚洲色hezyo | 果冻传媒在线完整免费观 | 免费看一级a一片毛片 | 国产特黄a级在线视频 | 亚洲精品久久久久69影院 | 边摸边吃奶玩乳尖视频 | 精品国产中文字幕在线视频 | 疯狂伦交1一6 小说 风间由美在线 | 精品一区二区国语对白 | 97香蕉超级碰碰碰久久兔费 | 亚洲男人的天堂在线 | 亚洲成综合人影院在院播放 | 丝瓜污污视频 | 国产自拍专区 | 青青久久精品国产免费看 | 女仆色永久免费网站 | 午夜影院小视频 | 日韩精品一区二区三区视频 | 鬼吹灯天星术在线高清观看 | 四虎影院永久网址 | sss亚洲国产欧美一区二区 | 午夜一区二区福利视频在线 | aigao视频| 九九精品免视频国产成人 | 日本韩国无矿砖码 | 痴mu动漫成年动漫在线观看 | 男女视频在线观看网站 | 成人福利在线播放 | 久久中文字幕无线观看 | 秘书喂奶好爽一边 | 国产suv精品一区二区四区三区 | 国产精品探花一区在线观看 | 亚洲AV无码一区二区三区乱子伦 | 国产盗摄wc女厕所 | 青青热久久综合网伊人 | 无人区在线观看免费国语完整版 |