爬蟲解析利器PyQuery詳解及使用實(shí)踐
↑?關(guān)注 + 星標(biāo)?,每天學(xué)Python新技能
后臺(tái)回復(fù)【大禮包】送你Python自學(xué)大禮包
作者:葉庭云
整理:Lemon
爬蟲解析利器
PyQuery詳解及使用實(shí)踐
之前跟大家分享了 selenium、Scrapy、Pyppeteer 等工具的使用。
今天來(lái)分享另一個(gè)好用的爬蟲解析工具 PyQuery。
一、簡(jiǎn)介
每個(gè)網(wǎng)頁(yè),都有一定的特殊結(jié)構(gòu)和層級(jí)關(guān)系,而且很多節(jié)點(diǎn)都有 id 或 class 作為區(qū)分,我們可以借助它們的結(jié)構(gòu)和屬性來(lái)提取信息。
PyQuery 是一個(gè)強(qiáng)大的 HTML 解析庫(kù),利用它,我們可以直接解析 DOM 節(jié)點(diǎn)的結(jié)構(gòu),并通過(guò) DOM 節(jié)點(diǎn)的一些屬性快速進(jìn)行內(nèi)容提取。
pyquery 是 Python 的第三方庫(kù),可以用 pip3 來(lái)安裝,安裝命令如下:
pip3?install?pyquery?-i?http://pypi.douban.com/simple?--trusted-host?pypi.douban.com
在解析 HTML 文本的時(shí)候,首先需要將其初始化為一個(gè) pyquery 對(duì)象。它的初始化方式有多種,比如直接傳入字符串、傳入 URL、傳入文件名等等。
字符串初始化
可以直接把 HTML 的內(nèi)容當(dāng)作參數(shù)來(lái)初始化 pyquery 對(duì)象,下面用一個(gè)實(shí)例來(lái)感受一下:
from?pyquery?import?PyQuery?as?pq
html?=?'''
'''
doc?=?pq(html)
print(doc('li'))
運(yùn)行結(jié)果如下:
class="item-0">first?itemli>
<li?class="item-1"><a?href="link2.html">second?itema>li>
<li><img?src="http://pic.netbian.com/uploads/allimg/210107/215736-1610027856f6ef.jpg"/>
190902/152344-1567409024af8c.jpg"/> ??
首先引入 pyquery 這個(gè)對(duì)象,取別名為 pq,然后定義了一個(gè)長(zhǎng) HTML 字符串,并將其當(dāng)作參數(shù)傳遞給 pyquery 類,這樣就成功完成了初始化。
接下來(lái),將初始化的對(duì)象傳入 CSS 選擇器。在這個(gè)實(shí)例中,我們傳入 li 節(jié)點(diǎn),這樣就可以選擇所有的 li 節(jié)點(diǎn)。
URL 初始化
#?-*-?coding:?UTF-8?-*-
from?pyquery?import?PyQuery?as?pq
url?=?'https://yetingyun.blog.csdn.net/'
doc?=?pq(url)
print(doc('title'))
運(yùn)行結(jié)果如下:
葉庭云的博客_CSDN博客-python?爬蟲,python數(shù)據(jù)可視化,計(jì)算機(jī)視覺(jué)圖像處理領(lǐng)域博主
pyquery 對(duì)象會(huì)首先請(qǐng)求這個(gè) URL,然后用得到的 HTML 內(nèi)容完成初始化。這就相當(dāng)于將網(wǎng)頁(yè)的源代碼以字符串的形式傳遞給 pyquery 類來(lái)初始化。
文件初始化
除了傳遞一個(gè) URL,我們還可以傳遞本地的文件名,參數(shù)指定為 filename 即可:
from?pyquery?import?PyQuery?as?pq
doc?=?pq(filename='時(shí)間輪播圖.html')
print(doc('title'))
運(yùn)行結(jié)果如下:
Awesome-pyecharts
當(dāng)然,這里需要有一個(gè)本地 HTML 文件,其內(nèi)容是待解析的 HTML 字符串。這樣它會(huì)先讀取本地的文件內(nèi)容,然后將文件內(nèi)容以字符串的形式傳遞給 pyquery 類來(lái)初始化。
以上 3 種方式均可初始化,當(dāng)然最常用的初始化方式還是以字符串形式傳遞。
二、pyquery基本使用
基本 CSS 選擇器
用一個(gè)實(shí)例來(lái)感受一下 pyquery 的 css 選擇器的用法:
from?pyquery?import?PyQuery?as?pq
html?=?'''
????
?????????- first?item
?????????- second?item
?????????- third?item
?????????- fourth?item
?????????- fifth?item
?????
?
'''
doc?=?pq(html)
print(doc('#container?.list?li'))
print(type(doc('#container?.list?li')))
運(yùn)行結(jié)果如下:
class="item-0">first?itemli>
<li?class="item-1"><a?href="link2.html">second?itema>li>
<li?class="item-0?active"><a?href="link3.html"><span?class="bold">third?itemspan>a>li>
<li?class="item-1?active"><a?href="link4.html">fourth?itema>li>
<li?class="item-0"><a?href="link5.html">fifth?itema>li>
<class?'pyquery.pyquery.PyQuery'>
初始化 pyquery 對(duì)象之后,傳入 css 選擇器 #container .list li,它的意思是先選取 id 為 container 的節(jié)點(diǎn),然后再選取其內(nèi)部 class 為 list 的所有 li 節(jié)點(diǎn),最后打印輸出。
可以看到,我們成功獲取到了符合條件的節(jié)點(diǎn)。我們將它的類型打印輸出后發(fā)現(xiàn),它的類型依然是 pyquery 類型。
下面,我們直接遍歷這些節(jié)點(diǎn),然后調(diào)用 text 方法,就可以獲取節(jié)點(diǎn)的文本內(nèi)容
from?pyquery?import?PyQuery?as?pq
html?=?'''
????
?????????- first?item
?????????- second?item
?????????- third?item
?????????- fourth?item
?????????- fifth?item
?????
?
'''
doc?=?pq(html)
for?item?in?doc('#container?.list?li').items():
????print(item.text())
運(yùn)行結(jié)果如下:
first?item
second?item
third?item
fourth?item
fifth?item
而是直接通過(guò)選擇器和 text 方法,就得到了我們想要提取的文本信息,是不是挺方便的?
獲取信息
提取到節(jié)點(diǎn)之后,我們的最終目的當(dāng)然是提取節(jié)點(diǎn)所包含的信息了。比較重要的信息有兩類,一是獲取屬性,二是獲取文本,下面分別進(jìn)行說(shuō)明。
獲取屬性:提取到某個(gè) pyquery 類型的節(jié)點(diǎn)后,可以調(diào)用 attr 方法來(lái)獲取屬性:
from?pyquery?import?PyQuery?as?pq
html?=?'''
????
????????
?????????????- first?item
?????????????- second?item
?????????????- third?item
?????????????- fourth?item
?????????????- fifth?item
?????????
?????
?
'''
doc?=?pq(html)
a?=?doc('.item-0.active?a')
print(a,?type(a))
print(a.attr('href'))
print(a.attr.href)
運(yùn)行結(jié)果如下:
"link3.html">class="bold">third?itemspan>a>?<class?'pyquery.pyquery.PyQuery'>
link3.html
link3.html
在這個(gè)例子中我們首先選中 class 為 item-0 和 active 的 li 節(jié)點(diǎn)內(nèi)的 a 節(jié)點(diǎn),它的類型是 pyquery 類型。然后調(diào)用 attr 方法。在這個(gè)方法中傳入屬性的名稱,就可以得到屬性值了。此外,也可以通過(guò)調(diào)用 attr 屬性來(lái)獲取屬性值。
遍歷獲取所有的 a 節(jié)點(diǎn)的屬性:
from?pyquery?import?PyQuery?as?pq
html?=?'''
????
????????
?????????????- first?item
?????????????- second?item
?????????????- third?item
?????????????- fourth?item
?????????????- fifth?item
?????????
?????
?
'''
doc?=?pq(html)
nodes?=?doc('a')
for?item?in?nodes.items():
????print(item.attr('href'))
運(yùn)行結(jié)果如下:
link2.html
link3.html
link4.html
link5.html
因此,在進(jìn)行屬性獲取時(shí),先要觀察返回節(jié)點(diǎn)是一個(gè)還是多個(gè),如果是多個(gè),則需要遍歷才能依次獲取每個(gè)節(jié)點(diǎn)的屬性。
獲取文本
獲取節(jié)點(diǎn)之后的另一個(gè)主要操作就是獲取其內(nèi)部文本了,此時(shí)可以調(diào)用 text 方法來(lái)實(shí)現(xiàn):
from?pyquery?import?PyQuery?as?pq
html?=?'''
????
????????
?????????????- first?item
?????????????- second?item
?????????????- third?item
?????????????- fourth?item
?????????????- fifth?item
?????????
?????
?
'''
doc?=?pq(html)
nodes?=?doc('li')
for?item?in?nodes.items():
????print(item.text())
運(yùn)行結(jié)果如下:
first?item
second?item
third?item
fourth?item
fifth?item
三、爬取B站視頻熱搜榜單數(shù)據(jù)
下面用一個(gè)爬取B站視頻熱搜榜單數(shù)據(jù)的實(shí)例來(lái)熟悉 PyQuery 的使用
URL:https://www.bilibili.com/ranking?spm_id_from=333.851.b_7072696d61727950616765546162.3

