天天看點

【0基礎學爬蟲】爬蟲基礎之自動化工具 Pyppeteer 的使用

作者:K哥爬蟲
【0基礎學爬蟲】爬蟲基礎之自動化工具 Pyppeteer 的使用
大資料時代,各行各業對資料采集的需求日益增多,網絡爬蟲的運用也更為廣泛,越來越多的人開始學習網絡爬蟲這項技術,K哥爬蟲此前已經推出不少爬蟲進階、逆向相關文章,為實作從易到難全方位覆寫,特設【0基礎學爬蟲】專欄,幫助小白快速入門爬蟲,本期為自動化工具 Pyppeteer 的使用。

概述

前兩期文章中已經介紹到了 Selenium 與 Playwright 的使用方法,它們的功能都非常強大。而本期要講的 Pyppeteer 與 Playwright 一緻,都可以作為 Selenium 的替代者來使用。且與 Playwright 相比,Pyppeteer 的使用更加簡單。

Pyppeteer 的使用

介紹

在上上期文章中,我們介紹了 Selenium 隐藏特征的方法,其中使用到了 stealth.min.js 檔案。在介紹檔案的來源時我們提到了 Puppeteer,Puppeteer是一個基于 Node.js 的自動化工具。而這期要将的 Pyppeteer 就是 Puppeteer 的 Python 版。

Pyppeteer 是一個使用 Python 語言封裝的 Google Chrome 浏覽器的非官方 API。它可以用來進行自動化測試、網站爬蟲和資料抓取等工作。

Pyppeteer 的底層是通過調用 Chrome 浏覽器的 DevTools Protocol 接口來實作的。DevTools Protocol 是一個基于 WebSocket 協定的遠端調試接口,可以讓開發者控制和檢查 Chrome 浏覽器的行為。Pyppeteer 利用這個接口實作了對 Chrome 浏覽器的完全控制,包括加載頁面、模拟使用者操作、擷取頁面内容等等。

Pyppeteer 支援 Python 3.6 及以上版本,并且可以在 Windows、macOS 和 Linux 等作業系統上運作。它提供了簡單易用的 API,可以友善地模拟使用者在浏覽器上的操作,例如點選連結、填寫表單、觸發事件等等。同時,它也支援對浏覽器的調試、截屏、PDF 導出等進階功能。

Pyppeteer 的使用方式與其他 Python 庫類似,可以通過 pip 包管理器進行安裝。除了 Pyppeteer 本身外,還需要安裝 asyncio 庫和一個相容的 Chrome 浏覽器版本。在安裝完成後,可以通過 Python 代碼來控制浏覽器的行為,實作各種自動化測試或資料抓取的任務。

安裝

Pyppeteer 的安裝與 Playwright 相似。

Pyppeteer 采用了async機制,是以必須使用Python 3.5及以上版本。

首先使用 pip 安裝 Pyppeteer 包:

pip install pyppeteer

安裝完成後可以選擇執行 pyppeteer-install 下載下傳用于 pyppeteer 的 chromium,這一步可以省略,因為第一次運作 Pyppeteer 時會自動檢測是否安裝了 chromium 浏覽器,如果沒有安裝程式會自動進行安裝配置。

使用

前兩期文章中介紹到了 Selenium 與 Playwright 庫的使用方法,因為自動化庫的使用大同小異,是以這裡隻介紹 Pyppeteer 中比較特殊的方法

Pyppeteer 基于異步實作,是以它支援異步操作。

啟動

以百度熱搜榜為例:

import asyncio
from pyppeteer import launch


async def main():
    browser = await launch(headless=False)
    page = await browser.newPage()
    await page.goto('https://top.baidu.com/board?tab=realtime')
    await browser.close()

asyncio.get_event_loop().run_until_complete(main())
           

示例代碼中使用 launch 方法建立了一個浏覽器對象 browser ,設定了 headless=False 來關閉無頭模式,這一行代碼的作用相當于啟動一個浏覽器,await的作用就是等待浏覽器啟動完畢。

建立完浏覽器後,使用到了 newPage 方法,建立了一個 Page 對象,這一步相當于打開了一個新的标簽頁,通過 await 等待标簽頁建立完畢,然後調用 goto 方法打開目标網址,最後使用 close 方法關閉浏覽器。

launch詳解

launch 方法用于啟動浏覽器程序并傳回浏覽器執行個體,它包含了多個參數:

參數 描述
ignoreHTTPSErrors(bool) 是否忽略HTTPS錯誤。預設為 False
headless(bool) 是否開啟無頭模式。預設為True
executablePath (str) 可執行檔案的路徑,設定該參數可以指定已有的 Chrome 或 Chromium 浏覽器。
slowMo (int | float) 傳入指定時間(毫秒),用于延緩 Pyppeteer 的一些模拟操作。
args (List [str]) 傳遞給浏覽器的額外參數。
dumpio(bool) 是否将 Pyppeteer 的輸出資訊傳給 process.stdout和process.stderr。預設為False。
userDataDir (str) 使用者資料檔案夾。
env(dict) 浏覽器環境。預設與 Python 程序相同。
devtools(bool) 是否為每個标簽頁打開 DevTools 面闆,預設為False,如果該參數為 True,則 headless 會被強制設定為 False。
logLevel(int | str) 日志級别。預設值與根記錄器相同。
autoClose(bool) 腳本完成時自動關閉浏覽器程序。預設為True。
loop(asyncio.AbstractEventLoop) 事件循環。

