日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

第09讲:爬虫解析利器 PyQuery 的使用

發(fā)布時(shí)間:2024/4/11 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第09讲:爬虫解析利器 PyQuery 的使用 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

上一課時(shí)我們學(xué)習(xí)了正則表達(dá)式的基本用法,然而一旦你的正則表達(dá)式寫(xiě)法有問(wèn)題,我們就無(wú)法獲取需要的信息。

你可能會(huì)思考:每個(gè)網(wǎng)頁(yè),都有一定的特殊結(jié)構(gòu)和層級(jí)關(guān)系,而且很多節(jié)點(diǎn)都有 id 或 class 作為區(qū)分,我們可以借助它們的結(jié)構(gòu)和屬性來(lái)提取信息嗎?

這的確可行。這個(gè)課時(shí)我會(huì)為你介紹一個(gè)更加強(qiáng)大的 HTML 解析庫(kù):pyquery。利用它,我們可以直接解析 DOM 節(jié)點(diǎn)的結(jié)構(gòu),并通過(guò) DOM 節(jié)點(diǎn)的一些屬性快速進(jìn)行內(nèi)容提取。

接下來(lái),我們就來(lái)感受一下 pyquery 的強(qiáng)大之處。

準(zhǔn)備工作

pyquery 是 Python 的第三方庫(kù),我們可以借助于 pip3 來(lái)安裝,安裝命令如下:

pip3 install pyquery

更詳細(xì)的安裝方法可以參考:https://cuiqingcai.com/5186.html。

初始化

我們?cè)诮馕?HTML 文本的時(shí)候,首先需要將其初始化為一個(gè) pyquery 對(duì)象。它的初始化方式有多種,比如直接傳入字符串、傳入 URL、傳入文件名,等等。

下面我們來(lái)詳細(xì)介紹一下。

字符串初始化

我們可以直接把 HTML 的內(nèi)容當(dāng)作參數(shù)來(lái)初始化 pyquery 對(duì)象。我們用一個(gè)實(shí)例來(lái)感受一下:

html = ''' <div><ul><li class="item-0">first item</li><li class="item-1"><a href="link2.html">second item</a></li><li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li><li class="item-1 active"><a href="link4.html">fourth item</a></li><li class="item-0"><a href="link5.html">fifth item</a></li></ul></div> ''' from pyquery import PyQuery as pq doc = pq(html) print(doc('li'))

運(yùn)行結(jié)果如下:

<li class="item-0">first item</li> <li class="item-1"><a href="link2.html">second item</a></li> <li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li> <li class="item-1 active"><a href="link4.html">fourth item</a></li> <li class="item-0"><a href="link5.html">fifth item</a></li>

這里首先引入 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 初始化

初始化的參數(shù)不僅可以以字符串的形式傳遞,還可以傳入網(wǎng)頁(yè)的 URL,此時(shí)只需要指定參數(shù)為 url 即可:

from pyquery import PyQuery as pq doc = pq(url='https://cuiqingcai.com') print(doc('title'))

運(yùn)行結(jié)果:

<title>靜覓丨崔慶才的個(gè)人博客</title>

這樣的話,pyquery 對(duì)象會(huì)首先請(qǐng)求這個(gè) URL,然后用得到的 HTML 內(nèi)容完成初始化。這就相當(dāng)于將網(wǎng)頁(yè)的源代碼以字符串的形式傳遞給 pyquery 類來(lái)初始化。

它與下面的功能是相同的:

from pyquery import PyQuery as pq import requests doc = pq(requests.get('https://cuiqingcai.com').text) print(doc('title'))

文件初始化

當(dāng)然除了傳遞一個(gè) URL,我們還可以傳遞本地的文件名,參數(shù)指定為 filename 即可:

from pyquery import PyQuery as pq doc = pq(filename='demo.html') print(doc('li'))

當(dāng)然,這里需要有一個(gè)本地 HTML 文件 demo.html,其內(nèi)容是待解析的 HTML 字符串。這樣它會(huì)先讀取本地的文件內(nèi)容,然后將文件內(nèi)容以字符串的形式傳遞給 pyquery 類來(lái)初始化。

以上 3 種方式均可初始化,當(dāng)然最常用的初始化方式還是以字符串形式傳遞。

基本 CSS 選擇器

