一、BeautifulSoup簡介
BeautifulSoup是Python爬蟲應用解析Html的利器,是Python三方模塊bs4中提供的進行HTML解析的類,可以認為是一個HTML解析工具箱,對HTML報文中的標簽具有比較好的容錯識別功能。lxml是一款html文本解析器,BeautifulSoup構建對象時需要指定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報文的常用功能:
通過BeautifulSoup對象可以訪問標簽對應的html元素、并進一步訪問標簽的名字、屬性、html元素標簽對中的內容。
案例:
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’])
通過標簽的contents屬性,可以訪問其下嵌套的所有下級HTML元素,這些該標簽下的子標簽對應的HTML元素放到一個contents 指向的列表中。
如:print(soup.body.contents)
可以訪問標簽對應的父、子、兄弟及祖先標簽信息;
使用strings屬性迭代訪問除標簽外的所有內容;
可以使用find、find_all、find_parent、find_parents等系列方法查找滿足特定條件的標簽;
使用select通過css選擇器定位特定標簽。
具體的大家可以參考老猿博客的免費專欄《爬蟲:https://blog.csdn.net/laoyuanpython/category_9103810.html》或付費專欄《Python爬蟲入門:https://blog.csdn.net/laoyuanpython/category_10762553.html》的相關介紹。
二、一些解析技巧
在HTML解析時,如果通過簡單的tag、或單個tag屬性(如id、class)或文本一次搜索或select定位是最簡單的,而有些情況需要使用組合方法才能處理。
2.1、通過標簽的多個屬性組合定位或查找
經常有些要定位的標簽有很多,按單個屬性查找也有很多,得使用多個屬性查找。如:
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文本中有多個id為article_content的div標簽,如果使用:
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》》》
就會返回兩條記錄。這時候就可以使用多標簽屬性定位的如下4種語句:
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_=‘article_content clearfix’)
6[《div class=“article_content clearfix” id=“article_content”》。。.。。.《/div》]
7》》》s.find_all(“div”,“#article_content”,class_=‘article_content clearfix’)
8[《div class=“article_content clearfix” id=“article_content”》。。.。。.《/div》]
以上四種方式是等價的,因為id可以用#來標記,class在查找時需要和Python關鍵字class區分,因此有上述不同方法,注意select的每個屬性必須用中括號括起來,不同屬性的中括號之間不能有空格,如果有空格表示的就不是查找同一標簽的屬性,空格后的屬性表示前一個屬性對應標簽的子孫標簽的屬性。
2.2、利用tag標簽關系定位內容
tag標簽關系包括父子、兄弟、祖先等關系,有時要查找或定位的內容本身不是很好定位,但結合其他標簽關系(主要是父子、祖先關系)則可以唯一確認。
案例:
這是CSDN的博文中關于博主個人信息的部分報文:
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”》原創《/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》
以上報文中,如果要取博主的原創文章數和周排名,原創文章數和博主周排名的tag標簽完全相同,二者都在span標簽內,標簽的屬性及值都相同,只是span標簽的父標簽dt標簽的兄弟標簽dd標簽的string的中文內容才能區分。對于這種情況,首先要通過祖先標簽《div class=“data-info d-flex item-tiling”》定位到祖先標簽,再在祖先標簽內通過中文字符串定位到要訪問屬性的兄弟標簽的子標簽,然后通過該子標簽找到其父標簽的父標簽,再通過該父標簽的dt子標簽的span子標簽訪問具體取值。
示例代碼如下:
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“》原創《/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==‘原創’:
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使用的也是標簽的屬性來定位標簽,并且兩個中括號之間有空格,表明后一個要查找的標簽在前一個屬性對應標簽的子孫標簽范圍內。
2.3、分析前去除程序代碼避免干擾
在解析HTML報文時,絕大多數情況是需要分析有用的標簽信息,但作為技術文章,大部分的博文中都有代碼,這些代碼可能會對分析進行干擾。如本文中的代碼含有一些分析的HTML報文,如果獲取本文的完整HTML內容,這些報文在非代碼部分也會出現,此時要排除代碼的影響,可以將代碼先從分析內容中去除再來分析。
目前大多數技術平臺的博文編輯器都支持對代碼的標識,象markdown等編輯器代碼的標簽為code標檢,如果有其他編輯器用不同標簽的,只有確認了標簽名,都可以按下面介紹的類似方式來處理。
處理步驟如下:
獲取報文;
構建BeatifulSoap對象soup;
通過soup.code.extract()或soup.code.decompose()方式就從soup對象中去除了代碼部分,decompose方法與extract方法的區別就是decompose直接刪除對應對象數據而extract再刪除時將刪除對象單獨返回。
關于這部分內容的案例可以參考《https://blog.csdn.net/LaoYuanPython/article/details/114729045 n行Python代碼系列:四行程序分離HTML報文中的程序代碼》的詳細介紹。
三、小結
本文介紹了使用BeatifulSoap解析HTML報文的三個使用技巧,包括通過多屬性組合查找或定位標簽、通過結合多個標簽關系來定位標簽以及去除html報文中的代碼標簽來避免代碼對解析的影響。
編輯:lyn
-
HTML
+關注
關注
0文章
278瀏覽量
36152 -
python
+關注
關注
56文章
4807瀏覽量
84952
發布評論請先 登錄
相關推薦
評論