大家好,上篇推文介紹了爬蟲方面需要注意的地方、使用vscode開發(fā)環(huán)境的時(shí)候會(huì)遇到的問題以及使用正則表達(dá)式的方式爬取頁面信息,本篇內(nèi)容主要是介紹BeautifulSoup模塊的使用教程。
一、BeautifulSoup介紹
引用官方的解釋:
Beautiful Soup 是一個(gè)可以從HTML或XML文件中提取數(shù)據(jù)的Python庫.它能夠通過你喜歡的轉(zhuǎn)換器實(shí)現(xiàn)慣用的文檔導(dǎo)航,查找,修改文檔的方式.
簡單來說Beautiful Soup是python的一個(gè)庫,是一個(gè)可以從網(wǎng)頁抓取數(shù)據(jù)的利器。
官方文檔:
https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/
二、BeautifulSoup安裝
pip install beautifulsoup4
或
pip install beautifulsoup4
-i http://pypi.douban.com/simple/
--trusted-host http://pypi.douban.com
順便說一句:我使用的開發(fā)工具還是vscode,不清楚的看一下之前的推文。
三、BeautifulSoup解析器

3.1 html.parse
html.parse 是內(nèi)置的不需要安裝的
import requests
from bs4 import BeautifulSoup
url='https://www.baidu.com'
response=requests.get(url)
response.encoding = 'utf-8'
soup = BeautifulSoup(response.text, 'html.parser')
print(soup.prettify())
結(jié)果

3.2 lxml
lxml 是需要安裝 pip install lxml
import requests
from bs4 import BeautifulSoup
url='https://www.baidu.com'
response=requests.get(url)
response.encoding = 'utf-8'
soup = BeautifulSoup(response.text, 'lxml')
print(soup)
結(jié)果

3.3 lxml-xml/xml
lxml-xml/Xm是需要安裝的 pip install lxml
import requests
from bs4 import BeautifulSoup
url='https://www.baidu.com'
response=requests.get(url)
response.encoding = 'utf-8'
soup = BeautifulSoup(response.text, 'xml')
print(soup)
結(jié)果

3.4 html5lib
html5lib 是需要安裝的 pip install html5lib
import requests
from bs4 import BeautifulSoup
url='https://www.baidu.com'
response=requests.get(url)
response.encoding = 'utf-8'
soup = BeautifulSoup(response.text, 'html5lib')
print(soup)
結(jié)果

大家看到這幾個(gè)解析器解析出來的記過基本上都是一樣,但是如果一段HTML或XML文檔格式不正確的話,那么在不同的解析器中返回的結(jié)果可能是不一樣的。什么叫HTML或XML文檔格式不正確,簡單的來說就是缺少不必要的標(biāo)簽或者標(biāo)簽沒有閉合,比如頁面缺少body標(biāo)簽、只有a標(biāo)簽開始的部分<a>缺少a標(biāo)簽結(jié)束的部分</a>(這里是一些前端的知識(shí),不明白的可以搜索一下,很簡單)。
我們來嘗試一下
from bs4 import BeautifulSoup
html="<body><div><a href=''>Python知識(shí)學(xué)堂</div></body>"
soup = BeautifulSoup(html, 'html.parser')
print("html.parser 結(jié)果:")
print(soup)
soup1 = BeautifulSoup(html, 'lxml')
print("lxml 結(jié)果:")
print(soup1)
soup2 = BeautifulSoup(html, 'xml')
print("xml 結(jié)果:")
print(soup2)
soup3 = BeautifulSoup(html, 'html5lib')
print("html5lib 結(jié)果:")
print(soup3)
結(jié)果

可以看出html.parser與lxml 差不多的 都會(huì)給標(biāo)簽補(bǔ)齊,但lxml會(huì)把html 標(biāo)簽給補(bǔ)齊,xml也會(huì)給標(biāo)簽補(bǔ)齊,而且還會(huì)加上xml文檔的版本編碼方式等信息,但是不會(huì)把html標(biāo)簽補(bǔ)齊,html5lib 也會(huì)補(bǔ)齊不但補(bǔ)齊了html標(biāo)簽而且給整個(gè)頁面補(bǔ)齊head 標(biāo)簽。
這就驗(yàn)證了上面表格上的html5lib 的容錯(cuò)性最好,但是html5lib 解析器的速度不快,內(nèi)容比較少的話是比較不出速度的差別的,所以推薦使用lxml作為解析器,因?yàn)樾矢? 在Python2.7.3之前的版本和Python3中3.2.2之前的版本,必須安裝lxml或html5lib, 因?yàn)槟切㏄ython版本的標(biāo)準(zhǔn)庫中內(nèi)置的HTML解析方法不夠穩(wěn)定.
如果我們不指定解析器會(huì)怎么樣?
from bs4 import BeautifulSoup
html="<body><div><a href=''>Python知識(shí)學(xué)堂</div></body>"
soup = BeautifulSoup(html)
print("html.parser 結(jié)果:")
print(soup)
結(jié)果