我們先用一個(gè)實(shí)例來(lái)感受一下 pyquery 的 CSS 選擇器的用法:

html = ''' <div id="container"><ul class="list"><li class="item-0">first item</li><li class="item-1"><a href="link2.html">second item</a></li><li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li><li class="item-1 active"><a href="link4.html">fourth item</a></li><li class="item-0"><a href="link5.html">fifth item</a></li></ul></div> ''' from pyquery import PyQuery as pq doc = pq(html) print(doc('#container .list li')) print(type(doc('#container .list li')))

運(yùn)行結(jié)果:

<li class="item-0">first item</li> <li class="item-1"><a href="link2.html">second item</a></li> <li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li> <li class="item-1 active"><a href="link4.html">fourth item</a></li> <li class="item-0"><a href="link5.html">fifth item</a></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)容,代碼示例如下:

for item in doc('#container .list li').items():print(item.text())

運(yùn)行結(jié)果如下:

first item second item third item fourth item fifth item

怎么樣?我們沒(méi)有再寫(xiě)正則表達(dá)式,而是直接通過(guò)選擇器和 text 方法,就得到了我們想要提取的文本信息,是不是方便多了?

下面我們?cè)賮?lái)詳細(xì)了解一下 pyquery 的用法吧,我將為你講解如何用它查找節(jié)點(diǎn)、遍歷節(jié)點(diǎn)、獲取各種信息等操作方法。掌握了這些,我們就能更高效地完成數(shù)據(jù)提取。

查找節(jié)點(diǎn)

下面我們介紹一些常用的查詢方法。

子節(jié)點(diǎn)

查找子節(jié)點(diǎn)需要用到 find 方法,傳入的參數(shù)是 CSS 選擇器,我們還是以上面的 HTML 為例:

from pyquery import PyQuery as pq doc = pq(html) items = doc('.list') print(type(items)) print(items) lis = items.find('li') print(type(lis)) print(lis)

運(yùn)行結(jié)果:

<class 'pyquery.pyquery.PyQuery'> <ul class="list"><li class="item-0">first item</li><li class="item-1"><a href="link2.html">second item</a></li><li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li><li class="item-1 active"><a href="link4.html">fourth item</a></li><li class="item-0"><a href="link5.html">fifth item</a></li> </ul> <class 'pyquery.pyquery.PyQuery'> <li class="item-0">first item</li> <li class="item-1"><a href="link2.html">second item</a></li> <li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li> <li class="item-1 active"><a href="link4.html">fourth item</a></li> <li class="item-0"><a href="link5.html">fifth item</a></li>

首先,我們通過(guò) .list 參數(shù)選取 class 為 list 的節(jié)點(diǎn),然后調(diào)用 find 方法,傳入 CSS 選擇器,選取其內(nèi)部的 li 節(jié)點(diǎn),最后打印輸出。可以發(fā)現(xiàn),find 方法會(huì)將符合條件的所有節(jié)點(diǎn)選擇出來(lái),結(jié)果的類型是 pyquery 類型。

find 的查找范圍是節(jié)點(diǎn)的所有子孫節(jié)點(diǎn),而如果我們只想查找子節(jié)點(diǎn),那可以用 children 方法:

lis = items.children() print(type(lis)) print(lis)

運(yùn)行結(jié)果如下:

<class 'pyquery.pyquery.PyQuery'> <li class="item-0">first item</li> <li class="item-1"><a href="link2.html">second item</a></li> <li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li> <li class="item-1 active"><a href="link4.html">fourth item</a></li> <li class="item-0"><a href="link5.html">fifth item</a></li>

如果要篩選所有子節(jié)點(diǎn)中符合條件的節(jié)點(diǎn),比如想篩選出子節(jié)點(diǎn)中 class 為 active 的節(jié)點(diǎn),可以向 children 方法傳入 CSS 選擇器 .active,代碼如下:

lis = items.children('.active') print(lis)

運(yùn)行結(jié)果:

<li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li> <li class="item-1 active"><a href="link4.html">fourth item</a></li>

我們看到輸出的結(jié)果已經(jīng)做了篩選,留下了 class 為 active 的節(jié)點(diǎn)。

父節(jié)點(diǎn)

我們可以用 parent 方法來(lái)獲取某個(gè)節(jié)點(diǎn)的父節(jié)點(diǎn),下面用一個(gè)實(shí)例來(lái)感受一下:

