一、BeautifulSoup簡(jiǎn)介
BeautifulSoup是Python爬蟲(chóng)應(yīng)用解析Html的利器,是Python三方模塊bs4中提供的進(jìn)行HTML解析的類(lèi),可以認(rèn)為是一個(gè)HTML解析工具箱,對(duì)HTML報(bào)文中的標(biāo)簽具有比較好的容錯(cuò)識(shí)別功能。lxml是一款html文本解析器,BeautifulSoup構(gòu)建對(duì)象時(shí)需要指定HTML解析器,推薦使用lxml。
BeautifulSoup和lxml安裝命令:
1pip install -i https://pypi.tuna.tsinghua.edu.cn/simple bs4
2pip install -i https://pypi.tuna.tsinghua.edu.cn/simple lxml
加載BeautifulSoup:
1from bs4 import BeautifulSoup
BeatifulSoap解析HTML報(bào)文的常用功能:
通過(guò)BeautifulSoup對(duì)象可以訪(fǎng)問(wèn)標(biāo)簽對(duì)應(yīng)的html元素、并進(jìn)一步訪(fǎng)問(wèn)標(biāo)簽的名字、屬性、html元素標(biāo)簽對(duì)中的內(nèi)容。
案例:
1from bs4 import BeautifulSoup
2import urllib.request
3def getURLinf(url):
4header = {‘User-Agent’: ‘Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36’}
5req = urllib.request.Request(url=url,headers=header)
6resp = urllib.request.urlopen(req,timeout=5)
7html = resp.read().decode()
8soup = BeautifulSoup(html,‘lxml’)
9return (soup,req,resp)
10soup,req ,resp = getURLinf(r‘https://blog.csdn.net/LaoYuanPython/article/details/111303395’)
11print(soup.p)
12print(soup.link)
13print(soup.title)
14print(soup.link.attrs)
15print(soup.link[‘rel’])
通過(guò)標(biāo)簽的contents屬性,可以訪(fǎng)問(wèn)其下嵌套的所有下級(jí)HTML元素,這些該標(biāo)簽下的子標(biāo)簽對(duì)應(yīng)的HTML元素放到一個(gè)contents 指向的列表中。
如:print(soup.body.contents)
可以訪(fǎng)問(wèn)標(biāo)簽對(duì)應(yīng)的父、子、兄弟及祖先標(biāo)簽信息;
使用strings屬性迭代訪(fǎng)問(wèn)除標(biāo)簽外的所有內(nèi)容;
可以使用find、find_all、find_parent、find_parents等系列方法查找滿(mǎn)足特定條件的標(biāo)簽;
使用select通過(guò)css選擇器定位特定標(biāo)簽。
具體的大家可以參考老猿博客的免費(fèi)專(zhuān)欄《爬蟲(chóng):https://blog.csdn.net/laoyuanpython/category_9103810.html》或付費(fèi)專(zhuān)欄《Python爬蟲(chóng)入門(mén):https://blog.csdn.net/laoyuanpython/category_10762553.html》的相關(guān)介紹。
二、一些解析技巧
在HTML解析時(shí),如果通過(guò)簡(jiǎn)單的tag、或單個(gè)tag屬性(如id、class)或文本一次搜索或select定位是最簡(jiǎn)單的,而有些情況需要使用組合方法才能處理。
2.1、通過(guò)標(biāo)簽的多個(gè)屬性組合定位或查找
經(jīng)常有些要定位的標(biāo)簽有很多,按單個(gè)屬性查找也有很多,得使用多個(gè)屬性查找。如:
1《div id=“article_content” class=“article_content clearfix”》
2。。.。。.
3《/div》
4《div id=“article_content” class=“article_view”》
5。。.。。.
6《/div》
7《div id=“article_view” class=“article_view”》
8。。.。。.
9《/div》
上面的html文本中有多個(gè)id為article_content的div標(biāo)簽,如果使用:
1》》》 text=“”“```html
2《div id=”article_content“ class=”article_content clearfix“》
3。。.。。.
4《/div》
5《div id=”article_content“ class=”article_view“》
6。。.。。.
7《/div》
8《div id=”article_view“ class=”article_view“》
9。。.。。.
10《/div》”“”
11》》》 s = BeautifulSoup(text,‘lxml’)
12》》》 s.select(‘div#article_content’)
13[《div class=“article_content clearfix” id=“article_content”》。。.。。.《/div》,
14《div class=“article_view” id=“article_content”》。。.。。.《/div》]
15》》》
就會(huì)返回兩條記錄。這時(shí)候就可以使用多標(biāo)簽屬性定位的如下4種語(yǔ)句:
1》》》s.select(‘div#article_content[class=“article_content clearfix”]’)
2[《div class=“article_content clearfix” id=“article_content”》。。.。。.《/div》]
3》》》s.select(‘div[id=“article_content”][class=“article_content clearfix”]’)
4[《div class=“article_content clearfix” id=“article_content”》。。.。。.《/div》]
5》》》s.find_all(“div”,id=“article_content”,class_=‘a(chǎn)rticle_content clearfix’)
6[《div class=“article_content clearfix” id=“article_content”》。。.。。.《/div》]
7》》》s.find_all(“div”,“#article_content”,class_=‘a(chǎn)rticle_content clearfix’)
8[《div class=“article_content clearfix” id=“article_content”》。。.。。.《/div》]
以上四種方式是等價(jià)的,因?yàn)閕d可以用#來(lái)標(biāo)記,class在查找時(shí)需要和Python關(guān)鍵字class區(qū)分,因此有上述不同方法,注意select的每個(gè)屬性必須用中括號(hào)括起來(lái),不同屬性的中括號(hào)之間不能有空格,如果有空格表示的就不是查找同一標(biāo)簽的屬性,空格后的屬性表示前一個(gè)屬性對(duì)應(yīng)標(biāo)簽的子孫標(biāo)簽的屬性。
2.2、利用tag標(biāo)簽關(guān)系定位內(nèi)容
tag標(biāo)簽關(guān)系包括父子、兄弟、祖先等關(guān)系,有時(shí)要查找或定位的內(nèi)容本身不是很好定位,但結(jié)合其他標(biāo)簽關(guān)系(主要是父子、祖先關(guān)系)則可以唯一確認(rèn)。
案例:
這是CSDN的博文中關(guān)于博主個(gè)人信息的部分報(bào)文:
1《div class=“data-info d-flex item-tiling”》
2《dl class=“text-center” title=“1055”》
3《a href=“https://blog.csdn.net/LaoYuanPython” data-report-click=‘{“mod”:“1598321000_001”,“spm”:“1001.2101.3001.4310”}’ data-report-query=“t=1”》
4《dt》《span class=“count”》1055《/span》《/dt》
5《dd class=“font”》原創(chuàng)《/dd》
6《/a》
7《/dl》
8《dl class=“text-center” data-report-click=‘{“mod”:“1598321000_002”,“spm”:“1001.2101.3001.4311”}’ title=“22”》
9《a href=“https://blog.csdn.net/rank/writing_rank” target=“_blank”》
10《dt》《span class=“count”》22《/span》《/dt》
11《dd class=“font”》周排名《/dd》
12《/a》
13《/dl》
14《/div》
以上報(bào)文中,如果要取博主的原創(chuàng)文章數(shù)和周排名,原創(chuàng)文章數(shù)和博主周排名的tag標(biāo)簽完全相同,二者都在span標(biāo)簽內(nèi),標(biāo)簽的屬性及值都相同,只是span標(biāo)簽的父標(biāo)簽dt標(biāo)簽的兄弟標(biāo)簽dd標(biāo)簽的string的中文內(nèi)容才能區(qū)分。對(duì)于這種情況,首先要通過(guò)祖先標(biāo)簽《div class=“data-info d-flex item-tiling”》定位到祖先標(biāo)簽,再在祖先標(biāo)簽內(nèi)通過(guò)中文字符串定位到要訪(fǎng)問(wèn)屬性的兄弟標(biāo)簽的子標(biāo)簽,然后通過(guò)該子標(biāo)簽找到其父標(biāo)簽的父標(biāo)簽,再通過(guò)該父標(biāo)簽的dt子標(biāo)簽的span子標(biāo)簽訪(fǎng)問(wèn)具體取值。
示例代碼如下:
1》》》 text=“”“
2《div class=”data-info d-flex item-tiling“》
3《dl class=”text-center“ title=”1055“》
4《a href=”https://blog.csdn.net/LaoYuanPython“ data-report-click=‘{”mod“:”1598321000_001“,”spm“:”1001.2101.3001.4310“}’ data-report-query=”t=1“》
5《dt》《span class=”count“》1055《/span》《/dt》
6《dd class=”font“》原創(chuàng)《/dd》
7《/a》
8《/dl》
9《dl class=”text-center“ data-report-click=‘{”mod“:”1598321000_002“,”spm“:”1001.2101.3001.4311“}’ title=”22“》
10《a href=”https://blog.csdn.net/rank/writing_rank“ target=”_blank“》
11《dt》《span class=”count“》22《/span》《/dt》
12《dd class=”font“》周排名《/dd》
13《/a》
14《/dl》
15《/div》”“”
16》》》 s = BeautifulSoup(text,‘lxml’)
17》》》 subSoup = s.select(‘[class=“data-info d-flex item-tiling”] [class=“font”]’)
18》》》 for item in subSoup:
19parent = item.parent
20if item.string==‘原創(chuàng)’:
21orignalNum = int(parent.select(‘.count’)[0].string)
22elif item.string==‘周排名’:
23weekRank = int(parent.select(‘.count’)[0].string)
24》》》 print(orignalNum,weekRank)
251055 22
26》》》
注意:上面的select使用的也是標(biāo)簽的屬性來(lái)定位標(biāo)簽,并且兩個(gè)中括號(hào)之間有空格,表明后一個(gè)要查找的標(biāo)簽在前一個(gè)屬性對(duì)應(yīng)標(biāo)簽的子孫標(biāo)簽范圍內(nèi)。
2.3、分析前去除程序代碼避免干擾
在解析HTML報(bào)文時(shí),絕大多數(shù)情況是需要分析有用的標(biāo)簽信息,但作為技術(shù)文章,大部分的博文中都有代碼,這些代碼可能會(huì)對(duì)分析進(jìn)行干擾。如本文中的代碼含有一些分析的HTML報(bào)文,如果獲取本文的完整HTML內(nèi)容,這些報(bào)文在非代碼部分也會(huì)出現(xiàn),此時(shí)要排除代碼的影響,可以將代碼先從分析內(nèi)容中去除再來(lái)分析。
目前大多數(shù)技術(shù)平臺(tái)的博文編輯器都支持對(duì)代碼的標(biāo)識(shí),象markdown等編輯器代碼的標(biāo)簽為code標(biāo)檢,如果有其他編輯器用不同標(biāo)簽的,只有確認(rèn)了標(biāo)簽名,都可以按下面介紹的類(lèi)似方式來(lái)處理。
處理步驟如下:
獲取報(bào)文;
構(gòu)建BeatifulSoap對(duì)象soup;
通過(guò)soup.code.extract()或soup.code.decompose()方式就從soup對(duì)象中去除了代碼部分,decompose方法與extract方法的區(qū)別就是decompose直接刪除對(duì)應(yīng)對(duì)象數(shù)據(jù)而extract再刪除時(shí)將刪除對(duì)象單獨(dú)返回。
關(guān)于這部分內(nèi)容的案例可以參考《https://blog.csdn.net/LaoYuanPython/article/details/114729045 n行Python代碼系列:四行程序分離HTML報(bào)文中的程序代碼》的詳細(xì)介紹。
三、小結(jié)
本文介紹了使用BeatifulSoap解析HTML報(bào)文的三個(gè)使用技巧,包括通過(guò)多屬性組合查找或定位標(biāo)簽、通過(guò)結(jié)合多個(gè)標(biāo)簽關(guān)系來(lái)定位標(biāo)簽以及去除html報(bào)文中的代碼標(biāo)簽來(lái)避免代碼對(duì)解析的影響。
編輯:lyn
-
HTML
+關(guān)注
關(guān)注
0文章
277瀏覽量
34164 -
python
+關(guān)注
關(guān)注
55文章
4767瀏覽量
84375
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論