從結(jié)果提示可以得出,不指定解析器的話,他會(huì)給出系統(tǒng)最好的解析器,我的系統(tǒng)是lxml,如果你在別的環(huán)境沒有安裝lxml的話,可能會(huì)是別的解析器,總之系統(tǒng)會(huì)給你選擇一個(gè)默認(rèn)最好的解析器給你,所以你可以不指定,這還不是比較人性化的吧。
四、BeautifulSoup對象種類
Beautiful Soup將復(fù)雜HTML文檔轉(zhuǎn)換成一個(gè)復(fù)雜的樹形結(jié)構(gòu),每個(gè)節(jié)點(diǎn)都是Python對象,所有對象可以歸納為4種: Tag , NavigableString , BeautifulSoup , Comment .
4.1 tag
tag中最重要的屬性: name和attributes
from bs4 import BeautifulSoup
html="<body><div><a data-id='234' href='' class='hyyh'>Python知識(shí)學(xué)堂</div><test>Python知識(shí)學(xué)堂</test></body>"
soup = BeautifulSoup(html,'lxml')
tag=soup.a #a標(biāo)簽就相當(dāng)于一個(gè)標(biāo)簽
tag.name
print(tag.name)
tag=soup.test #test 也是算是標(biāo)簽
tag.name
print(tag.name)
結(jié)果

上面的代碼中的a標(biāo)簽就是表示一個(gè)tag,而且test也算是一個(gè)標(biāo)簽,test是我隨便寫的,所以Beautiful Soup中html標(biāo)簽和自定義的標(biāo)簽都是可以當(dāng)作是tag,是不是很強(qiáng)大!
那么什么是attributes呢?看上面的代碼 a 標(biāo)簽中的data-id與class這個(gè)就算是標(biāo)簽中的屬性;
from bs4 import BeautifulSoup
html="<body><div><a data-id='234' href='' class='hyyh'>Python知識(shí)學(xué)堂</div><test/></body>"
soup = BeautifulSoup(html,'lxml')
tag=soup.a
print(tag.attrs)
結(jié)果:

如果要獲取某一個(gè)屬性,可以使用tag['data-id']或tag.attrs['data-id'] 都是可以的。
這個(gè)用處最多的應(yīng)該是獲取a標(biāo)簽的鏈接地址以及img標(biāo)簽的媒體文件地址等。
如果屬于里有多個(gè)值的話會(huì)返回一個(gè)list
from bs4 import BeautifulSoup
html="<body><div><a data-id='知識(shí)學(xué)堂 python' href='' class='hyyh'>Python知識(shí)學(xué)堂</div><test/></body>"
soup = BeautifulSoup(html,'lxml')
print(tag['data-id'])
結(jié)果:

4.2 NavigableString
包含在tag內(nèi)的字符串可以用NavigableString類來直接獲取,也叫可以遍歷的字符串。
from bs4 import BeautifulSoup
html="<body><div><a href=''>Python知識(shí)學(xué)堂,歡迎你!</div><test/></body>"
soup = BeautifulSoup(html,'lxml')
tag=soup.a
print(tag.string)
結(jié)果:

這個(gè)比較簡單,就不再多說了;
4.3 BeautifulSoup
BeautifulSoup 對象表示的是一個(gè)文檔的全部內(nèi)容.大部分時(shí)候,可以把它當(dāng)作 Tag 對象,它支持 遍歷文檔樹 和 搜索文檔樹 中描述的大部分的方法.
先大概了解一下,在后面遍歷文檔、搜索文檔會(huì)有描述;
4.4 Comment
主要是文檔中的注釋部分。
Comment 對象是一個(gè)特殊類型的 NavigableString 對象:
from bs4 import BeautifulSoup
html= "<b><!--python 知識(shí)學(xué)堂 --></b>"
soup = BeautifulSoup(html,'lxml')
comment = soup.b.string
print(comment)
結(jié)果

不過下面這種情況是獲取不到的
from bs4 import BeautifulSoup
html= "<b>我是誰?<!--python 知識(shí)學(xué)堂 --></b>"
soup = BeautifulSoup(html,'lxml')
comment = soup.b.string
print(comment)
結(jié)果

可以看到返回的結(jié)果是None,所以只有在特殊的情況下才能獲取到注釋的內(nèi)容;
五、總結(jié)
本篇文章講述了關(guān)于BeautifulSoup的一些基礎(chǔ)的內(nèi)容。主要是bs的幾種解析器,根據(jù)實(shí)際的情況選擇不同的解析器。