html = ''' <div class="wrap"><div id="container"><ul class="list"><li class="item-0">first item</li><li class="item-1"><a href="link2.html">second item</a></li><li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li><li class="item-1 active"><a href="link4.html">fourth item</a></li><li class="item-0"><a href="link5.html">fifth item</a></li></ul></div></div> ''' from pyquery import PyQuery as pq doc = pq(html) items = doc('.list') container = items.parent() print(type(container)) print(container)

運(yùn)行結(jié)果如下:

<class 'pyquery.pyquery.PyQuery'> <div id="container"><ul class="list"><li class="item-0">first item</li><li class="item-1"><a href="link2.html">second item</a></li><li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li><li class="item-1 active"><a href="link4.html">fourth item</a></li><li class="item-0"><a href="link5.html">fifth item</a></li></ul></div>

在上面的例子中我們首先用 .list 選取 class 為 list 的節(jié)點(diǎn),然后調(diào)用 parent 方法得到其父節(jié)點(diǎn),其類型依然是 pyquery 類型。

這里的父節(jié)點(diǎn)是該節(jié)點(diǎn)的直接父節(jié)點(diǎn),也就是說(shuō),它不會(huì)再去查找父節(jié)點(diǎn)的父節(jié)點(diǎn),即祖先節(jié)點(diǎn)。

但是如果你想獲取某個(gè)祖先節(jié)點(diǎn),該怎么辦呢?我們可以用 parents 方法:

from pyquery import PyQuery as pq doc = pq(html) items = doc('.list') parents = items.parents() print(type(parents)) print(parents)

運(yùn)行結(jié)果如下:

<class 'pyquery.pyquery.PyQuery'> <div class="wrap"><div id="container"><ul class="list"><li class="item-0">first item</li><li class="item-1"><a href="link2.html">second item</a></li><li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li><li class="item-1 active"><a href="link4.html">fourth item</a></li><li class="item-0"><a href="link5.html">fifth item</a></li></ul></div></div><div id="container"><ul class="list"><li class="item-0">first item</li><li class="item-1"><a href="link2.html">second item</a></li><li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li><li class="item-1 active"><a href="link4.html">fourth item</a></li><li class="item-0"><a href="link5.html">fifth item</a></li></ul></div>

可以看到,這個(gè)例子的輸出結(jié)果有兩個(gè):一個(gè)是 class 為 wrap 的節(jié)點(diǎn),一個(gè)是 id 為 container 的節(jié)點(diǎn)。也就是說(shuō),使用 parents 方法會(huì)返回所有的祖先節(jié)點(diǎn)。

如果你想要篩選某個(gè)祖先節(jié)點(diǎn)的話,可以向 parents 方法傳入 CSS 選擇器,這樣就會(huì)返回祖先節(jié)點(diǎn)中符合 CSS 選擇器的節(jié)點(diǎn):

parent = items.parents('.wrap') print(parent)

運(yùn)行結(jié)果如下:

<div class="wrap"><div id="container"><ul class="list"><li class="item-0">first item</li><li class="item-1"><a href="link2.html">second item</a></li><li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li><li class="item-1 active"><a href="link4.html">fourth item</a></li><li class="item-0"><a href="link5.html">fifth item</a></li></ul></div></div>

可以看到,輸出結(jié)果少了一個(gè)節(jié)點(diǎn),只保留了 class 為 wrap 的節(jié)點(diǎn)。

兄弟節(jié)點(diǎn)

前面我們說(shuō)明了子節(jié)點(diǎn)和父節(jié)點(diǎn)的用法,還有一種節(jié)點(diǎn)叫作兄弟節(jié)點(diǎn)。如果要獲取兄弟節(jié)點(diǎn),可以使用 siblings 方法。這里還是以上面的 HTML 代碼為例:

from pyquery import PyQuery as pq doc = pq(html) li = doc('.list .item-0.active') print(li.siblings())

在這個(gè)例子中我們首先選擇 class 為 list 的節(jié)點(diǎn),內(nèi)部 class 為 item-0 和 active 的節(jié)點(diǎn),也就是第 3 個(gè) li 節(jié)點(diǎn)。很明顯,它的兄弟節(jié)點(diǎn)有 4 個(gè),那就是第 1、2、4、5 個(gè) li 節(jié)點(diǎn)。

