国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

python爬蟲入門教程--HTML文本的解析庫BeautifulSoup(四)

2019-11-25 16:08:58
字體:
來源:轉載
供稿:網友

前言

python爬蟲系列文章的第3篇介紹了網絡請求庫神器 Requests ,請求把數據返回來之后就要提取目標數據,不同的網站返回的內容通常有多種不同的格式,一種是 json 格式,這類數據對開發者來說最友好。另一種 XML 格式的,還有一種最常見格式的是 HTML 文檔,今天就來講講如何從 HTML 中提取出感興趣的數據

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

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

安裝 BeautifulSoup

pip install beautifulsoup4

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

HTML 標簽

學習 BeautifulSoup4 前有必要先對 HTML 文檔有一個基本認識,如下代碼,HTML 是一個樹形組織結構。

<html>  <head>  <title>hello, world</title> </head> <body>  <h1>BeautifulSoup</h1>  <p>如何使用BeautifulSoup</p> <body></html> 
  • 它由很多標簽(Tag)組成,比如 html、head、title等等都是標簽
  • 一個標簽對構成一個節點,比如 ... 是一個根節點
  • 節點之間存在某種關系,比如 h1 和 p 互為鄰居,他們是相鄰的兄弟(sibling)節點
  • h1 是 body 的直接子(children)節點,還是 html 的子孫(descendants)節點
  • body 是 p 的父(parent)節點,html 是 p 的祖輩(parents)節點
  • 嵌套在標簽之間的字符串是該節點下的一個特殊子節點,比如 “hello, world” 也是一個節點,只不過沒名字。

使用 BeautifulSoup

構建一個 BeautifulSoup 對象需要兩個參數,第一個參數是將要解析的 HTML 文本字符串,第二個參數告訴 BeautifulSoup 使用哪個解析器來解析 HTML。

解析器負責把 HTML 解析成相關的對象,而 BeautifulSoup 負責操作數據(增刪改查)。”html.parser” 是Python內置的解析器,”lxml” 則是一個基于c語言開發的解析器,它的執行速度更快,不過它需要額外安裝

通過 BeautifulSoup 對象就可以定位到 HTML 中的任何一個標簽節點。

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"> 第二個p標簽</p>  <a  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 標簽>>> soup.title<title>hello, world</title># p 標簽>>> soup.p<p class="bold">/u5982/u4f55/u4f7f/u7528BeautifulSoup</p># p 標簽的內容>>> soup.p.stringu'/u5982/u4f55/u4f7f/u7528BeautifulSoup'

BeatifulSoup 將 HTML 抽象成為 4 類主要的數據類型,分別是Tag , NavigableString , BeautifulSoup,Comment 。每個標簽節點就是一個Tag對象,NavigableString 對象一般是包裹在Tag對象中的字符串,BeautifulSoup 對象代表整個 HTML 文檔。例如:

>>> type(soup)<class 'bs4.BeautifulSoup'>>>> type(soup.h1)<class 'bs4.element.Tag'>>>> type(soup.p.string)<class 'bs4.element.NavigableString'>

Tag

每個 Tag 都有一個名字,它對應 HTML 的標簽名稱。

>>> soup.h1.nameu'h1'>>> soup.p.nameu'p'

標簽還可以有屬性,屬性的訪問方式和字典是類似的,它返回一個列表對象

>>> soup.p['class'][u'bold']

NavigableString

獲取標簽中的內容,直接使用 .stirng 即可獲取,它是一個 NavigableString 對象,你可以顯式地將它轉換為 unicode 字符串。

>>> soup.p.stringu'/u5982/u4f55/u4f7f/u7528BeautifulSoup'>>> type(soup.p.string)<class 'bs4.element.NavigableString'>>>> unicode_str = unicode(soup.p.string)>>> unicode_stru'/u5982/u4f55/u4f7f/u7528BeautifulSoup'

