爬虫解析利器PyQuery详解及使用实践
作者:葉庭云
整理:Lemon
爬蟲解析利器
PyQuery詳解及使用實踐
之前跟大家分享了 selenium、Scrapy、Pyppeteer 等工具的使用。
今天來分享另一個好用的爬蟲解析工具 PyQuery。
一、簡介
每個網頁,都有一定的特殊結構和層級關系,而且很多節點都有 id 或 class 作為區分,我們可以借助它們的結構和屬性來提取信息。
PyQuery 是一個強大的 HTML 解析庫,利用它,我們可以直接解析 DOM 節點的結構,并通過 DOM 節點的一些屬性快速進行內容提取。
pyquery 是 Python 的第三方庫,可以用 pip3 來安裝,安裝命令如下:
pip3?install?pyquery?-i?http://pypi.douban.com/simple?--trusted-host?pypi.douban.com在解析 HTML 文本的時候,首先需要將其初始化為一個 pyquery 對象。它的初始化方式有多種,比如直接傳入字符串、傳入 URL、傳入文件名等等。
字符串初始化
可以直接把 HTML 的內容當作參數來初始化 pyquery 對象,下面用一個實例來感受一下:
from?pyquery?import?PyQuery?as?pqhtml?=?''' <div><ul?class="clearfix"><li?class="item-0">first?item</li><li?class="item-1"><a?href="link2.html">second?item</a></li><li><img?src="http://pic.netbian.com/uploads/allimg/210107/215736-1610027856f6ef.jpg"></li><li><img?src="http://pic.netbian.com//uploads/allimg/190902/152344-1567409024af8c.jpg"></li>?</ul> </div> '''doc?=?pq(html) print(doc('li'))運行結果如下:
<li?class="item-0">first?item</li> <li?class="item-1"><a?href="link2.html">second?item</a></li> <li><img?src="http://pic.netbian.com/uploads/allimg/210107/215736-1610027856f6ef.jpg"/></li> <li><img?src="http://pic.netbian.com//uploads/allimg/190902/152344-1567409024af8c.jpg"/></li>??首先引入 pyquery 這個對象,取別名為 pq,然后定義了一個長 HTML 字符串,并將其當作參數傳遞給 pyquery 類,這樣就成功完成了初始化。
接下來,將初始化的對象傳入 CSS 選擇器。在這個實例中,我們傳入 li 節點,這樣就可以選擇所有的 li 節點。
URL 初始化
#?-*-?coding:?UTF-8?-*-from?pyquery?import?PyQuery?as?pqurl?=?'https://yetingyun.blog.csdn.net/'doc?=?pq(url) print(doc('title'))運行結果如下:
<title>葉庭云的博客_CSDN博客-python?爬蟲,python數據可視化,計算機視覺圖像處理領域博主</title>pyquery 對象會首先請求這個 URL,然后用得到的 HTML 內容完成初始化。這就相當于將網頁的源代碼以字符串的形式傳遞給 pyquery 類來初始化。
文件初始化
除了傳遞一個 URL,我們還可以傳遞本地的文件名,參數指定為 filename 即可:
from?pyquery?import?PyQuery?as?pqdoc?=?pq(filename='時間輪播圖.html') print(doc('title'))運行結果如下:
<title>Awesome-pyecharts</title>當然,這里需要有一個本地 HTML 文件,其內容是待解析的 HTML 字符串。這樣它會先讀取本地的文件內容,然后將文件內容以字符串的形式傳遞給 pyquery 類來初始化。
以上 3 種方式均可初始化,當然最常用的初始化方式還是以字符串形式傳遞。
二、pyquery基本使用
基本 CSS 選擇器
用一個實例來感受一下 pyquery 的 css 選擇器的用法:
from?pyquery?import?PyQuery?as?pq 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> '''doc?=?pq(html) print(doc('#container?.list?li')) print(type(doc('#container?.list?li')))運行結果如下:
<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 對象之后,傳入 css 選擇器 #container .list li,它的意思是先選取 id 為 container 的節點,然后再選取其內部 class 為 list 的所有 li 節點,最后打印輸出。
可以看到,我們成功獲取到了符合條件的節點。我們將它的類型打印輸出后發現,它的類型依然是 pyquery 類型。
下面,我們直接遍歷這些節點,然后調用 text 方法,就可以獲取節點的文本內容
from?pyquery?import?PyQuery?as?pq 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> '''doc?=?pq(html) for?item?in?doc('#container?.list?li').items():print(item.text())運行結果如下:
first?item second?item third?item fourth?item fifth?item而是直接通過選擇器和 text 方法,就得到了我們想要提取的文本信息,是不是挺方便的?
獲取信息
提取到節點之后,我們的最終目的當然是提取節點所包含的信息了。比較重要的信息有兩類,一是獲取屬性,二是獲取文本,下面分別進行說明。
獲取屬性:提取到某個 pyquery 類型的節點后,可以調用 attr 方法來獲取屬性:
from?pyquery?import?PyQuery?as?pq 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> '''doc?=?pq(html) a?=?doc('.item-0.active?a') print(a,?type(a)) print(a.attr('href')) print(a.attr.href)運行結果如下:
<a?href="link3.html"><span class="bold">third?item</span></a>?<class?'pyquery.pyquery.PyQuery'> link3.html link3.html在這個例子中我們首先選中 class 為 item-0 和 active 的 li 節點內的 a 節點,它的類型是 pyquery 類型。然后調用 attr 方法。在這個方法中傳入屬性的名稱,就可以得到屬性值了。此外,也可以通過調用 attr 屬性來獲取屬性值。
遍歷獲取所有的 a 節點的屬性:
from?pyquery?import?PyQuery?as?pq 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> '''doc?=?pq(html) nodes?=?doc('a') for?item?in?nodes.items():print(item.attr('href'))運行結果如下:
link2.html link3.html link4.html link5.html因此,在進行屬性獲取時,先要觀察返回節點是一個還是多個,如果是多個,則需要遍歷才能依次獲取每個節點的屬性。
獲取文本
獲取節點之后的另一個主要操作就是獲取其內部文本了,此時可以調用 text 方法來實現:
from?pyquery?import?PyQuery?as?pq 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> '''doc?=?pq(html) nodes?=?doc('li') for?item?in?nodes.items():print(item.text())運行結果如下:
first?item second?item third?item fourth?item fifth?item三、爬取B站視頻熱搜榜單數據
下面用一個爬取B站視頻熱搜榜單數據的實例來熟悉 PyQuery 的使用
URL:https://www.bilibili.com/ranking?spm_id_from=333.851.b_7072696d61727950616765546162.3
1. 發送請求
import?requests #?偽裝請求頭 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" } #?目標URL url?=?'https://www.bilibili.com/v/popular/rank/all' #?request請求獲取的文本傳入PyQuery初始化 resp?=?requests.get(url,?headers=headers) print(resp.status_code) print(resp.text)在上面的代碼中,我們完成了以下幾件事:
導入 requests 庫
偽裝請求頭
使用 get 方法構造請求
打印查看請求的狀態碼和網頁源代碼文本
2. 解析提取數據和保存
from?pyquery?import?PyQuery?as?pq import?openpyxlwb?=?openpyxl.Workbook()????#?初始化工作簿對象 sheet?=?wb.active???????????#?獲取活動的工作表 #?添加列名 sheet.append(['rank',?'title',?'link',?'bicon_play',?'bicon_view',?'creator',?'score']) doc?=?pq(resp) #?獲取class=rank-list?下所有li節點內容 #?遍歷li節點 con1?=?doc('.rank-list?li') for?item?in?con1.items():rank?=?item('.num').text()???#?排名title?=?item('.content?.info?a:first-child').text()?????????#?視頻標題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?openpyxlwb?=?openpyxl.Workbook()????#?初始化工作簿對象 sheet?=?wb.active???????????#?獲取活動的工作表 #?添加列名 sheet.append(['rank',?'title',?'link',?'bicon_play',?'bicon_view',?'creator',?'score']) #?日志輸出配置 logging.basicConfig(level=logging.INFO,?format='%(asctime)s?-?%(levelname)s:?%(message)s') #?偽裝請求頭 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" } #?目標URL url?=?'https://www.bilibili.com/v/popular/rank/all' #?request請求獲取的文本傳入PyQuery初始化 resp?=?requests.get(url,?headers=headers).text doc?=?pq(resp) #?獲取class=rank-list?下所有li節點內容 #?遍歷li節點 con1?=?doc('.rank-list?li') for?item?in?con1.items():rank?=?item('.num').text()???#?排名title?=?item('.content?.info?a:first-child').text()?????????#?視頻標題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')運行效果如下:
作者:葉庭云
CSDN:https://yetingyun.blog.csdn.net/
推薦閱讀 誤執行了rm -fr /*之后,除了跑路還能怎么辦?!程序員必備58個網站匯總大幅提高生產力:你需要了解的十大Jupyter Lab插件----------? END? ----------總結
以上是生活随笔為你收集整理的爬虫解析利器PyQuery详解及使用实践的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大一新生开发的小工具火了!不一样的 Py
- 下一篇: 漫画 | 程序员的悲哀是什么?