我們來(lái)運(yùn)行一下:

<li class="item-1"><a href="link2.html">second item</a></li> <li class="item-0">first item</li> <li class="item-1 active"><a href="link4.html">fourth item</a></li> <li class="item-0"><a href="link5.html">fifth item</a></li>

可以看到,結(jié)果顯示的正是我們剛才所說(shuō)的 4 個(gè)兄弟節(jié)點(diǎn)。

如果要篩選某個(gè)兄弟節(jié)點(diǎn),我們依然可以用 siblings 方法傳入 CSS 選擇器,這樣就會(huì)從所有兄弟節(jié)點(diǎn)中挑選出符合條件的節(jié)點(diǎn)了:

from pyquery import PyQuery as pq doc = pq(html) li = doc('.list .item-0.active') print(li.siblings('.active'))

在這個(gè)例子中我們篩選 class 為 active 的節(jié)點(diǎn),從剛才的結(jié)果中可以觀察到,class 為 active 兄弟節(jié)點(diǎn)的是第 4 個(gè) li 節(jié)點(diǎn),所以結(jié)果應(yīng)該是1個(gè)。

我們?cè)倏匆幌逻\(yùn)行結(jié)果:

<li class="item-1 active"><a href="link4.html">fourth item</a></li>

遍歷

通過(guò)剛才的例子我們可以觀察到,pyquery 的選擇結(jié)果既可能是多個(gè)節(jié)點(diǎn),也可能是單個(gè)節(jié)點(diǎn),類型都是 pyquery 類型,并沒(méi)有返回列表。

對(duì)于單個(gè)節(jié)點(diǎn)來(lái)說(shuō),可以直接打印輸出,也可以直接轉(zhuǎn)成字符串:

from pyquery import PyQuery as pq doc = pq(html) li = doc('.item-0.active') print(li) print(str(li))

運(yùn)行結(jié)果如下:

<li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li> <li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>

對(duì)于有多個(gè)節(jié)點(diǎn)的結(jié)果,我們就需要用遍歷來(lái)獲取了。例如,如果要把每一個(gè) li 節(jié)點(diǎn)進(jìn)行遍歷,需要調(diào)用 items 方法:

from pyquery import PyQuery as pq doc = pq(html) lis = doc('li').items() print(type(lis)) for li in lis:print(li, type(li))

運(yùn)行結(jié)果如下:

<class 'generator'> <li class="item-0">first item</li> <class 'pyquery.pyquery.PyQuery'> <li class="item-1"><a href="link2.html">second item</a></li> <class 'pyquery.pyquery.PyQuery'> <li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li> <class 'pyquery.pyquery.PyQuery'> <li class="item-1 active"><a href="link4.html">fourth item</a></li> <class 'pyquery.pyquery.PyQuery'> <li class="item-0"><a href="link5.html">fifth item</a></li> <class 'pyquery.pyquery.PyQuery'>

可以發(fā)現(xiàn),調(diào)用 items 方法后,會(huì)得到一個(gè)生成器,遍歷一下,就可以逐個(gè)得到 li 節(jié)點(diǎn)對(duì)象了,它的類型也是 pyquery 類型。每個(gè) li 節(jié)點(diǎn)還可以調(diào)用前面所說(shuō)的方法進(jìn)行選擇,比如繼續(xù)查詢子節(jié)點(diǎn),尋找某個(gè)祖先節(jié)點(diǎn)等,非常靈活。

獲取信息

提取到節(jié)點(diǎn)之后,我們的最終目的當(dāng)然是提取節(jié)點(diǎn)所包含的信息了。比較重要的信息有兩類,一是獲取屬性,二是獲取文本,下面分別進(jìn)行說(shuō)明。

獲取屬性

提取到某個(gè) pyquery 類型的節(jié)點(diǎn)后,就可以調(diào)用 attr 方法來(lái)獲取屬性:

html = ''' <div class="wrap"><div id="container"><ul class="list"><li class="item-0">first item</li><li class="item-1"><a href="link2.html">second item</a></li><li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li><li class="item-1 active"><a href="link4.html">fourth item</a></li><li class="item-0"><a href="link5.html">fifth item</a></li></ul></div></div> ''' from pyquery import PyQuery as pq doc = pq(html) a = doc('.item-0.active a') print(a, type(a)) print(a.attr('href'))

