Node爬蟲工具Puppeteer入門教程實(shí)踐
【Puppeteer概要】
- Puppeteer 是一個(gè) Node 庫(kù),它提供了一個(gè)高級(jí) API 來通過 DevTools 協(xié)議控制 Chromium 或 Chrome。 Puppeteer API 是分層次的,反映了瀏覽器結(jié)構(gòu)。
- Puppeteer 使用 DevTools 協(xié)議 與瀏覽器進(jìn)行通信。
- Browser 實(shí)例可以擁有瀏覽器上下文。
- BrowserContext 實(shí)例定義了一個(gè)瀏覽會(huì)話并可擁有多個(gè)頁(yè)面。
- Page 至少有一個(gè)框架:主框架。 可能還有其他框架由 iframe 或 框架標(biāo)簽 創(chuàng)建。
- frame 至少有一個(gè)執(zhí)行上下文 - 默認(rèn)的執(zhí)行上下文 - 框架的 JavaScript 被執(zhí)行。 一個(gè)框架可能有額外的與 擴(kuò)展 關(guān)聯(lián)的執(zhí)行上下文。
- Worker 具有單一執(zhí)行上下文,并且便于與 WebWorkers 進(jìn)行交互。
【Puppeteer 錯(cuò)誤處理】
Error handling
- 如果
Puppeteer方法無(wú)法執(zhí)行一個(gè)請(qǐng)求,就會(huì)拋出一個(gè)錯(cuò)誤。例如,page.waitForSelector(selector[, options])選擇器如果在給定的時(shí)間范圍內(nèi)無(wú)法匹配節(jié)點(diǎn),就會(huì)失敗。 對(duì)于某些類型的錯(cuò)誤,Puppeteer使用特定的錯(cuò)誤類處理。這些類可以通過require('puppeteer/Errors')獲得。 支持的類列表:
TimeoutError 一個(gè)處理超時(shí)錯(cuò)誤的例子:
const {
TimeoutError
} = require('puppeteer/Errors'); // ...
try {
await page.waitForSelector('.foo');
} catch(e) {
if (e instanceof TimeoutError) {
// 如果超時(shí),做一些處理。
}
}Puppeteer Working with Chrome Extensions
Puppeteer可以用來測(cè)試Chrome擴(kuò)展
注意
Chrome / Chromium擴(kuò)展當(dāng)前只能在非無(wú)頭模式下使用。
下面的代碼用來處理擴(kuò)展的 background page,該擴(kuò)展的代碼在 ./my-extension:
const puppeteer = require('puppeteer'); (async() = > {
const pathToExtension = require('path').join(__dirname, 'my-extension');
const browser = puppeteer.launch({
headless: false,
args: [`--disable - extensions - except = $ {
pathToExtension
}`, `--load - extension = $ {
pathToExtension
}`]
});
const targets = await browser.targets();
const backgroundPageTarget = targets.find(target = >target.type() === 'background_page');
const backgroundPage = await backgroundPageTarget.page(); // 像處理任何其他頁(yè)面一樣測(cè)試背景頁(yè)面。 await browser.close();})();【Puppeteer class:puppeteer】
Puppeteer模塊提供了一種啟動(dòng)Chromium實(shí)例的方法。 下面就是使用Puppeteer進(jìn)行自動(dòng)化的一個(gè)典型示例:
const puppeteer = require('puppeteer');
puppeteer.launch().then(async browser = >{
const page = await browser.newPage();
await page.goto('https://www.google.com'); // 其他操作... await browser.close();});Methods
- puppeteer.connect(options)v0.9.0
- puppeteer.createBrowserFetcher([options])v0.9.0
- puppeteer.defaultArgs([options])v0.9.0
- puppeteer.executablePath()v0.9.0
- puppeteer.launch([options])v0.9.0
Methods
puppeteer.connect(options)v0.9.0
options<Object>browserWSEndpoint<string>一個(gè) 瀏覽器 websocket 端點(diǎn)鏈接。ignoreHTTPSErrors<boolean>是否在導(dǎo)航期間忽略 HTTPS 錯(cuò)誤. 默認(rèn)是false。defaultViewport<?Object> 為每個(gè)頁(yè)面設(shè)置一個(gè)默認(rèn)視口大小。默認(rèn)是800x600。如果為 null 的話就禁用視圖口。width<number>頁(yè)面寬度像素。height<number>頁(yè)面高度像素。deviceScaleFactor<number>設(shè)置設(shè)備的縮放(可以認(rèn)為是 dpr)。默認(rèn)是1。isMobile<boolean>是否在頁(yè)面中設(shè)置了meta viewport標(biāo)簽。默認(rèn)是false。hasTouch``<boolean>指定viewport是否支持觸摸事件。默認(rèn)是false。isLandscape<boolean>指定視口是否處于橫向模式。默認(rèn)是false。slowMo<number>將 Puppeteer 操作減少指定的毫秒數(shù)。這樣你就可以看清發(fā)生了什么,這很有用。returns:<Promise<Browser>>此方法將Puppeteer添加到已有的Chromium實(shí)例。
puppeteer.createBrowserFetcher([options])v0.9.0
options<Object>host<string>要使用的下載主機(jī). 默認(rèn)是https://storage.googleapis.com。path<string>下載文件夾的路徑. 默認(rèn)是<root>/.local-chromium,<root>是 puppeteer 的包根目錄。platform<string>可能的值有:mac, win32, win64, linux。默認(rèn)是當(dāng)前平臺(tái)。returns:<BrowserFetcher>
puppeteer.defaultArgs([options])v0.9.0
options<Object>設(shè)置瀏覽器可選項(xiàng)。有一下字段:headless<boolean>是否在 無(wú)頭模式 下運(yùn)行瀏覽器。默認(rèn)是true除非devtools選項(xiàng)是true。args<Array<string>>傳遞給瀏覽器實(shí)例的其他參數(shù)。可以 在這 找到 Chromium 標(biāo)志列表。userDataDir<string>用戶數(shù)據(jù)目錄 的路徑。devtools<boolean>是否為每個(gè)選項(xiàng)卡自動(dòng)打開DevTools面板。如果這個(gè)選項(xiàng)是true的話,headless選項(xiàng)將被設(shè)置為false。returns:<Array<string>>Chromium 啟動(dòng)時(shí)使用的默認(rèn)參數(shù)。
puppeteer.executablePath()v0.9.0
returns:<string>Puppeteer 希望找到綁定的Chromium的路徑。- 如果使用
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD跳過下載,則Chromium可能不存在。
puppeteer.launch([options])v0.9.0
options<Object>在瀏覽器上設(shè)置的一組可配置選項(xiàng)。 有以下字段:ignoreHTTPSErrors<boolean>是否在導(dǎo)航期間忽略HTTPS錯(cuò)誤. 默認(rèn)是false。headless<boolean>是否以 無(wú)頭模式 運(yùn)行瀏覽器。默認(rèn)是true,除非devtools選項(xiàng)是true。executablePath<string>可運(yùn)行 Chromium 或 Chrome 可執(zhí)行文件的路徑,而不是綁定的Chromium。如果executablePath是一個(gè)相對(duì)路徑,那么他相對(duì)于 當(dāng)前工作路徑 解析。slowMo<number>將 Puppeteer 操作減少指定的毫秒數(shù)。這樣你就可以看清發(fā)生了什么,這很有用。defaultViewport<?Object>為每個(gè)頁(yè)面設(shè)置一個(gè)默認(rèn)視口大小。默認(rèn)是800x600。如果為 null 的話就禁用視圖口。width<number>頁(yè)面寬度像素。height<number>頁(yè)面高度像素。deviceScaleFactor<number>設(shè)置設(shè)備的縮放(可以認(rèn)為是dpr)。默認(rèn)是1。isMobile<boolean>是否在頁(yè)面中設(shè)置了meta viewport標(biāo)簽。默認(rèn)是false。hasTouch``<boolean>指定viewport是否支持觸摸事件。默認(rèn)是false。isLandscape<boolean>指定視口是否處于橫向模式。默認(rèn)是false。args<Array<string>>傳遞給瀏覽器實(shí)例的其他參數(shù)。 這些參數(shù)可以參考 這里。- ignoreDefaultArgs <(boolean|
<Array<string>>)> 如果是true,那就不要使用puppeteer.defaultArgs()。 如果給出了數(shù)組,則過濾掉給定的默認(rèn)參數(shù)。這個(gè)選項(xiàng)請(qǐng)謹(jǐn)慎使用。默認(rèn)為false。 handleSIGINT<boolean>Ctrl-C 關(guān)閉瀏覽器進(jìn)程。默認(rèn)是true。handleSIGTERM<boolean>關(guān)閉 SIGTERM 上的瀏覽器進(jìn)程。默認(rèn)是true。handleSIGHUP<boolean>關(guān)閉 SIGHUP 上的瀏覽器進(jìn)程。默認(rèn)是true.timeout<number>等待瀏覽器實(shí)例啟動(dòng)的最長(zhǎng)時(shí)間(以毫秒為單位)。默認(rèn)是30000 (30 秒). 通過 0 來禁用超時(shí)。dumpio<boolean>是否將瀏覽器進(jìn)程標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸入到process.stdout 和 process.stderr中。默認(rèn)是false。userDataDir<string>用戶數(shù)據(jù)目錄 路徑。env<Object>指定瀏覽器可見的環(huán)境變量。默認(rèn)是process.env。devtools<boolean>是否為每個(gè)選項(xiàng)卡自動(dòng)打開DevTools面板。如果這個(gè)選項(xiàng)是true,headless選項(xiàng)將會(huì)設(shè)置成false。pipe<boolean>通過管道而不是WebSocket連接到瀏覽器。默認(rèn)是false。returns:<Promise<Browser>>瀏覽器實(shí)例支持Promise。
這個(gè)方法結(jié)合了下面3個(gè)步驟:
使用 puppeteer.defaultArgs() 作為一組默認(rèn)值來啟動(dòng) Chromium。
啟動(dòng)瀏覽器并根據(jù) executablePath ,handleSIGINT,dumpio 和其他選項(xiàng)開始管理它的進(jìn)程。 創(chuàng)建一個(gè) Browser 類的實(shí)例,并根據(jù) defaultViewport,slowMo 和 ignoreHTTPSErrors 初始化它。 ignoreDefaultArgs 選項(xiàng)可用于自定義(1)步驟的行為。 例如,要從參數(shù)中過濾掉 --mute-audio:
const browser = await puppeteer.launch({
ignoreDefaultArgs: ['--mute-audio']
});
復(fù)制代碼Puppeteer 瀏覽器
- extends:
EventEmitter當(dāng)Puppeteer連接到一個(gè)Chromium實(shí)例的時(shí)候會(huì)通過puppeteer.launch或puppeteer.connect創(chuàng)建一個(gè)Browser對(duì)象。 下面是使用Browser創(chuàng)建Page的例子
const puppeteer = require('puppeteer');
puppeteer.launch().then(async browser = >{
const page = await browser.newPage();
await page.goto('https://example.com');
await browser.close();
});- 一個(gè)斷開連接和重連到 Browser 的例子:
const puppeteer = require('puppeteer');
puppeteer.launch().then(async browser = >{ // 存儲(chǔ)節(jié)點(diǎn)以便能重新連接到 Chromium
const browserWSEndpoint = browser.wsEndpoint(); // 從 Chromium 斷開和 puppeteer 的連接 browser.disconnect(); // 使用節(jié)點(diǎn)來重新建立連接
const browser2 = await puppeteer.connect({browserWSEndpoint}); // 關(guān)閉 Chromium
await browser2.close();});Puppeteer 頁(yè)面
Page提供操作一個(gè)tab頁(yè)或者extensionbackgroundpage的方法。一個(gè)Browser實(shí)例可以有多個(gè)Page實(shí)例。 下面的例子創(chuàng)建一個(gè)Page實(shí)例,導(dǎo)航到一個(gè)url,然后保存截圖:
const puppeteer = require('puppeteer');
puppeteer.launch().then(async browser = >{
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({
path: 'screenshot.png'
});
await browser.close();
});- Page會(huì)觸發(fā)多種事件(下面描述的),可以用 node原生的方法 來捕獲處理,比如
on,once或者removeListener。下面的例子捕獲了一個(gè)page實(shí)例的load事件,打印了一句話:
page.once('load', () => console.log('Page loaded!'));- 可以用
removeListener取消對(duì)事件的監(jiān)聽:
function logRequest(interceptedRequest) {
console.log('A request was made:', interceptedRequest.url());
}
page.on('request', logRequest); // 一段時(shí)間后...page.removeListener('request', logRequest);Methods
page.$(selector)v0.9.0
selector
<string>選擇器 返回:<Promise<?ElementHandle>>此方法在頁(yè)面內(nèi)執(zhí)行
document.querySelector。如果沒有元素匹配指定選擇器,返回值是 null。page.mainFrame().$(selector) 的簡(jiǎn)寫。
page.$$(selector)v0.9.0
selector
<string>選擇器返回:
<Promise<Array<ElementHandle>>>此方法在頁(yè)面內(nèi)執(zhí)行
document.querySelectorAll。如果沒有元素匹配指定選擇器,返回值是 []。page.mainFrame().$$(selector)的簡(jiǎn)寫。
page.waitForSelector(".index-content .click-zoom a")
- 等待頁(yè)面元素加載完成
await page.waitForSelector(".index-content .click-zoom a")page.waitFor(1000)
- 等待1000毫秒執(zhí)行
await page.waitFor(1000)
page.click('.btn')
await page.click('.btn')- 點(diǎn)擊class 為btn元素
page.evaluate
- 執(zhí)行原生js
await page.evaluate(() => {
document.getElementById("HD_CheckIn").value = "2020-07-11";
})示例
- 代碼執(zhí)行
- 安裝 puppeteer 依賴包
- node xxx.js 運(yùn)行js
/**
* 爬取游戲站數(shù)據(jù) https://game.pipajam.com/
*/
const fs = require('fs')
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: false,
args: ['--start-maximized', '--disable-infobars'],
width: 1600,
height: 900
});
// 1、 創(chuàng)建兩個(gè)頁(yè)面
const page = await browser.newPage();
const page2 = await browser.newPage();
// 2、進(jìn)入首頁(yè)
await page.goto(
'https://game.pipajam.com/'
);
// 3、等待頁(yè)面游戲數(shù)據(jù)元素加載完成
await page.waitForSelector(".index-content .click-zoom a")
// 4、獲取所以游戲鏈接 游戲名稱
const list = await page.$$eval(".index-content .click-zoom a", (el => el.map(el => ([el.href, el.getElementsByTagName('h6')[0].innerText]))));
console.log(list);
let len = list.length, index = 0, data = []
// 5、調(diào)用函數(shù) 組裝數(shù)據(jù)
mainFun()
async function mainFun () {
try {
// 6、開啟page2 頁(yè)面 獲取游戲詳情數(shù)據(jù)
await page2.goto(
list[index][0],{
timeout: 0
}
);
// 7、等待詳情卡片加載完成
await page2.waitForSelector(".play-game-card .play-game-card-center")
// 8、獲取游戲鏈接地址 圖片地址
const item = await page2.$eval(".play-game-card .play-game-card-center", (el => [el.getElementsByTagName('p')[0].innerHTML, el.getElementsByTagName('img')[0].src]));
await page2.click('.play-game-card .play-game-card-center a')
const url = await page2.evaluate(param => window.location.href, "參數(shù)");
// 9、組裝數(shù)據(jù)
data.push({
description: item[0],
img: item[1],
instructton: "",
keyfeatures: "",
name: list[index][1],
published: "Mon Oct 08 2018",
tags: [],
url,
type: 'Children\'s intelligence',
})
console.log('以寫入第' + (index+1) + '數(shù)據(jù)。');
// 10、獲取所以游戲數(shù)據(jù) 并寫入指定json 文件
++index < len ? mainFun() : fs.writeFile('../../json/Game/pipajam.json', JSON.stringify(data), () => {})
} catch (error) {
console.log(error, 'err')
}
}
})();到此這篇關(guān)于Node爬蟲工具Puppeteer入門教程實(shí)踐的文章就介紹到這了,更多相關(guān)Node Puppeteer入門內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Express+Nodejs 下的登錄攔截實(shí)現(xiàn)代碼
本篇文章主要介紹了Express+Nodejs 下的登錄攔截實(shí)現(xiàn)代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-07-07
Node.js使用Express創(chuàng)建Web項(xiàng)目詳細(xì)教程
如果需要入門使用node.js進(jìn)行web開發(fā),正在學(xué)習(xí) nodejs web開發(fā)指南 的和想快速了解node.js web開發(fā)模式的朋友,相信本文是有一定幫助意義的。2017-03-03
node.js文件上傳重命名以及移動(dòng)位置的示例代碼
本篇文章主要介紹了node.js文件上傳重命名以及移動(dòng)位置的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-01-01
Nodejs多站點(diǎn)切換Htpps協(xié)議詳解及簡(jiǎn)單實(shí)例
這篇文章主要介紹了Nodejs多站點(diǎn)切換Htpps協(xié)議詳解及簡(jiǎn)單實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-02-02
node.js 用socket實(shí)現(xiàn)聊天的示例代碼
本篇文章主要介紹了node.js 用socket實(shí)現(xiàn)聊天的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10