1. 發(fā)送請(qǐng)求
import?requests
#?偽裝請(qǐng)求頭
headers?=?{
????"Origin":?"https://www.bilibili.com",
????"User-Agent":"Mozilla/5.0?(Windows?NT?6.1;?WOW64)?AppleWebKit/537.1?(KHTML,?like?Gecko)?Chrome/22.0.1207.1?Safari/537.1"
}
#?目標(biāo)URL
url?=?'https://www.bilibili.com/v/popular/rank/all'
#?request請(qǐng)求獲取的文本傳入PyQuery初始化
resp?=?requests.get(url,?headers=headers)
print(resp.status_code)
print(resp.text)
在上面的代碼中,我們完成了以下幾件事:
導(dǎo)入 requests 庫(kù) 偽裝請(qǐng)求頭 使用 get 方法構(gòu)造請(qǐng)求 打印查看請(qǐng)求的狀態(tài)碼和網(wǎng)頁(yè)源代碼文本
2. 解析提取數(shù)據(jù)和保存
from?pyquery?import?PyQuery?as?pq
import?openpyxl
wb?=?openpyxl.Workbook()????#?初始化工作簿對(duì)象
sheet?=?wb.active???????????#?獲取活動(dòng)的工作表
#?添加列名
sheet.append(['rank',?'title',?'link',?'bicon_play',?'bicon_view',?'creator',?'score'])
doc?=?pq(resp)
#?獲取class=rank-list?下所有l(wèi)i節(jié)點(diǎn)內(nèi)容
#?遍歷li節(jié)點(diǎn)
con1?=?doc('.rank-list?li')
for?item?in?con1.items():
????rank?=?item('.num').text()???#?排名
????title?=?item('.content?.info?a:first-child').text()?????????#?視頻標(biāo)題
????link?=?'https:'?+?item('.content?.info?a').attr('href')?????#?視頻鏈接
????#?creator?=?item('.content?.info?.detail?a?span').text()????#?UP主
????bicon_play,?bicon_view,?creator?=?item('.content?.info?.detail?span').text().split('?')
????#?print(bicon_play,?bicon_view,?creator)?????
????score?=?item('.content?.info?.pts?div').text()
????sheet.append([rank,?title,?link,?bicon_play,?bicon_view,?creator,?score])
wb.save(filename='data.xlsx')
3. 完整代碼
#?-*-?coding:?UTF-8?-*-
from?pyquery?import?PyQuery?as?pq
import?requests
import?logging
import?openpyxl
wb?=?openpyxl.Workbook()????#?初始化工作簿對(duì)象
sheet?=?wb.active???????????#?獲取活動(dòng)的工作表
#?添加列名
sheet.append(['rank',?'title',?'link',?'bicon_play',?'bicon_view',?'creator',?'score'])
#?日志輸出配置
logging.basicConfig(level=logging.INFO,?format='%(asctime)s?-?%(levelname)s:?%(message)s')
#?偽裝請(qǐng)求頭
headers?=?{
????"Origin":?"https://www.bilibili.com",
????"User-Agent":"Mozilla/5.0?(Windows?NT?6.1;?WOW64)?AppleWebKit/537.1?(KHTML,?like?Gecko)?Chrome/22.0.1207.1?Safari/537.1"
}
#?目標(biāo)URL
url?=?'https://www.bilibili.com/v/popular/rank/all'
#?request請(qǐng)求獲取的文本傳入PyQuery初始化
resp?=?requests.get(url,?headers=headers).text
doc?=?pq(resp)
#?獲取class=rank-list?下所有l(wèi)i節(jié)點(diǎn)內(nèi)容
#?遍歷li節(jié)點(diǎn)
con1?=?doc('.rank-list?li')
for?item?in?con1.items():
????rank?=?item('.num').text()???#?排名
????title?=?item('.content?.info?a:first-child').text()?????????#?視頻標(biāo)題
????link?=?'https:'?+?item('.content?.info?a').attr('href')?????#?視頻鏈接
????#?creator?=?item('.content?.info?.detail?a?span').text()????????#?UP主
????bicon_play,?bicon_view,?creator?=?item('.content?.info?.detail?span').text().split('?')
????#?print(bicon_play,?bicon_view,?creator)?????#?排名
????score?=?item('.content?.info?.pts?div').text()
????sheet.append([rank,?title,?link,?bicon_play,?bicon_view,?creator,?score])
????logging.info([rank,?title,?link,?bicon_play,?bicon_view,?creator,?score])
wb.save(filename='data.xlsx')
運(yùn)行效果如下:


作者:葉庭云
CSDN:https://yetingyun.blog.csdn.net/
見面禮
掃碼加我微信備注「三劍客」送你上圖三本Python入門電子書?
推薦閱讀
點(diǎn)分享 點(diǎn)收藏 點(diǎn)點(diǎn)贊 點(diǎn)在看