運(yùn)行結(jié)果如下:

<a href="link3.html"><span class="bold">third item</span></a> <class 'pyquery.pyquery.PyQuery'> 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)獲取屬性值,用法如下:

print(a.attr.href)

結(jié)果:

link3.html

這兩種方法的結(jié)果完全一樣。如果選中的是多個(gè)元素,然后調(diào)用 attr 方法,會(huì)出現(xiàn)怎樣的結(jié)果呢?我們用實(shí)例來(lái)測(cè)試一下:

a = doc('a') print(a, type(a)) print(a.attr('href')) print(a.attr.href)

運(yùn)行結(jié)果如下:

<a href="link2.html">second item</a><a href="link3.html"><span class="bold">third item</span></a><a href="link4.html">fourth item</a><a href="link5.html">fifth item</a> <class 'pyquery.pyquery.PyQuery'> link2.html link2.html

照理來(lái)說(shuō),我們選中的 a 節(jié)點(diǎn)應(yīng)該有 4 個(gè),打印結(jié)果也應(yīng)該是 4 個(gè),但是當(dāng)我們調(diào)用 attr 方法時(shí),返回結(jié)果卻只有第 1 個(gè)。這是因?yàn)?#xff0c;當(dāng)返回結(jié)果包含多個(gè)節(jié)點(diǎn)時(shí),調(diào)用 attr 方法,只會(huì)得到第 1 個(gè)節(jié)點(diǎn)的屬性。

那么,遇到這種情況時(shí),如果想獲取所有的 a 節(jié)點(diǎn)的屬性,就要用到前面所說(shuō)的遍歷了:

from pyquery import PyQuery as pq doc = pq(html) a = doc('a') for item in a.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):

html = ''' <div class="wrap"><div id="container"><ul class="list"><li class="item-0">first item</li><li class="item-1"><a href="link2.html">second item</a></li><li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li><li class="item-1 active"><a href="link4.html">fourth item</a></li><li class="item-0"><a href="link5.html">fifth item</a></li></ul></div></div> ''' from pyquery import PyQuery as pq doc = pq(html) a = doc('.item-0.active a') print(a) print(a.text())

運(yùn)行結(jié)果:

<a href="link3.html"><span class="bold">third item</span></a> third item

這里我們首先選中一個(gè) a 節(jié)點(diǎn),然后調(diào)用 text 方法,就可以獲取其內(nèi)部的文本信息了。text 會(huì)忽略節(jié)點(diǎn)內(nèi)部包含的所有 HTML,只返回純文字內(nèi)容。

但如果你想要獲取這個(gè)節(jié)點(diǎn)內(nèi)部的 HTML 文本,就要用 html 方法了:

from pyquery import PyQuery as pq doc = pq(html) li = doc('.item-0.active') print(li) print(li.html())

這里我們選中第 3 個(gè) li 節(jié)點(diǎn),然后調(diào)用 html 方法,它返回的結(jié)果應(yīng)該是 li 節(jié)點(diǎn)內(nèi)的所有 HTML 文本。

運(yùn)行結(jié)果:

<a href="link3.html"><span class="bold">third item</span></a>

這里同樣有一個(gè)問(wèn)題,如果我們選中的結(jié)果是多個(gè)節(jié)點(diǎn),text 或 html 方法會(huì)返回什么內(nèi)容?我們用實(shí)例來(lái)看一下:

