【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()方法不需要遍歷就可以獲取,它將所有節點取文字之後合併成一個字串。