1. 程式人生 > >【Python3 爬蟲學習筆記】解析庫的使用 9 —— 使用pyquery 2

【Python3 爬蟲學習筆記】解析庫的使用 9 —— 使用pyquery 2

遍歷

pyquery的選擇結果可能是多個節點,也可能是單個節點,型別都是PyQuery型別,並沒有返回像Beautiful Soup那樣的列表。
對於單個節點來說,可以直接列印輸出,也可以直接轉成字串:

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

執行結果如下:

<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>

對於多個節點的結果,我們就需要遍歷來獲取了。例如,這裡把每一個li節點進行遍歷,需要呼叫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))

執行結果如下:

<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'>

可以發現,呼叫items()方法後,會得到一個生成器,遍歷一下,就可以逐個得到li節點物件了,它的型別也是PyQuery型別。每個li節點還可以呼叫前面所說的方法進行選擇,比如繼續查詢子節點,尋找某個祖先節點等,非常靈活。

獲取資訊

提取到節點之後,我們的最終目的當然是提取節點所包含的資訊。比較重要的資訊有兩類,一是屬性,二是獲取文字。

獲取屬性

提取到某個PyQuery型別的節點後,就可以呼叫attr()方法來獲取屬性:

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'))

執行結果如下:

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

這裡首先選中class為item-0和active的li節點內的a節點,它的型別是PyQuery型別。
然後呼叫attr()方法。在這個方法中傳入屬性的名稱,就可以得到這個屬性值了。
此外,也可以通過呼叫attr屬性來獲取屬性,用法如下:

print(a.attr.href)

結果如下:

link3.html

這兩種方法的結果完全一樣。
如果選中的是多個元素,然後呼叫attr()方法:

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

執行結果如下:

<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

理論上,我們選中的a節點應該有四個,而且列印結果也應該有4個,但是當我們呼叫attr()方法時,返回結果卻只有第一個。這時因為,當返回結果包含多個節點時,呼叫attr()方法,只會得到第一個節點的屬性。
那麼遇到這種情況時,如果想要獲取所有的a節點的屬性,就要用到前面所說的遍歷了:

from pyquery import PyQuery as pq
doc = pq(html)
a = doc('a')
for item in a.items():
	print(item.attr('href')

此時的執行結果如下:

link2.html
link3.html
link4.html
link5.html

因此,在進行屬性獲取時,可以觀察返回節點是一個還是多個,如果是多個,則需要遍歷才能依次獲取每個節點的屬性。

獲取文字

獲取節點之後的另一個主要操作就是獲取其內部的文字了,此時可以呼叫text()方法來實現:

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())

執行結果如下:

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

這裡首先選中一個a節點,然後呼叫text()方法,就可以獲取其內部的文字資訊。此時它會忽略掉節點內部包含的所有HTML,只返回純文字內容。
但如果想要獲取這個節點內部的HTML文字,就要用html()方法了:

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

這裡我們選中了第三個li節點,然後呼叫了html()方法,它返回的結果應該是li節點內的所有HTML文字。
執行結果如下:

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

這裡同樣有一個問題,如果我們選中的結果是多個節點,text()或html()會返回什麼內容?

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()))

執行結果如下:

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

結果可能比較出乎意料,html()方法返回的是第一個li節點的內部HTML文字,而text()文字,而text()則返回了所有的li節點內部的純文字,中間用一個空格分割開,即返回結果是一個字串。
所以這個地方值得注意,如果得到結果是多個節點,並且想要獲取每個節點的內部HTML文字,則需要遍歷每個節點。而text()方法不需要遍歷就可以獲取,它將所有節點取文字之後合併成一個字串。