html = ''' <div class="wrap"><div id="container"><ul class="list"><li class="item-1"><a href="link2.html">second item</a></li><li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li><li class="item-1 active"><a href="link4.html">fourth item</a></li><li class="item-0"><a href="link5.html">fifth item</a></li></ul></div></div> ''' from pyquery import PyQuery as pq doc = pq(html) li = doc('li') print(li.html()) print(li.text()) print(type(li.text())

運(yùn)行結(jié)果如下:

<a href="link2.html">second item</a> second item third item fourth item fifth item <class'str'>

結(jié)果比較出乎意料,html 方法返回的是第 1 個(gè) li 節(jié)點(diǎn)的內(nèi)部 HTML 文本,而 text 則返回了所有的 li 節(jié)點(diǎn)內(nèi)部的純文本,中間用一個(gè)空格分割開(kāi),即返回結(jié)果是一個(gè)字符串。

這個(gè)地方值得注意,如果你想要得到的結(jié)果是多個(gè)節(jié)點(diǎn),并且需要獲取每個(gè)節(jié)點(diǎn)的內(nèi)部 HTML 文本,則需要遍歷每個(gè)節(jié)點(diǎn)。而 text 方法不需要遍歷就可以獲取,它將所有節(jié)點(diǎn)取文本之后合并成一個(gè)字符串。

節(jié)點(diǎn)操作

pyquery 提供了一系列方法來(lái)對(duì)節(jié)點(diǎn)進(jìn)行動(dòng)態(tài)修改,比如為某個(gè)節(jié)點(diǎn)添加一個(gè) class,移除某個(gè)節(jié)點(diǎn)等,這些操作有時(shí)會(huì)為提取信息帶來(lái)極大的便利。

由于節(jié)點(diǎn)操作的方法太多,下面舉幾個(gè)典型的例子來(lái)說(shuō)明它的用法。
addClass 和 removeClass
我們先用一個(gè)實(shí)例來(lái)感受一下:

html = ''' <div class="wrap"><div id="container"><ul class="list"><li class="item-0">first item</li><li class="item-1"><a href="link2.html">second item</a></li><li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li><li class="item-1 active"><a href="link4.html">fourth item</a></li><li class="item-0"><a href="link5.html">fifth item</a></li></ul></div></div> ''' from pyquery import PyQuery as pq doc = pq(html) li = doc('.item-0.active') print(li) li.removeClass('active') print(li) li.addClass('active') print(li)

首先選中第 3 個(gè) li 節(jié)點(diǎn),然后調(diào)用 removeClass 方法,將 li 節(jié)點(diǎn)的 active 這個(gè) class 移除,第 2 步調(diào)用 addClass 方法,將 class 添加回來(lái)。每執(zhí)行一次操作,就打印輸出當(dāng)前 li 節(jié)點(diǎn)的內(nèi)容。

運(yùn)行結(jié)果如下:

<li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li> <li class="item-0"><a href="link3.html"><span class="bold">third item</span></a></li> <li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>

可以看到,一共輸出了 3 次。第 2 次輸出時(shí),li 節(jié)點(diǎn)的 active 這個(gè) class 被移除了,第 3 次 class 又添加回來(lái)了。

所以說(shuō),addClass 和 removeClass 方法可以動(dòng)態(tài)改變節(jié)點(diǎn)的 class 屬性。

attr、text、html
當(dāng)然,除了操作 class 這個(gè)屬性外,也可以用 attr 方法對(duì)屬性進(jìn)行操作。此外,我們還可以用 text 和 html 方法來(lái)改變節(jié)點(diǎn)內(nèi)部的內(nèi)容。示例如下:

html = ''' <ul class="list"><li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li> </ul> ''' from pyquery import PyQuery as pq doc = pq(html) li = doc('.item-0.active') print(li) li.attr('name', 'link') print(li) li.text('changed item') print(li) li.html('<span>changed item</span>') print(li)

這里我們首先選中 li 節(jié)點(diǎn),然后調(diào)用 attr 方法來(lái)修改屬性。該方法的第 1 個(gè)參數(shù)為屬性名,第 2 個(gè)參數(shù)為屬性值。最后調(diào)用 text 和 html 方法來(lái)改變節(jié)點(diǎn)內(nèi)部的內(nèi)容。3 次操作后,分別打印輸出當(dāng)前的 li 節(jié)點(diǎn)。

運(yùn)行結(jié)果如下:

<li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li> <li class="item-0 active" name="link"><a href="link3.html"><span class="bold">third item</span></a></li> <li class="item-0 active" name="link">changed item</li> <li class="item-0 active" name="link"><span>changed item</span></li>

我們發(fā)現(xiàn),調(diào)用 attr 方法后,li 節(jié)點(diǎn)多了一個(gè)原本不存在的屬性 name,其值為 link。接著調(diào)用 text 方法傳入文本,li 節(jié)點(diǎn)內(nèi)部的文本全被改為傳入的字符串文本。最后,調(diào)用 html 方法傳入 HTML 文本,li 節(jié)點(diǎn)內(nèi)部又變?yōu)閭魅氲?HTML 文本了。

