天天看點

使用Puppeteer進行資料抓取(二)——Page對象

page對象是puppeteer最常用的對象,它可以認為是chrome的一個tab頁,主要的頁面操作都是通過它進行的。Google的官方文檔詳細介紹了page對象的使用,這裡我隻是簡單的小結一下。

頁面模拟設定相關函數有如下幾個,

page.setViewport: 設定視圖大小

page.setUserAget: 設定UserAgent

page.SetCookie: 設定Cookie

另外,也可以使用emulate函數提供快捷設定,puppeteer/DeviceDescriptors還提供了常用裝置的預設

頁面跳轉相關函數有如下幾個,

page.goto(url, options)

page.goBack(options)

page.goForward(options)

page.reload(options)

其中比較常用的是page.goto,相當于在浏覽器中輸入了位址,然後回車。此外,也可以同通過執行js跳轉和模拟點選link跳轉。

常用的元素函數選擇有:

page.$(selector)

page.$$(selector)

它們的功能類似于document.querySelector和document.querySelectorAll。

它們傳回的對象是<Promise<?ElementHandle>>,可以用它判斷某元素是否存在,也可以對ElementHandle執行相應操作,具體在後面的ElementHandle中介紹。

另外,還有一個使用xpath的select版本。

page.$x(expression)

雖然這個用的相對少點,但也還是非常有用的。

page本身提供原始的mouse和keyboard的模拟輸入類。

page.mouse

page.keyboard

但同時也提供更友善快捷的模拟輸入函數

page.click(selector[, options])        在被選擇元素上模拟點選

page.type(selector, text[, options])    在被選擇的輸入框中輸入

page.hover(selector)                模拟滑鼠移動到被選擇元素上

page.select(selector, ...values)        在被選擇元素上模拟選擇select選項

page.tap(selector)                    在被選擇元素上模拟觸摸

當我們使用page.goto等跳轉函數主動跳轉頁面時,本身該函數就是可以異步等待的,可以直接使用await等待跳轉完成。

除此之外,系統也提供了如下等待函數

page.waitForNavigation(options)

page.waitFor(selectorOrFunctionOrTimeout[, options[, ...args]])

page.waitForSelector(selector[, options])

page.waitForXPath(xpath[, options])

page.waitForFunction(pageFunction[, options[, ...args]])

其中最常用的是page.waitForNavigation,常用于等待跳轉結束,例如點選搜尋按鈕後,等待跳轉至搜尋結果頁面。

const navigationPromise = page.waitForNavigation();

await page.click('a.my-link'); 

await navigationPromise; 

執行腳本最常用的函數是page.evaluate,它類似于在控制台中執行指令。

console.log(await page.evaluate('1 + 2'));

var title = await

page.evaluate('document.title')

它也可以用來執行寫好的node函數,實際上該函數是在浏覽器中執行的,但可以像本地函數一樣編寫,還支援參數傳值。

var title = await page.evaluate(async (i) => {

    return document.title + ' ' + i;

}, 'hello');

console.log(title);

雖然這node函數不能調試,但仍然是有非常大的好處的,

不用考慮字元串轉義的問題,書寫起來非常直接

腳本在IDE中有高亮顯示和智能提示的,寫起來更加友善

另外,還有幾個其它的執行腳本的函數,應用于不同的場合,也是非常有用的。

page.evaluateHandle(pageFunction, ...args)

page.evaluateOnNewDocument(pageFunction, ...args)

page.$$eval(selector, pageFunction[, ...args])

page.$eval(selector, pageFunction[, ...args])

例如:

const searchValue = await page.$eval('#search', el => el.value);

const preloadHref = await page.$eval('link[rel=preload]', el => el.href);

const html = await page.$eval('.main-container', e => e.outerHTML);

puppeteer提供了一些檢視頁面資訊的函數,

page.url()

page.content()

page.frames()

page.mainFrame()

page.metrics()

page.target()

page.title()

page.viewport()

page.setRequestInterception提供了中斷請求的機制,例如,我們可以通過它實作一個無圖模式。

await page.setRequestInterception(true);

page.on('request', interceptedRequest => {

    if (interceptedRequest.url().endsWith('.png') || interceptedRequest.url().endsWith('.jpg'))

        interceptedRequest.abort();

    else

        interceptedRequest.continue();

});

await page.goto('https://example.com');

這裡有一個interceptedRequest對象,它提供了三種響應模式:abort、continue和respond。

内容儲存主要包括注入javascript和style,都是非常有用的函數。

page.addScriptTag(options)

page.addStyleTag(options)

puppteer提供了一系列事件的通知:

<col>

close

frameattached

pageerror

console

framedetached

request

dialog

framenavigated

requestfailed

domcontentloaded

load

requestfinished

error

metrics

response

簡單的示例如下:

page.on('load',

    async () =&gt; {

        console.log('page loading done, start fetch...');

    });

内容儲存主要包括儲存為pdf和截圖

page.pdf(options)

page.screenshot([options])

另外,還有一些用的較少的函數,但一旦用上也是能解決比較問題的。

page.authenticate(credentials)

page.bringToFront()

page.browser()

page.close(options)

page.coverage

page.exposeFunction(name, puppeteerFunction)

page.queryObjects(prototypeHandle)

page.setBypassCSP(enabled)

page.setCacheEnabled(enabled)

page.setContent(html)

page.setDefaultNavigationTimeout(timeout)

page.setJavaScriptEnabled(enabled)

page.setOfflineMode(enabled)

page.tracing

除了page對象外,還有其他的幾個對象,如果有空再詳細的介紹一下。