基本概念介紹完,現在可以正式進入主題了,如何從 HTML 中找到我們關心的數據?BeautifulSoup 提供了兩種方式,一種是遍歷,另一種是搜索,通常兩者結合來完成查找任務。

遍歷文檔樹

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

通過遍歷文檔樹的方式獲取標簽節點可以直接通過 .標簽名的方式獲取,例如:

獲取 body 標簽:

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

獲取 p 標簽

>>> soup.body.p<p class="bold">/u5982/u4f55/u4f7f/u7528BeautifulSoup</p>

獲取 p 標簽的內容

>>> soup.body.p.string/u5982/u4f55/u4f7f/u7528BeautifulSoup

前面說了,內容也是一個節點,這里就可以用 .string 的方式得到。遍歷文檔樹的另一個缺點是只能獲取到與之匹配的第一個子節點,例如,如果有兩個相鄰的 p 標簽時,第二個標簽就沒法通過 .p 的方式獲取,這是需要借用 next_sibling 屬性獲取相鄰且在后面的節點。此外,還有很多不怎么常用的屬性,比如:.contents 獲取所有子節點,.parent 獲取父節點,更多的參考請查看官方文檔

搜索文檔樹

搜索文檔樹是通過指定標簽名來搜索元素,另外還可以通過指定標簽的屬性值來精確定位某個節點元素,最常用的兩個方法就是 find 和 find_all。這兩個方法在 BeatifulSoup 和 Tag 對象上都可以被調用。

find_all()

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

find_all 的返回值是一個 Tag 組成的列表,方法調用非常靈活,所有的參數都是可選的。

第一個參數 name 是標簽節點的名字。

# 找到所有標簽名為title的節點>>> 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>]

第二個參數是標簽的class屬性值

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

等效于

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

因為 class 是 Python 關鍵字,所以這里指定為 class_。

kwargs 是標簽的屬性名值對,例如:查找有href屬性值為 "http://foofish.net" 的標簽

>>> soup.find_all( rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" )[<a  rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >python</a>]

當然,它還支持正則表達式

>>> import re>>> soup.find_all(href=re.compile("^http"))[<a  rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >python</a>]

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

>>> 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>]

遍歷和搜索相結合查找,先定位到 body 標簽,縮小搜索范圍,再從 body 中找 a 標簽。

>>> body_tag = soup.body>>> body_tag.find_all("a")[<a  rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >python</a>]

find()

find 方法跟 find_all 類似,唯一不同的地方是,它返回的單個 Tag 對象而非列表,如果沒找到匹配的節點則返回 None。如果匹配多個 Tag,只返回第0個。

>>> body_tag.find("a")<a  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()

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

>>> p1 = body_tag.find('p').get_text()>>> type(p1)<type 'unicode'>>>> p1u'/xc8/xe7/xba/xce/xca/xb9/xd3/xc3BeautifulSoup'>>> p2 = body_tag.find("p").string>>> type(p2)<class 'bs4.element.NavigableString'>>>> p2u'/xc8/xe7/xba/xce/xca/xb9/xd3/xc3BeautifulSoup'>>>

實際場景中我們一般使用 get_text 方法獲取標簽中的內容。

總結

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

好了,以上就是關于這篇文章的全部內容,希望本文的內容對大家學習或者使用python能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對武林網的支持。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 兴海县| 宁武县| 马山县| 菏泽市| 七台河市| 松原市| 始兴县| 龙门县| 大荔县| 莱西市| 会泽县| 石楼县| 谢通门县| 南充市| 塔城市| 科技| 武汉市| 鸡泽县| 昌邑市| 法库县| 南和县| 淮安市| 肇东市| 信丰县| 余江县| 玛多县| 瓦房店市| 临夏市| 新沂市| 赤水市| 三江| 定襄县| 侯马市| 且末县| 琼结县| 雷波县| 瑞丽市| 咸丰县| 顺昌县| 久治县| 双城市|