所以說(shuō),使用 attr 方法時(shí)如果只傳入第 1 個(gè)參數(shù)的屬性名,則是獲取這個(gè)屬性值;如果傳入第 2 個(gè)參數(shù),可以用來(lái)修改屬性值。使用 text 和 html 方法時(shí)如果不傳參數(shù),則是獲取節(jié)點(diǎn)內(nèi)純文本和 HTML 文本,如果傳入?yún)?shù),則進(jìn)行賦值。

remove

顧名思義,remove 方法就是移除,它有時(shí)會(huì)為信息的提取帶來(lái)非常大的便利。下面有一段 HTML 文本:

html = ''' <div class="wrap">Hello, World<p>This is a paragraph.</p></div> ''' from pyquery import PyQuery as pq doc = pq(html) wrap = doc('.wrap') print(wrap.text())

現(xiàn)在我們想提取“Hello, World”這個(gè)字符串,該怎樣操作呢?

這里先直接嘗試提取 class 為 wrap 的節(jié)點(diǎn)的內(nèi)容,看看是不是我們想要的。

運(yùn)行結(jié)果如下:

Hello, World This is a paragraph.

這個(gè)結(jié)果還包含了內(nèi)部的 p 節(jié)點(diǎn)的內(nèi)容,也就是說(shuō) text 把所有的純文本全提取出來(lái)了。

如果我們想去掉 p 節(jié)點(diǎn)內(nèi)部的文本,可以選擇再把 p 節(jié)點(diǎn)內(nèi)的文本提取一遍,然后從整個(gè)結(jié)果中移除這個(gè)子串,但這個(gè)做法明顯比較煩瑣。

這時(shí) remove 方法就可以派上用場(chǎng)了,我們可以接著這么做:

wrap.find('p').remove() print(wrap.text())

首先選中 p 節(jié)點(diǎn),然后調(diào)用 remove 方法將其移除,這時(shí) wrap 內(nèi)部就只剩下“Hello, World”這句話了,最后利用 text 方法提取即可。

其實(shí)還有很多其他節(jié)點(diǎn)操作的方法,比如 append、empty 和 prepend 等方法,詳細(xì)的用法可以參考官方文檔:http://pyquery.readthedocs.io/en/latest/api.html。

偽類選擇器

CSS 選擇器之所以強(qiáng)大,還有一個(gè)很重要的原因,那就是它支持多種多樣的偽類選擇器,例如選擇第一個(gè)節(jié)點(diǎn)、最后一個(gè)節(jié)點(diǎn)、奇偶數(shù)節(jié)點(diǎn)、包含某一文本的節(jié)點(diǎn)等。示例如下:

html = ''' <div class="wrap"><div id="container"><ul class="list"><li class="item-0">first item</li><li class="item-1"><a href="link2.html">second item</a></li><li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li><li class="item-1 active"><a href="link4.html">fourth item</a></li><li class="item-0"><a href="link5.html">fifth item</a></li></ul></div></div> ''' from pyquery import PyQuery as pq doc = pq(html) li = doc('li:first-child') print(li) li = doc('li:last-child') print(li) li = doc('li:nth-child(2)') print(li) li = doc('li:gt(2)') print(li) li = doc('li:nth-child(2n)') print(li) li = doc('li:contains(second)') print(li)

在這個(gè)例子中我們使用了 CSS3 的偽類選擇器,依次選擇了第 1 個(gè) li 節(jié)點(diǎn)、最后一個(gè) li 節(jié)點(diǎn)、第 2 個(gè) li 節(jié)點(diǎn)、第 3 個(gè) li 之后的 li 節(jié)點(diǎn)、偶數(shù)位置的 li 節(jié)點(diǎn)、包含 second 文本的 li 節(jié)點(diǎn)。

關(guān)于 CSS 選擇器的更多用法,可以參考 http://www.w3school.com.cn/css/index.asp。

到此為止,pyquery 的常用用法就介紹完了。如果想查看更多的內(nèi)容,可以參考 pyquery 的官方文檔:http://pyquery.readthedocs.io。相信一旦你擁有了它,解析網(wǎng)頁(yè)將不再是難事。

總結(jié)

以上是生活随笔為你收集整理的第09讲:爬虫解析利器 PyQuery 的使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。