page對象是puppeteer最常用的對象,它可以認為是chrome的一個tab頁,主要的頁面操作都是通過它進行的。Google的官方文檔詳細介紹了page對象的使用,這里我只是簡單的小結一下。
客戶端模擬
頁面模擬設置相關函數有如下幾個,
- page.setViewport: 設置視圖大小
- page.setUserAget: 設置UserAgent
- page.SetCookie: 設置Cookie
另外,也可以使用emulate函數提供快捷設置,puppeteer/DeviceDescriptors還提供了常用設備的預設
const puppeteer = require('puppeteer');
const devices = require('puppeteer/DeviceDescriptors');|
const iPhone = devices['iPhone 6'];
puppeteer.launch().then(async browser => {
const page = await browser.newPage();
await page.emulate(iPhone);
await page.goto('https://www.google.com');
// other actions...
await browser.close();
});
除此之外,還可以使用page.setExtraHTTPHeaders設置其它HttpHeader
頁面跳轉
頁面跳轉相關函數有如下幾個,
- 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.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;
另外,我們如果需要更細粒度的等待,可以使用其它幾個wait函數,如如果我們要等待某圖片的第一次加載。
執行腳本
執行腳本最常用的函數是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,都是非常有用的函數。
事件
puppteer提供了一系列事件的通知:
close |
frameattached |
pageerror |
console |
framedetached |
request |
dialog |
framenavigated |
requestfailed |
domcontentloaded |
load |
requestfinished |
error |
metrics |
response |
簡單的示例如下:
page.on('load',
async () => {
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對象外,還有其他的幾個對象,如果有空再詳細的介紹一下。