禁用提示條

與 Selenium 一樣,Pyppeteer 控制浏覽器時會提示 Chrome 正受到自動測試軟體的控制。可以通過 設定 launch 方法中的 args 參數來關閉提示。

browser = await launch(headless=False, args=['--disable-infobars'])
           

使用者資料持久化

自動化工具如 Selenium 、Playwright 都有一個特征,就是每一次運作的時候建立的都是一個全新的浏覽器,它不會記錄使用者之前的行為。如第一次運作時我登入了某個網站,而第二次運作時再次進入該網站時依舊需要登入。這是因為自動化工具沒有記錄使用者行為資訊。Pyppeteer 中,如果需要記錄使用者的行為資訊,可以通過設定 launch 方法中的 userDataDir 方法來實作。

browser = await launch(headless=False, args=['--disable-infobars'], userDataDir='./userdata')
           

設定了使用者資料檔案夾後運作代碼,會生成一個 userdata 檔案夾,其中就存儲着使用者上次控制浏覽器時記錄的一些行為資料。

【0基礎學爬蟲】爬蟲基礎之自動化工具 Pyppeteer 的使用

執行 JS 語句

import asyncio
from pyppeteer import launch


async def main():
    browser = await launch(headless=False)
    page = await browser.newPage()
    await page.goto('https://top.baidu.com/board?tab=realtime')
    dimensions = await page.evaluate('''() => {
           return {
               width: document.documentElement.clientWidth,
               height: document.documentElement.clientHeight,
               deviceScaleFactor: window.devicePixelRatio,
           }
       }''')
    print(dimensions)
    await browser.close()
# {'width': 783, 'height': 583, 'deviceScaleFactor': 1}
           

通過調用 Page 對象下的 evaluate 方法可以執行一段 JS 語句。

反檢測

Pyppeteer 的反檢測方式與 Selenium 和 Playwright 有些差別,但是思想是一樣的。

首先需要安裝 pyppeteer_stealth 庫,它的作用就是用來隐藏特征。

pip install pyppeteer_stealth

以無頭模式為例:

import asyncio
from pyppeteer import launch
from pyppeteer_stealth import stealth


async def main():
    browser = await launch()
    page = await browser.newPage()
    # 隐藏特征
    await stealth(page)
    
    await page.goto('https://bot.sannysoft.com/')
    await page.screenshot(path='page.png')
    await browser.close()

asyncio.get_event_loop().run_until_complete(main())
           

隐藏特征前:

【0基礎學爬蟲】爬蟲基礎之自動化工具 Pyppeteer 的使用

隐藏特征後:

【0基礎學爬蟲】爬蟲基礎之自動化工具 Pyppeteer 的使用

3

等待

waitForSelector :等待符合條件的節點加載完成

waitForFunction :等待某個 JavaScript 方法執行完畢或傳回結果

waitForRequest :等待某個特定的請求發出

waitForResponse :等待某個特定請求對應的響應

waitForNavigation :等待頁面跳轉,如果頁面加載失敗則抛出異常

waitFor :通用等待

waitForXpath :等待符合 Xpath 的節點加載出來

選擇器

Pyppeteer 提供了一些比較有意思的選擇器方法。

J() :傳回比對到的第一個節點,等同于 querySelector 方法。

JJ() :傳回比對到的所有節點,等同于 querySelectorAll 方法。

JJeval() :執行 JS 腳本并傳回一個 JSON 對象,等同于 querySelectorAllEval 方法。

Jeval() :執行 JS 腳本并傳回執行結果,等同于 querySelectorEval 方法。

Jx() :通過 Xpath 比對符合條件的内容,等同于 xpath 方法。

import asyncio
from pyppeteer import launch

async def main():
    browser = await launch(headless=False)
    page = await browser.newPage()
    await page.goto('https://top.baidu.com/board?tab=realtime')
    # 等待元素加載
    await page.waitForXPath('//div[@class="c-single-text-ellipsis"]')
    element_j = await page.J('.c-single-text-ellipsis')
    element_jj = await page.JJ('.c-single-text-ellipsis')
    # 列印元素的文本資訊
    print(await (await element_j.getProperty('textContent')).jsonValue())
    for element in element_jj:
        # 列印元素的文本資訊
        print(await (await element.getProperty('textContent')).jsonValue())

    await browser.close()

asyncio.get_event_loop().run_until_complete(main())
"""
運作結果:
青年強則國家強 
青年強則國家強 
烏代表舉自家國旗挑釁暴揍俄代表 
英王加冕禮彩排:黃金鑽石馬車亮眼 
平凡崗位上的奮鬥故事 
俞敏洪建議24節氣都放假 
7人吃自助4小時炫300多個螃蟹 
  .
  .
  .
"""
           

總結

Pyppeteer 類似于輕量級的 Playwright ,它使用起來更加簡單,且 Pyppeteer 與 Playwright 一樣都支援異步,性能方面也比較強。缺點就是它基于 Chromium 核心,資源消耗比較大,不支援其它浏覽器,而且 Pyppeteer 的作者近年來都沒對該庫進行維護,導緻存在一些 bug。

繼續閱讀