? ? ? ? 前面,我們已經介紹了Xpath庫和Beautiful Soup庫(支持css選擇器)來提取頁面信息。它們有各自的優缺點,那可不可以取長補短呢?當然可以,parsel庫就是結合Xpath和css選擇器兩種方式來提取網頁信息。同時,Python爬蟲有一個最流行的Scrapy框架,parsel就是它的底層支持。了解了它,后面學習Scrapy選擇器的用法就非常方便了!!!
目錄
Parsel
1、準備工作
2、案例
3、提取文本?
(1)Xpath的提取方法
(2)css選擇器提取方法
4、提取屬性
5、正則提取
Parsel
1、準備工作
使用前要先安裝parsel庫,安裝命令如下:
pip3 install parsel
2、案例
????????為了讓讀者更加能清晰感受到parsel庫,首先來看一下一個示例:
# html代碼
html = '''
<div><ul><li class="item-0">firsst item</li><li class="item-1"><a href="link2.html">secomd item</a> </li><li class="item-0 active"><a href="link3.html"><span class="bold">third item</span> </a> firsst 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></ul>
</div>
'''
# 導包
from parsel import Selector
# 創建一個Selector對象,向其中傳入text參數,傳入的就是上面的html代碼
selector = Selector(html)
# 有了Selector對象,我們就可以使用css和xpath方法
# 這里用css選擇器選擇class為item-0的節點
items = selector.css('.item-0')
# 打印該節點的長度 類型 信息
print(len(items),type(items),items)
# 分隔行
print()
# 這里我們用xpath的方式提取li節點提取class為item-0的節點
items2 = selector.xpath('//li[contains(@class, "item-0")]')
# 打印該節點的長度 類型 信息
print(len(items2),type(items2),items2)
# 這兩種方式得到的結果是一樣的
結果如下:
3 <class 'parsel.selector.SelectorList'> [<Selector query="descendant-or-self::*[@class and contains(concat(' ', normalize-space(@class), ' '), ' item-0 ')]" data='<li class="item-0">firsst item</li>'>, <Selector query="descendant-or-self::*[@class and contains(concat(' ', normalize-space(@class), ' '), ' item-0 ')]" data='<li class="item-0 active"><a href="li...'>, <Selector query="descendant-or-self::*[@class and contains(concat(' ', normalize-space(@class), ' '), ' item-0 ')]" data='<li class="item-0"><a href="link5.htm...'>]3 <class 'parsel.selector.SelectorList'> [<Selector query='//li[contains(@class, "item-0")]' data='<li class="item-0">firsst item</li>'>, <Selector query='//li[contains(@class, "item-0")]' data='<li class="item-0 active"><a href="li...'>, <Selector query='//li[contains(@class, "item-0")]' data='<li class="item-0"><a href="link5.htm...'>]
????????可以看到兩個結果都是SelectorList對象,這其實是一個可迭代對象。用len 方法獲取了結果的長度,都是3。另外,提取結果代表的節點也是一樣的,都是第1、3、5個li節點,每個節點還是以Selector 對象的形式返回, 其中每個 Selector 對象的 data屬性里包含對應提取節點的 HTML 代碼。
????????這里大家可能會有個疑問,第一次不是用css方法提取的節點嗎? 為什么結果中的 Selector對象輸出的是xpath屬性而不是css屬性? 這是因為在css方法的背后,我們傳入的 CSS 選擇器首先是被轉成了 XPath,真正用于節點提取的是XPath。其中CSS選擇器轉換為 XPath的過程是由底層的 cssselect?這個庫實現的, 例如.item-0這個CSS 選擇器轉換為 XPath的結果就是 descendant-or-self::*[@class?and contains(concat(' ' , normalize-space(@class), ' '), ' item-o ')],?因此輸出的 Selector 對象就有了xpath屬性。不過大家不用擔心,這個對提取結果是沒有影響的,僅僅是換了一個表示方法而已。
3、提取文本?
? ? ? ? 提取文本只需采用xpath或者css選擇器的方式去獲取即可。由于Selector對象是一個可迭代對象,這里我們需要進行遍歷然后再選擇Xpath或css選擇器的方式去提取。
(1)Xpath的提取方法
? ? ? ? 首先演示一下用Xpath方式去獲取文本,Xpath是用text()方法來提取節點的文本,但提取的只是Selector構成的可迭代對象SelectorList。SelectorList中有一個get方法,可以獲取第一個Selector對象的文本內容;getall方法則獲取所有Selector對象的文本內容。代碼如下:
# html代碼
html = '''
<div><ul><li class="item-0">first item</li><li class="item-1"><a href="link2.html">secomd item</a> </li><li class="item-0 active"><a href="link3.html"><span class="bold">third item</span> </a> firsst 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></ul>
</div>
'''
from parsel import Selector
selector = Selector(html)
# 采用css選擇器選擇目標節點
items = selector.css('.item-0')
# 因為Selector是一個可迭代的對象,它是有列表組成的。所以可以遍歷提取所需要的信息
for item in items:# 采用Xpath方式提取文本信息,Selector中有一個get方法,它是用來提取所獲取第一個節點的文本內容# text = item.xpath('.//text()').get()# print(text)# 采用Xpath方式提取文本信息,Selector中有一個getall方法,它是用來提取所獲取所有的節點文本內容text2 = item.xpath('.//text()').getall()print(text2)
結果如下:
first item
['first item']
third item
['third item', ' ', ' firsst item']
fifth item
['fifth item', ' ']
(2)css選擇器提取方法
? ? ? ? css選擇器是通過::text來提取文本的,采用css選擇器定位到所需要的節點,然后加上::text,但它返回的也是Selector對象構成的SelectorList對象,所以也是跟上面一樣,加上get方法或getall方法。?
# html代碼
html = '''
<div><ul><li class="item-0">first item</li><li class="item-1"><a href="link2.html">secomd item</a> </li><li class="item-0 active"><a href="link3.html"><span class="bold">third item</span> </a> firsst 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></ul>
</div>
'''
from parsel import Selector
selector = Selector(html)
# 采用css選擇器選擇目標節點
items = selector.css('.item-0')
# 因為Selector是一個可迭代的對象,它是有列表組成的。所以可以遍歷提取所需要的信息
for item in items:# 采用Xpath方式提取文本信息,Selector中有一個get方法,它是用來提取所獲取第一個節點的文本內容text = item.css('::text').get()print(text)# 采用Xpath方式提取文本信息,Selector中有一個getall方法,它是用來提取所獲取所有的節點文本內容text2 = item.css('::text').getall()print(text2)
結果如下:
C:\Users\Lenovo\AppData\Local\Programs\Python\Python311\python.exe C:\Users\Lenovo\Desktop\爬蟲學習\Python知識\parsel庫\提取文本2.py
first item
['first item']
third item
['third item', ' ', ' firsst item']
fifth item
['fifth item', ' ']進程已結束,退出代碼為 0
4、提取屬性
? ? ? ? 提取屬性的方式更上面類似,直接采用xpath提取屬性的方法:選中節點后加上/@再加屬性名稱;css選擇器提取屬性的方法加::attr(),往里面傳入對應的屬性名稱。示例如下:
# html代碼
html = '''
<div><ul><li class="item-0">first item</li><li class="item-1"><a href="link2.html">secomd item</a> </li><li class="item-0 active"><a href="link3.html"><span class="bold">third item</span> </a> firsst 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></ul>
</div>
'''
from parsel import Selector
selector = Selector(text=html)
# css選擇器提取屬性的方式
result = selector.css('.item-0.active a::attr(href)').get()
print(result)
# xpath提取屬性的方式
result = selector.xpath('//li[contains(@class, "item-0") and contains(@class, "active")]/a/@href').get()
print(result)
結果如下:
link3.html
link3.html
5、正則提取
? ? ? ? Selector對象還提供正則表達式的提取方法。可以先采用css選擇器或xpath選擇器選中所需要的目標節點,然后調用Selector對象的re方法輸入正則表達式來匹配,其匹配選中節點所有符合正則表達式的內容;re_first方法輸入正則表達式來匹配,其匹配選中節點第一個符合正則表達式的內容。示例如下:
# html代碼
html = '''
<div><ul><li class="item-0">first item</li><li class="item-1"><a href="link2.html">secomd item</a> </li><li class="item-0 active"><a href="link3.html"><span class="bold">third item</span> </a> firsst 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></ul>
</div>
'''
from parsel import Selector
selector = Selector(text=html)
# 選用css選擇器選中目標節點,再用re方法輸入正則表達式來匹配,其匹配選中節點所有符合正則表達式的內容
result = selector.css('.item-0').re('link.*')
print(result)
# 選用css選擇器選中目標節點,再用re_first方法輸入正則表達式來匹配,其匹配選中節點第一個符合正則表達式的內容
result = selector.css('.item-0').re_first('<span class="bold">(.*?)</span>')
print(result)
結果如下:
['link3.html"><span class="bold">third item</span> </a> firsst item</li>', 'link5.html">fifth item</a> </li>']
third item