爬蟲必備Beautiful Soup包使用詳解
使用Beautiful Soup解析數(shù)據(jù)
Beautiful Soup是一個(gè)用于從HTML和XML文件中提取數(shù)據(jù)的Python模塊。Beautiful Soup提供一些簡(jiǎn)單的函數(shù)用來(lái)處理導(dǎo)航、搜索、修改分析樹(shù)等功能。Beautiful Soup 模塊中的查找提取功能非常強(qiáng)大,而且非常便捷。Beautiful Soup自動(dòng)輸入文檔轉(zhuǎn)換為Unicode編碼,輸出文檔轉(zhuǎn)換為UTF-8編碼。開(kāi)發(fā)者不需要考慮編碼方式,除非文檔沒(méi)有指定一個(gè)編碼方式,這時(shí),Beautiful Soup就不能自動(dòng)識(shí)別編碼方式了。
Beautiful Soup 的安裝
目前推薦使用的是Beautiful Soup 4, 已經(jīng)被移植到bs4當(dāng)中,需要from bs4 然后導(dǎo)入Beautiful Soup 。
pip?install?bs4
解析器
Beautiful Soup支持Python標(biāo)準(zhǔn)庫(kù)中包含的HTML解析器,但它也支持許多第三方Python解析器,其中包含lxml解析器。根據(jù)不同的操作系統(tǒng),您可以使用以下命令之一安裝lxml:
§ apt-get install python-lxml
§ easy_install lxml
§ pip install lxml
另一個(gè)解析器是html5lib,它是一個(gè)用于解析HTML的Python庫(kù),按照Web瀏覽器的方式解析HTML。您可以使用以下命令之一安裝html5lib:
§ apt-get install python-html5lib
§ easy_install html5lib
§ pip install html5lib
關(guān)于每個(gè)解析器的優(yōu)缺點(diǎn)如下表:
| 解析器 | 用 ? 法 | 優(yōu) 點(diǎn) | 缺 點(diǎn) |
|---|---|---|---|
| Python標(biāo)準(zhǔn)庫(kù) | BeautifulSoup(markup, 'html.parser') | Python 標(biāo)準(zhǔn)庫(kù)執(zhí)行速度適中 | (在Python2.7.3或3.2.2之前的版本中)文檔容錯(cuò)能力差 |
| lxml的HTML解析器 | BeautifulSoup(markup, 'lxml') | 速度快文檔容錯(cuò)能力強(qiáng) | 需要安裝C語(yǔ)言庫(kù) |
| lxml的XML解析器 | BeautifulSoup(markup, 'lxml-xml') BeautifulSoup(markup,'xml') | 速度快唯一支持XML的解析器 | 需要安裝C語(yǔ)言庫(kù) |
| html5lib | BeautifulSoup(markup, 'html5lib') | 最好的容錯(cuò)性,以瀏覽器的方式解析文檔生成HTML5格式文檔 | 速度慢,不依賴外部擴(kuò)展 |
Beautiful Soup的簡(jiǎn)單應(yīng)用
Beautiful Soup安裝完成以后,下面將將介紹如何通過(guò)Beautiful Soup 庫(kù)進(jìn)行HTML的解析工作,具體示例步驟如下:
(1)導(dǎo)入bs4庫(kù),然后創(chuàng)建一個(gè)模擬HTML代碼的字符串,代碼如下:
#?作者??????:liuxiaowei
#?創(chuàng)建時(shí)間???:2/5/22 9:25 PM
#?文件??????:使用BeautifulSoup解析HTML代碼.py
# IDE ?????:PyCharm
from?bs4?import?BeautifulSoup??#?導(dǎo)入BeautifulSoup庫(kù)
#?創(chuàng)建模擬HTML代碼的字符串
html_doc?=?"""
第一個(gè)?HTML?頁(yè)面
body 元素的內(nèi)容會(huì)顯示在瀏覽器中。
title 元素的內(nèi)容會(huì)顯示在瀏覽器的標(biāo)題欄中。
"""
(2)創(chuàng)建BeautifulSoup對(duì)象,并指定解析器為lxml,最后通過(guò)打印的方式將解析的HTML代碼顯示在控制臺(tái)當(dāng)中,代碼如下:
#?創(chuàng)建一個(gè)BeautifulSoup對(duì)象,獲取頁(yè)面正文
soup?=?BeautifulSoup(html_doc,?features="lxml")
print(soup)??????????????????#?打印解析的HTML代碼
print(type(soup))????????????#?打印數(shù)據(jù)類型
程序運(yùn)行結(jié)果如下:
第一個(gè)?HTML?頁(yè)面
body 元素的內(nèi)容會(huì)顯示在瀏覽器中。
title 元素的內(nèi)容會(huì)顯示在瀏覽器的標(biāo)題欄中。
<class?'bs4.BeautifulSoup'>
說(shuō) 明
如果將html_doc字符串中的代碼,保存在index.html文件中,可以通過(guò)打開(kāi)HTML文件的方式進(jìn)行代碼解析,并且可以通過(guò)prettify()方法進(jìn)行代碼的格式化處理,代碼如下:
with?open('index.html',?'w')?as?f:
??f.write('html_doc')
soup?=?BeautifulSoup(open("index.html"),?"lxml")
print(soup.prettify())
獲取節(jié)點(diǎn)內(nèi)容
使用Beautiful Soup 可以直接調(diào)用節(jié)點(diǎn)的名稱,然后再調(diào)用對(duì)應(yīng)的string屬性便可以獲取到節(jié)點(diǎn)內(nèi)的文本信息。在單個(gè)節(jié)點(diǎn)結(jié)構(gòu)層次非常清晰的情況下,使用這種方式提取節(jié)點(diǎn)信息的速度是非常快的。
獲取節(jié)點(diǎn)對(duì)應(yīng)的代碼
示例代碼如下:
#_*_coding:utf-8_*_
#?作者??????:liuxiaowei
#?創(chuàng)建時(shí)間???:2/5/22 9:25 PM
#?文件??????:使用BeautifulSoup解析HTML代碼.py
# IDE ?????:PyCharm
from?bs4?import?BeautifulSoup??#?導(dǎo)入BeautifulSoup庫(kù)
#?創(chuàng)建模擬HTML代碼的字符串
html_doc?=?"""
第一個(gè)?HTML?頁(yè)面
body 元素的內(nèi)容會(huì)顯示在瀏覽器中。
title 元素的內(nèi)容會(huì)顯示在瀏覽器的標(biāo)題欄中。
"""
#?創(chuàng)建一個(gè)BeautifulSoup對(duì)象,獲取頁(yè)面正文
with?open('index.html',?'w')?as?f:
????f.write(html_doc)
soup?=?BeautifulSoup(open('index.html'),?"lxml")
print(soup.prettify())
程序運(yùn)行結(jié)果如下:
head節(jié)點(diǎn)內(nèi)容為:
?
第一個(gè)?HTML?頁(yè)面
body節(jié)點(diǎn)內(nèi)容為:
?
body 元素的內(nèi)容會(huì)顯示在瀏覽器中。
title 元素的內(nèi)容會(huì)顯示在瀏覽器的標(biāo)題欄中。
title節(jié)點(diǎn)內(nèi)容為:
?第一個(gè)?HTML?頁(yè)面
p節(jié)點(diǎn)內(nèi)容為:
?body 元素的內(nèi)容會(huì)顯示在瀏覽器中。
注 意
在打印p節(jié)點(diǎn)對(duì)應(yīng)的代碼時(shí),會(huì)發(fā)現(xiàn)只打印了第一個(gè)P節(jié)點(diǎn)內(nèi)容,這說(shuō)明當(dāng)多個(gè)節(jié)點(diǎn)時(shí),該選擇方式只會(huì)獲取第一個(gè)節(jié)點(diǎn)中的內(nèi)容,其他后面的節(jié)點(diǎn)將被忽略。
說(shuō) 明
除了通過(guò)制訂節(jié)點(diǎn)名稱的方式獲取節(jié)點(diǎn)內(nèi)容以外,還可以使用name屬性獲取節(jié)點(diǎn)的名稱,示例代碼如下:
#?獲取節(jié)點(diǎn)名稱
print(soup.head.name)
print(soup.body.name)
print(soup.title.name)
print(soup.p.name)程序運(yùn)行結(jié)果如下:
head
body
title
p
獲取節(jié)點(diǎn)屬性
每個(gè)節(jié)點(diǎn)可能都會(huì)含有多個(gè)屬性,例如, class或者id等。如果已經(jīng)選擇了一個(gè)指定的節(jié)點(diǎn)名稱,那么只需要調(diào)用attrs即可獲取這個(gè)節(jié)點(diǎn)下的所有屬性。代碼如下:
#_*_coding:utf-8_*_
#?作者??????:liuxiaowei
#?創(chuàng)建時(shí)間???:2/6/22 10:17 AM
#?文件??????:獲取節(jié)點(diǎn)屬性.py
# IDE ?????:PyCharm
from?bs4?import?BeautifulSoup??#?導(dǎo)入BeautifulSoup庫(kù)
#?創(chuàng)建模擬HTML代碼的字符串
html_doc?=?"""
????橫排響應(yīng)式登錄
????
????
????
????
登錄
"""
#?創(chuàng)建一個(gè)BeautifulSoup對(duì)象,獲取頁(yè)面正文
soup?=?BeautifulSoup(html_doc,?features="lxml")
print('meta節(jié)點(diǎn)中屬性如下:\n',soup.meta.attrs)
print('link節(jié)點(diǎn)中屬性如下:\n',soup.link.attrs)
print('div節(jié)點(diǎn)中屬性如下:\n',soup.div.attrs)
print('div節(jié)點(diǎn)中input屬性如下:\n',?soup.div.input.attrs)
程序運(yùn)行結(jié)果如下:
meta節(jié)點(diǎn)中屬性如下:
?{'http-equiv':?'Content-Type',?'content':?'text/html',?'charset':?'utf-8'}
link節(jié)點(diǎn)中屬性如下:
?{'href':?'font/css/bootstrap.min.css',?'type':?'text/css',?'rel':?['stylesheet']}
div節(jié)點(diǎn)中屬性如下:
?{'class':?['glyphicon',?'glyphicon-envelope']}
div節(jié)點(diǎn)中input屬性如下:
?{'type':?'text',?'placeholder':?'請(qǐng)輸入郵箱'}
在以上的運(yùn)行結(jié)果中可以發(fā)現(xiàn),attrs的返回結(jié)果為字典類型,字典中的元素分別是對(duì)應(yīng)屬性名稱與對(duì)應(yīng)的值。所以
在attrs后面添加[]括號(hào)并在括號(hào)內(nèi)添加屬性名稱即可獲取指定屬性對(duì)應(yīng)的值。代碼如下:
print('meta節(jié)點(diǎn)中http-equiv屬性對(duì)應(yīng)的值為:',?soup.meta.attrs['http-equiv'])
print('link節(jié)點(diǎn)中href屬性對(duì)應(yīng)的值為:',?soup.link.attrs['href'])
print('div節(jié)點(diǎn)中class屬性對(duì)應(yīng)的值為:',?soup.div.attrs['class'])
程序運(yùn)行結(jié)果如下:
meta節(jié)點(diǎn)中http-equiv屬性對(duì)應(yīng)的值為:Content-Type
link節(jié)點(diǎn)中href屬性對(duì)應(yīng)的值為:font/css/bootstrap.min.css
div節(jié)點(diǎn)中class屬性對(duì)應(yīng)的值為:?['glyphicon',?'glyphicon-envelope']
在獲取節(jié)點(diǎn)中指定屬性所對(duì)應(yīng)的值時(shí),除了使用上面的方式外,還可以不寫attrs,直接在節(jié)點(diǎn)后面以中括號(hào)的形式直接添加屬性名稱,來(lái)獲取對(duì)應(yīng)的值。代碼如下:
print('meta節(jié)點(diǎn)中http-equiv屬性對(duì)應(yīng)的值為:',?soup.meta['http-equiv'])
print('link節(jié)點(diǎn)中href屬性對(duì)應(yīng)的值為:',?soup.link['href'])
print('div節(jié)點(diǎn)中class屬性對(duì)應(yīng)的值為:',?soup.div['class'])
獲取節(jié)點(diǎn)包含的文本內(nèi)容
實(shí)現(xiàn)獲取節(jié)點(diǎn)包含的文本內(nèi)容是非常簡(jiǎn)單的,只需要在節(jié)點(diǎn)名稱后面添加string屬性即可。代碼如下:
print('title節(jié)點(diǎn)內(nèi)包含的文本內(nèi)容為:',?soup.title.string)
print('h3節(jié)點(diǎn)所包含的文本內(nèi)容為:',?soup.h3.string)
程序運(yùn)行結(jié)果如下:
title節(jié)點(diǎn)內(nèi)包含的文本內(nèi)容為:?橫排響應(yīng)式登錄
h3節(jié)點(diǎn)所包含的文本內(nèi)容為:?登錄
嵌套獲取節(jié)點(diǎn)內(nèi)容
HTML代碼中的每個(gè)節(jié)點(diǎn)都會(huì)出現(xiàn)嵌套的可能,而使用Beautiful Soup獲取每個(gè)節(jié)點(diǎn)的內(nèi)容時(shí),以通過(guò)“."直接獲取下一個(gè)節(jié)點(diǎn)中的內(nèi)容(當(dāng)前節(jié)點(diǎn)的子節(jié)點(diǎn))。代碼如下:
#_*_coding:utf-8_*_
#?作者??????:liuxiaowei
#?創(chuàng)建時(shí)間???:2/6/22 11:49 AM
#?文件??????:獲取嵌套節(jié)點(diǎn)內(nèi)容.py
# IDE ?????:PyCharm
from?bs4?import?BeautifulSoup??#?導(dǎo)入BeautifulSoup庫(kù)
#?創(chuàng)建模擬HTML代碼的字符串
html_doc?=?"""
????橫排響應(yīng)式登錄
????
????
????
????
"""
#?創(chuàng)建一個(gè)BeautifulSoup對(duì)象,獲取頁(yè)面正文
soup?=?BeautifulSoup(html_doc,?features="lxml")
print('head節(jié)點(diǎn)內(nèi)容如下:\n',soup.head)
print('head節(jié)點(diǎn)數(shù)據(jù)類型為:',type(soup.head))
print('head節(jié)點(diǎn)中title節(jié)點(diǎn)內(nèi)容如下:\n',soup.head.title)
print('head節(jié)點(diǎn)中title節(jié)點(diǎn)數(shù)據(jù)類型為:',type(soup.head.title))
print('head節(jié)點(diǎn)中title節(jié)點(diǎn)中的文本內(nèi)容為:',soup.head.title.string)
print('head節(jié)點(diǎn)中title節(jié)點(diǎn)中文本內(nèi)容的數(shù)據(jù)類型為:',type(soup.head.title.string))
程序運(yùn)行結(jié)果如下:
head節(jié)點(diǎn)內(nèi)容如下:
?
橫排響應(yīng)式登錄
"utf-8"?content="text/html"?http-equiv="Content-Type"/>
"width=device-width"?name="viewport"/>
"font/css/bootstrap.min.css"?rel="stylesheet"?type="text/css"/>
"css/style.css"?rel="stylesheet"?type="text/css"/>
head節(jié)點(diǎn)數(shù)據(jù)類型為:?<class?'bs4.element.Tag'>
head節(jié)點(diǎn)中title節(jié)點(diǎn)內(nèi)容如下:
?<title>橫排響應(yīng)式登錄title>
head節(jié)點(diǎn)中title節(jié)點(diǎn)數(shù)據(jù)類型為:?<class?'bs4.element.Tag'>
head節(jié)點(diǎn)中title節(jié)點(diǎn)中的文本內(nèi)容為:?橫排響應(yīng)式登錄
head節(jié)點(diǎn)中title節(jié)點(diǎn)中文本內(nèi)容的數(shù)據(jù)類型為:?<class?'bs4.element.NavigableString'>
說(shuō) 明
在上面的運(yùn)行結(jié)果中可以看出,在獲取head與其內(nèi)部的title節(jié)點(diǎn)內(nèi)容時(shí)數(shù)據(jù)類型均為“
關(guān)聯(lián)獲取
在獲取節(jié)點(diǎn)內(nèi)容時(shí),不一定都能做到一步獲取指定節(jié)點(diǎn)中的內(nèi)容,有時(shí)還需要先確認(rèn)某一個(gè)節(jié)點(diǎn),然后以該節(jié)點(diǎn)為中心獲取對(duì)應(yīng)的子節(jié)點(diǎn)、孫節(jié)點(diǎn)、父節(jié)點(diǎn)以及兄弟節(jié)點(diǎn)。
? 1、獲取子節(jié)點(diǎn)
在獲取某節(jié)點(diǎn)下面的所有子節(jié)點(diǎn)時(shí),可以使用contents或者是children屬性來(lái)實(shí)現(xiàn),其中contents返回的是一個(gè)列表,在這列表中的每個(gè)元素都是一個(gè)子節(jié)點(diǎn)內(nèi)容,而children返回的則是一個(gè)"list_iterator"類型的可迭代對(duì)象。獲取所有子節(jié)點(diǎn)的代碼如下:
#_*_coding:utf-8_*_
#?作者??????:liuxiaowei
#?創(chuàng)建時(shí)間???:2/6/22 1:18 PM
#?文件??????:實(shí)現(xiàn)獲取某節(jié)點(diǎn)下所有子節(jié)點(diǎn)內(nèi)容.py
# IDE ?????:PyCharm
from?bs4?import?BeautifulSoup??#?導(dǎo)入BeautifulSoup庫(kù)
#?創(chuàng)建模擬HTML代碼的字符串
html_doc?=?"""
????關(guān)聯(lián)獲取演示
????
"""
#?創(chuàng)建一個(gè)BeautifulSoup對(duì)象,獲取頁(yè)面正文
soup?=?BeautifulSoup(html_doc,?features="lxml")
print(soup.head.contents)???????????#?列表形式打印head下所有子節(jié)點(diǎn)
print(soup.head.children)???????????#?可迭代對(duì)象形式打印head下所有子節(jié)點(diǎn)
程序運(yùn)行結(jié)果如下:
['\n',?關(guān)聯(lián)獲取演示 ,?'\n',?"utf-8"/>,?'\n']
0x7f7cf94fcfa0>
從上面結(jié)果可以看出,通過(guò)head.contents所獲取的所有子節(jié)點(diǎn)中有三個(gè)換行符\n以及兩個(gè)子標(biāo)題(title與meta)對(duì)應(yīng)的所有內(nèi)容。head.children所獲取的則是一個(gè)'list_iterator'可迭代對(duì)象,如果需要的獲取該對(duì)象中的所有內(nèi)容可以直接將其轉(zhuǎn)換為list類型或者通過(guò)for循環(huán)遍歷的方式進(jìn)行獲取。代碼如下:
print(list(soup.head.children))???#?打印將可迭代對(duì)象轉(zhuǎn)換為列表形式的所有子節(jié)點(diǎn)
for?i?in?soup.head.children:????#?循環(huán)遍歷可迭代對(duì)象中的所有子節(jié)點(diǎn)
??print(i)?????????????#?打印子節(jié)點(diǎn)內(nèi)容
程序運(yùn)行結(jié)果如下:
['\n',?關(guān)聯(lián)獲取演示 ,?'\n',?"utf-8"/>,?'\n']
關(guān)聯(lián)獲取演示
"utf-8"/>
? 2、獲取孫節(jié)點(diǎn)
在獲取某節(jié)點(diǎn)下面所有的子孫節(jié)點(diǎn)時(shí),可以使用descendants屬性來(lái)實(shí)現(xiàn),該屬性會(huì)返回一個(gè)generator對(duì)象,獲取該對(duì)象中的所有內(nèi)容時(shí),同樣可以直接將其轉(zhuǎn)換為list 類型或者通過(guò)for循環(huán)遍歷的方式進(jìn)行獲取。這里以for循環(huán)遍歷方式為例,代碼如下:
#_*_coding:utf-8_*_
#?作者??????:liuxiaowei
#?創(chuàng)建時(shí)間???:2/6/22 2:06 PM
#?文件??????:使用descendants屬性獲取子孫節(jié)點(diǎn)內(nèi)容.py
# IDE ?????:PyCharm
from?bs4?import?BeautifulSoup??#?導(dǎo)入BeautifulSoup庫(kù)
#?創(chuàng)建模擬HTML代碼的字符串
html_doc?=?"""
…此處省略…
????
????????
????????????
????????????????此處為演示信息
????????????
????????
????
"""
#?創(chuàng)建一個(gè)BeautifulSoup對(duì)象,獲取頁(yè)面正文
soup?=?BeautifulSoup(html_doc,?features="lxml")
print(soup.body.descendants)??????????#?打印body節(jié)點(diǎn)下所有子孫節(jié)點(diǎn)內(nèi)容的generator對(duì)象
for?i?in?soup.body.descendants:???????#?循環(huán)遍歷generator對(duì)象中的所有子孫節(jié)點(diǎn)
????print(i)????????????????????????????#?打印子孫節(jié)點(diǎn)內(nèi)容
程序運(yùn)行如下:
所有子孫節(jié)點(diǎn)內(nèi)容的generator對(duì)象
0x7ff1b24f3580>
- "test1">瀏覽 89"test2">
- class="test3"?value="user1234">
????????????????此處為演示信息
????????????li>
ul>
div>
div> body節(jié)點(diǎn)下所有子節(jié)點(diǎn)內(nèi)容 body節(jié)點(diǎn)下所有孫節(jié)點(diǎn)及以下內(nèi)容
"test2">- class="test3"?value="user1234">
????????????????此處為演示信息
????????????li>
ul>
div>
<ul>
<li?class="test3"?value="user1234">
????????????????此處為演示信息
????????????li>
ul>
<li?class="test3"?value="user1234">
????????????????此處為演示信息
????????????li>
????????????????此處為演示信息
? 3.獲取父節(jié)點(diǎn)
獲取父節(jié)點(diǎn)有兩種方式:一種是通過(guò)parent屬性直接獲取指定節(jié)點(diǎn)的父節(jié)點(diǎn)內(nèi)容,還可以 通過(guò)parents屬性獲取指定節(jié)點(diǎn)的父節(jié)點(diǎn)及以上(祖先節(jié)點(diǎn))內(nèi)容,只是parents屬性會(huì)返回一個(gè)generator對(duì)象,獲取該對(duì)象中的所有內(nèi)容時(shí),同樣可以直接將其轉(zhuǎn)換為list類型或者通過(guò)for 循環(huán)遍歷的方式進(jìn)行獲取。這里以for循環(huán)遍歷方式為例,代碼如下:
#_*_coding:utf-8_*_
#?作者??????:liuxiaowei
#?創(chuàng)建時(shí)間???:2/6/22 2:34 PM
#?文件??????:獲取父節(jié)點(diǎn)及祖先節(jié)點(diǎn)內(nèi)容.py
# IDE ?????:PyCharm
from?bs4?import?BeautifulSoup??#?導(dǎo)入BeautifulSoup庫(kù)
#?創(chuàng)建模擬HTML代碼的字符串
html_doc?=?"""
????關(guān)聯(lián)獲取演示
????
"""
#?創(chuàng)建一個(gè)BeautifulSoup對(duì)象,獲取頁(yè)面正文
soup?=?BeautifulSoup(html_doc,?features="lxml")
print(soup.title.parent)????????????????#?打印title節(jié)點(diǎn)的父節(jié)點(diǎn)內(nèi)容
print(soup.title.parents)???????????????#?打印title節(jié)點(diǎn)的父節(jié)點(diǎn)及以上內(nèi)容的generator對(duì)象
for?i?in?soup.title.parents:???????????#?循環(huán)遍歷generator對(duì)象中的所有父節(jié)點(diǎn)及以上內(nèi)容
????print(i.name)???????????????????????#?打印父節(jié)點(diǎn)及祖先節(jié)點(diǎn)名稱直接獲取title節(jié)點(diǎn)的父節(jié)點(diǎn)內(nèi)容
關(guān)聯(lián)獲取演示
"utf-8"/>父節(jié)點(diǎn)及以上內(nèi)容的generator對(duì)象
0x7fb0b8df36d0> 循環(huán)遍歷父節(jié)點(diǎn)及祖先節(jié)點(diǎn)的名稱
head
html
[document]說(shuō) 明
在上面的運(yùn)行結(jié)果可以看出,parents屬性所獲取父節(jié)點(diǎn)的順序?yàn)閔ead,html,最后的[document]表示文檔對(duì)象,既是整個(gè)HTML文檔,也是BeautifulSoup對(duì)象。
? 4、獲取兄弟節(jié)點(diǎn)
兄弟節(jié)點(diǎn)也就是同級(jí)節(jié)點(diǎn),表示在同一級(jí)節(jié)點(diǎn)內(nèi)的所有子節(jié)點(diǎn)間的關(guān)系。如,在一段HTML代碼中獲取第一個(gè)p節(jié)點(diǎn)的下一個(gè)div兄弟節(jié)點(diǎn)時(shí)可以使用next_sibling屬性,如果想獲取當(dāng)前div節(jié)點(diǎn)的上一個(gè)兄弟節(jié)點(diǎn)p時(shí)可以使用previous_sibling屬性。通過(guò)這兩個(gè)屬性獲取兄弟節(jié)點(diǎn)時(shí),如果兩個(gè)節(jié)點(diǎn)之間含有換行符(\n)、空字符或者是其他文本內(nèi)容時(shí),將返回這些文本節(jié)點(diǎn)。代碼如下:
#_*_coding:utf-8_*_
#?作者??????:liuxiaowei
#?創(chuàng)建時(shí)間???:2/6/22 8:16 PM
#?文件??????:獲取兄弟節(jié)點(diǎn).py
# IDE ?????:PyCharm
from?bs4?import?BeautifulSoup??#?導(dǎo)入BeautifulSoup庫(kù)
#?創(chuàng)建模擬HTML代碼的字符串
html_doc?=?"""
????關(guān)聯(lián)獲取演示
????
第一個(gè)p節(jié)點(diǎn)下文本Python項(xiàng)目開(kāi)發(fā)案例集錦
"""
#?創(chuàng)建一個(gè)BeautifulSoup對(duì)象,獲取頁(yè)面正文
soup?=?BeautifulSoup(html_doc,?features="lxml")
print(soup.p.next_sibling)???????????????#?打印第一個(gè)p節(jié)點(diǎn)下一個(gè)兄弟節(jié)點(diǎn)(文本節(jié)點(diǎn)內(nèi)容)
print(list(soup.p.next_sibling))?????????#?以列表形式打印文本節(jié)點(diǎn)中的所有元素
div?=?soup.p.next_sibling.next_sibling??#?獲取p節(jié)點(diǎn)同級(jí)的第一個(gè)div節(jié)點(diǎn)
print(div)???????????????????????????????#?打印第一個(gè)div節(jié)點(diǎn)內(nèi)容
print(div.previous_sibling)??????????????#?打印第一個(gè)div節(jié)點(diǎn)上一個(gè)兄弟節(jié)點(diǎn)(文本節(jié)點(diǎn)內(nèi)容)程序運(yùn)行結(jié)果,第一個(gè)p節(jié)點(diǎn)的下一個(gè)兄弟節(jié)點(diǎn):
第一個(gè)p節(jié)點(diǎn)下文本文本節(jié)點(diǎn)中的所有元素
['\n',?'第',?'一',?'個(gè)',?'p',?'節(jié)',?'點(diǎn)',?'下',?'文',?'本',?'\n']第一個(gè)div節(jié)點(diǎn)內(nèi)容
class="div-1"?value="2"><a?href="https://item.jd.com/12451724.html">Python從入門到項(xiàng)目實(shí)踐第一個(gè)div節(jié)點(diǎn)上一個(gè)兄弟節(jié)點(diǎn)
第一個(gè)p節(jié)點(diǎn)下文本如果想獲取當(dāng)前節(jié)點(diǎn)后面的所有兄弟節(jié)點(diǎn)時(shí),可以使用next_siblings屬性。如果想獲取當(dāng)前節(jié)點(diǎn)前面的所有兄弟節(jié)點(diǎn)時(shí)可以使用previsou_siblings屬性。通過(guò)這兩個(gè)屬性所獲取的節(jié)點(diǎn)都將以generator(可迭代對(duì)象)的形式返回。在獲取節(jié)點(diǎn)的內(nèi)容時(shí),同樣可以直接將其轉(zhuǎn)換為list類型或者通過(guò)for循環(huán)遍歷的方式進(jìn)行獲取。這里以轉(zhuǎn)換list類型為例,代碼如下:
print('獲取p節(jié)點(diǎn)后面的所有兄弟節(jié)點(diǎn)如下:\n',?list(soup.p.next_siblings))
print('獲取p節(jié)點(diǎn)前面的所有兄弟節(jié)點(diǎn)如下:\n',?list(soup.p.previous_siblings))程序運(yùn)行結(jié)果如下:
獲取p節(jié)點(diǎn)后面的所有兄弟節(jié)點(diǎn)如下:
?['\n第一個(gè)p節(jié)點(diǎn)下文本\n',?class="div-1"?value="2"><a?href="https://item.jd.com/12451724.html">Python從入門到項(xiàng)目實(shí)踐,?'\n',?p-3"?value="3">12512461.html">Python項(xiàng)目開(kāi)發(fā)案例集錦
,?'\n',?,?'\n']
獲取p節(jié)點(diǎn)前面的所有兄弟節(jié)點(diǎn)如下:
?['\n']使用find()方法獲取內(nèi)容
在HTML代碼中獲取比較復(fù)雜的內(nèi)容時(shí),可以使用find_all()方法與find()方法。調(diào)用這些方法,然后傳入指定的參數(shù)即可靈活的獲取節(jié)點(diǎn)中的內(nèi)容。
find_all()——獲取所有符合條件的內(nèi)容
Beautiful Soup提供了一個(gè)find_all()方法,該方法可以獲取所有符合條件的內(nèi)容。語(yǔ)法格式如下:
find_all(name?=?None,?attrs?=?{},?recursive?=?True,?text?=?None,?limit?=?None,?**kwargs)? 1. name參數(shù)
name參數(shù)用來(lái)指定節(jié)點(diǎn)名稱,指定該參數(shù)以后將返回一個(gè)可迭代對(duì)象,所有符合條件的內(nèi)容均為對(duì)象中的一個(gè)元素。代碼如下:
#_*_coding:utf-8_*_
#?作者??????:liuxiaowei
#?創(chuàng)建時(shí)間???:2/6/22 10:06 PM
#?文件??????:find_all(name)通過(guò)節(jié)點(diǎn)名稱獲取內(nèi)容.py
# IDE ?????:PyCharm
from?bs4?import?BeautifulSoup??#?導(dǎo)入BeautifulSoup庫(kù)
#?創(chuàng)建模擬HTML代碼的字符串
html_doc?=?"""
????關(guān)聯(lián)獲取演示
????Python項(xiàng)目開(kāi)發(fā)案例集錦
"""
#?創(chuàng)建一個(gè)BeautifulSoup對(duì)象,獲取頁(yè)面正文
soup?=?BeautifulSoup(html_doc,?features="lxml")
print(soup.find_all(name='p'))???????????#?打印名稱為p的所有節(jié)點(diǎn)內(nèi)容
print(type(soup.find_all(name='p')))?????#?打印數(shù)據(jù)類型程序運(yùn)行結(jié)果如下:
[class="p-1"?value="1"><a?href="https://item.jd.com/12353915.html">零基礎(chǔ)學(xué)Python
,?p-2"?value="2">12451724.html">Python從入門到項(xiàng)目實(shí)踐
,?p-3"?value="3">12512461.html">Python項(xiàng)目開(kāi)發(fā)案例集錦
]說(shuō) 明
bs4.element.ResultSet類型的數(shù)據(jù)與Python中的列表類似,如果想獲取可迭代對(duì)象中的某條件數(shù)據(jù)可以使用切片的方式進(jìn)行,如獲取所有P節(jié)點(diǎn)中的第一個(gè)可以參考如下代碼:
print(soup.find_all(name='p')[0])???#?打印所有p節(jié)點(diǎn)中的第一個(gè)元素因?yàn)閎s4.element.ResultSet數(shù)據(jù)中的每一個(gè)元素都是bs4.element.Tag類型,所以可以直接對(duì)某一個(gè)元素進(jìn)行嵌套獲取。代碼如下:
print(type(soup.find_all(name='p')[0]))???#?打印數(shù)據(jù)類型
print(soup.find_all(name?=?'p')[0].find_all(name?=?'a'))??#?打印第一個(gè)p節(jié)點(diǎn)內(nèi)的子節(jié)點(diǎn)a程序運(yùn)行結(jié)果如下:
<class?'bs4.element.Tag'>
[<a?href="https://item.jd.com/12353915.html">零基礎(chǔ)學(xué)Python]? 2. attrs參數(shù)
attrs參數(shù)表示通過(guò)指定屬性進(jìn)行數(shù)據(jù)的獲取工作,在填寫attrs參數(shù)時(shí),默認(rèn)情況下需要填寫字典類型的參數(shù)值,但也可以通過(guò)賦值的方式填寫參數(shù)。代碼如下:
#_*_coding:utf-8_*_
#?作者??????:liuxiaowei
#?創(chuàng)建時(shí)間???:2/6/22 10:48 PM
#?文件??????:find_all(attrs)通過(guò)指定屬性獲取內(nèi)容.py
# IDE ?????:PyCharm
from?bs4?import?BeautifulSoup??#?導(dǎo)入BeautifulSoup庫(kù)
import?re??????????????????????#?導(dǎo)入正則表達(dá)式模塊
#?創(chuàng)建模擬HTML代碼的字符串
html_doc?=?"""
????關(guān)聯(lián)獲取演示
????Python項(xiàng)目開(kāi)發(fā)案例集錦
"""
#?創(chuàng)建一個(gè)BeautifulSoup對(duì)象,獲取頁(yè)面正文
soup?=?BeautifulSoup(html_doc,?features="lxml")
print('指定字符串所獲取的內(nèi)容如下:')
print(soup.find_all(text='零基礎(chǔ)學(xué)Python'))?????????#?打印指定字符串所獲取的內(nèi)容
print('指定正則表達(dá)式對(duì)象所獲取的內(nèi)容如下:')
print(soup.find_all(text=re.compile('Python')))????#?打印指定正則表達(dá)式對(duì)象所獲取的內(nèi)容程序運(yùn)行結(jié)果如下:
字典參數(shù)結(jié)果如下:
[class="p-1"?value="1"><a?href="https://item.jd.com/12353915.html">零基礎(chǔ)學(xué)Python
]
賦值參數(shù)結(jié)果如下:
[p-1"?value="1">12353915.html">零基礎(chǔ)學(xué)Python
,?p-1"?value="2">12451724.html">Python從入門到項(xiàng)目實(shí)踐
]
[p-3"?value="3">12512461.html">Python項(xiàng)目開(kāi)發(fā)案例集錦
]? 3. text參數(shù)
指定text參數(shù)可以獲取節(jié)點(diǎn)中的文本,該參數(shù)可以指定字符串或者正則表達(dá)式對(duì)象。代碼如下:
#_*_coding:utf-8_*_
#?作者??????:liuxiaowei
#?創(chuàng)建時(shí)間???:2/6/22 10:48 PM
#?文件??????:find_all(attrs)通過(guò)指定屬性獲取內(nèi)容.py
# IDE ?????:PyCharm
from?bs4?import?BeautifulSoup??#?導(dǎo)入BeautifulSoup庫(kù)
import?re??????????????????????#?導(dǎo)入正則表達(dá)式模塊
#?創(chuàng)建模擬HTML代碼的字符串
html_doc?=?"""
????關(guān)聯(lián)獲取演示
????Python項(xiàng)目開(kāi)發(fā)案例集錦
"""
#?創(chuàng)建一個(gè)BeautifulSoup對(duì)象,獲取頁(yè)面正文
soup?=?BeautifulSoup(html_doc,?features="lxml")
print('指定字符串所獲取的內(nèi)容如下:')
print(soup.find_all(text='零基礎(chǔ)學(xué)Python'))?????????#?打印指定字符串所獲取的內(nèi)容
print('指定正則表達(dá)式對(duì)象所獲取的內(nèi)容如下:')
print(soup.find_all(text=re.compile('Python')))????#?打印指定正則表達(dá)式對(duì)象所獲取的內(nèi)容程序運(yùn)行結(jié)果如下:
指定字符串所獲取的內(nèi)容如下:
['零基礎(chǔ)學(xué)Python']
指定正則表達(dá)式對(duì)象所獲取的內(nèi)容如下:
['零基礎(chǔ)學(xué)Python',?'Python從入門到項(xiàng)目實(shí)踐',?'Python項(xiàng)目開(kāi)發(fā)案例集錦',?'Python編程錦囊']find()——獲取第一個(gè)匹配的節(jié)點(diǎn)內(nèi)容
find_all()方法可以獲取所有符合條件的節(jié)點(diǎn)內(nèi)容,而find()方法只能獲取第一個(gè)匹配的節(jié)點(diǎn)內(nèi)容。
代碼如下:
#_*_coding:utf-8_*_
#?作者??????:liuxiaowei
#?創(chuàng)建時(shí)間???:2/6/22 11:14 PM
#?文件??????:find()方法獲取第一個(gè)匹配的節(jié)點(diǎn)內(nèi)容.py
# IDE ?????:PyCharm
from?bs4?import?BeautifulSoup??#?導(dǎo)入BeautifulSoup庫(kù)
import?re??????????????????????#?導(dǎo)入正則表達(dá)式模塊
#?創(chuàng)建模擬HTML代碼的字符串
html_doc?=?"""
????關(guān)聯(lián)獲取演示
????Python項(xiàng)目開(kāi)發(fā)案例集錦
"""
#?創(chuàng)建一個(gè)BeautifulSoup對(duì)象,獲取頁(yè)面正文
soup?=?BeautifulSoup(html_doc,?features="lxml")
print(soup.find(name='p'))??????????????????#?打印第一個(gè)name為p的節(jié)點(diǎn)內(nèi)容
print(soup.find(class_='p-3'))??????????????#?打印第一個(gè)class為p-3的節(jié)點(diǎn)內(nèi)容
print(soup.find(attrs={'value':'4'}))???????#?打印第一個(gè)value為4的節(jié)點(diǎn)內(nèi)容
print(soup.find(text=re.compile('Python')))?#?打印第一個(gè)文本中包含Python的文本信息程序運(yùn)行結(jié)果如下:
class="p-1"?value="1"><a?href="https://item.jd.com/12353915.html">零基礎(chǔ)學(xué)Python
p-3"?value="3">12512461.html">Python項(xiàng)目開(kāi)發(fā)案例集錦
零基礎(chǔ)學(xué)Python? 其他方法
除了find_all()和find()方法可以實(shí)現(xiàn)按照指定條件獲取節(jié)點(diǎn)內(nèi)容以外,Beautiful Soup模塊還提供了多個(gè)其他方法,這些方法的使用方式與find_all()和find()方法相同,只是查詢的范圍不同,各個(gè)方法的具體說(shuō)明如下:
根據(jù)條件獲取節(jié)點(diǎn)內(nèi)容的其他方法及描述
方 法 名 稱 描 ?述 find_parent() 獲取父節(jié)點(diǎn)內(nèi)容 find_parents() 獲取所有祖先節(jié)點(diǎn)內(nèi)容 find_next_sibling() 獲取后面第一個(gè)兄弟節(jié)點(diǎn)內(nèi)容 find_previous_siblings() 獲取前面第一個(gè)兄弟節(jié)點(diǎn)內(nèi)容 find_next_siblings() 獲取后面所有兄弟節(jié)點(diǎn)內(nèi)容 find_previous_siblings() 獲取前面所有兄弟節(jié)點(diǎn)內(nèi)容 find_next() 獲取當(dāng)前節(jié)點(diǎn)的下一個(gè)符合條件的節(jié)點(diǎn)內(nèi)容 find_all_next() 獲取當(dāng)前節(jié)點(diǎn)的下一個(gè)所有符合條件的節(jié)點(diǎn)內(nèi)容 find_previous() 獲取第一個(gè)符合條件的節(jié)點(diǎn)內(nèi)容 find_all_previous() 獲取所有符合條件的節(jié)點(diǎn)內(nèi)容 CSS選擇器
Beautiful Soup模塊還提供了CSS選擇器來(lái)獲取節(jié)點(diǎn)內(nèi)容,如果是Tag或者是Beautiful Soup對(duì)象都可以直接調(diào)用select()方法,然后填寫指定參數(shù)即可通過(guò)CSS選擇器獲取到節(jié)點(diǎn)中的內(nèi)容。
說(shuō) 明
CSS選擇器參考手冊(cè)
https://www.w3school.com.cn/cssref/css_selectors.asp
在使用CSS選擇器獲取節(jié)點(diǎn)內(nèi)容時(shí),首先需要調(diào)用select()方法,然后為其指定字符串類型的CSS選擇器。常見(jiàn)的CSS選擇器如下:
§ 直接填寫字符串類型的節(jié)點(diǎn)名稱
§ .class:表示指定class屬性值
§ #id:表示指定id屬性的值
使用CSS選擇器調(diào)用select()方法獲取節(jié)點(diǎn)內(nèi)容
示例代碼如下:
#_*_coding:utf-8_*_
#?作者??????:liuxiaowei
#?創(chuàng)建時(shí)間???:2/7/22 6:12 AM
#?文件??????:使用CSS選擇器獲取節(jié)點(diǎn)內(nèi)容.py
# IDE ?????:PyCharm
from?bs4?import?BeautifulSoup??#?導(dǎo)入BeautifulSoup庫(kù)
#?創(chuàng)建模擬HTML代碼的字符串
html_doc?=?"""
????關(guān)聯(lián)獲取演示
????
????
????????
????????
????????
????????
????
"""
#?創(chuàng)建一個(gè)BeautifulSoup對(duì)象,獲取頁(yè)面正文
soup?=?BeautifulSoup(html_doc,?features="lxml")
print('所有p節(jié)點(diǎn)內(nèi)容如下:')
print(soup.select('p'))????????????????#?打印所有p節(jié)點(diǎn)內(nèi)容
print('所有p節(jié)點(diǎn)中的第二個(gè)p節(jié)點(diǎn)內(nèi)容如下:')
print(soup.select('p')[1])?????????????#?打印所有p節(jié)點(diǎn)中的第二個(gè)p節(jié)點(diǎn)
print('逐層獲取的title節(jié)點(diǎn)如下:')
print(soup.select('html?head?title'))??#?打印逐層獲取的title節(jié)點(diǎn)
print('類名為test_2所對(duì)應(yīng)的節(jié)點(diǎn)如下:')
print(soup.select('.test_2'))??????????#?打印類名為test_2所對(duì)應(yīng)的節(jié)點(diǎn)
print('id值為class_1所對(duì)應(yīng)的節(jié)點(diǎn)如下:')
print(soup.select('#class_1'))?????????#?打印id值為class_1所對(duì)應(yīng)的節(jié)點(diǎn)程序運(yùn)行結(jié)果如下:
所有p節(jié)點(diǎn)內(nèi)容如下:
[class="p-1"?value="1"><a?href="https://item.jd.com/12353915.html">零基礎(chǔ)學(xué)Python
,?p-2"?value="2">12451724.html">Python從入門到項(xiàng)目實(shí)踐
,?p-3"?value="3">12512461.html">Python項(xiàng)目開(kāi)發(fā)案例集錦
,?p-4"?value="4">12550531.html">Python編程錦囊
,?p-5">12185501.html">零基礎(chǔ)學(xué)Java(全彩版)
,?p-6">12199033.html">零基礎(chǔ)學(xué)Android(全彩版)
,?p-7">12250414.html">零基礎(chǔ)學(xué)C語(yǔ)言(全彩版)
]
所有p節(jié)點(diǎn)中的第二個(gè)p節(jié)點(diǎn)內(nèi)容如下:p-2"?value="2">12451724.html">Python從入門到項(xiàng)目實(shí)踐
逐層獲取的title節(jié)點(diǎn)如下:
[關(guān)聯(lián)獲取演示 ]
類名為test_2所對(duì)應(yīng)的節(jié)點(diǎn)如下:
[test_2"?id="class_2">]p-5">12185501.html">零基礎(chǔ)學(xué)Java(全彩版)
p-6">12199033.html">零基礎(chǔ)學(xué)Android(全彩版)
p-7">12250414.html">零基礎(chǔ)學(xué)C語(yǔ)言(全彩版)
id值為class_1所對(duì)應(yīng)的節(jié)點(diǎn)如下:
[test_1"?id="class_1">]p-1"?value="1">12353915.html">零基礎(chǔ)學(xué)Python
p-2"?value="2">12451724.html">Python從入門到項(xiàng)目實(shí)踐
p-3"?value="3">12512461.html">Python項(xiàng)目開(kāi)發(fā)案例集錦
p-4"?value="4">12550531.html">Python編程錦囊
select()方法除了以上的基本使用方法以外,還可以實(shí)現(xiàn)嵌套獲取、獲取屬性值以及獲取文本等。
根據(jù)條件獲取節(jié)點(diǎn)內(nèi)容的其他方法及描述
獲取節(jié)點(diǎn)內(nèi)容的方式 描 ? 述 soup.select('div[class="test_1"]')[0].
select('p')[0]嵌套獲取class名為test_1對(duì)應(yīng)的div中所有p節(jié)點(diǎn)中的第一個(gè) soup.select('p')[0]['value']
soup.select('p')[0].attrs['value']獲取所有p節(jié)點(diǎn)中第一個(gè)節(jié)點(diǎn)內(nèi)value屬性對(duì)應(yīng)的值(兩種方式) soup.select('p')[0].get_text()
soup.select('p')[0].string獲取所有p節(jié)點(diǎn)中第一個(gè)節(jié)點(diǎn)內(nèi)的文本(兩種方式) soup.select('p'([1:]) 獲取所有p節(jié)點(diǎn)中第二個(gè)以后的p節(jié)點(diǎn) soup.select('.p-1, .p-5') 獲取class名為p-1與p-5對(duì)應(yīng)的節(jié)點(diǎn) soup.select('a[href]') 獲取存在href屬性的所有a節(jié)點(diǎn) soup.select('p[value = "1"]') 獲取所有屬性值為value = "1"的p節(jié)點(diǎn) 說(shuō) 明
Beautiful Soup 模塊還提供了一個(gè)select_one()方法,用于獲取所有符合條件節(jié)點(diǎn)的第一個(gè)節(jié)點(diǎn),例如soup.select_one('a')將獲取所有a節(jié)點(diǎn)中的第一個(gè)a節(jié)點(diǎn)內(nèi)容。
總 結(jié)

- class="test3"?value="user1234">
- class="test3"?value="user1234">
