透過Puppeteer使用Node.js操作Headless Chrome
Puppeteer
是Node.js的Headless Chrome API
透過Node.js可輕易的操作Chrome
可操作跳頁、點選按鈕、上傳檔案、爬資料、頁面截圖等任何我們人可以透過chrome的動作
用途上可用於爬蟲、前端自動化測試、自動操作機器人
甚至可配合其他通訊軟體API像是Slack、Line Notify來發送訊息、截圖
安裝
首先要確定系統上有安裝Chrome
接者使用yarn或npm安裝即可
# npm
npm i puppeteer
# yarn
yarn add puppeteer
啟動Chrome瀏覽器
常用參數https://hakkatv.dgfactor.com/
- headless: 是否使用headless模式,若在開發模式希望可以看到畫面,可以先設定為false
- executablePath: chrome的binary file path
- ignoreHTTPSErrors: 忽略HTTPS錯誤
基本使用範例
這段範例將進行
- 開啟Google Chrome
- 開啟新分頁
- 分頁前往Google首頁
- 找到搜尋列並輸入"Puppeteer"
- 再按下Enter進行搜尋
const puppeteer = require('puppeteer')
class DemoGoogleSearch {
constructor() {
this.start()
}
async start() {
// 開啟chrome
this.browser = await puppeteer.launch({
headless: false, // 關閉headless模式, debug用
executablePath: '/usr/bin/google-chrome', // 設定chrome可執行檔位置
})
// 建立新分頁
this.page = await this.browser.newPage()
// 前往google網址
await this.page.goto('https://www.google.com/', {
waitUntil: 'networkidle0',
})
// 找到input attribute為"Google 搜尋"的DOM
await this.page.waitForSelector(`input[title*="Google 搜尋"]`)
// 對input attribute為"Google 搜尋"的DOM輸入"Puppeteer"
await this.page.type(`input[title*="Google 搜尋"]`, 'Puppeteer')
// 按下Enter按鈕
await this.page.keyboard.press('Enter')
}
}
new DemoGoogleSearch()
page.goto
這個是最常用到的功能
用來前往某個網址
且通常會使用waitUntil: 'networkidle0'選項
確認500ms內無任何新的請求才完成這個page.goto async method
詳細可參考官方文件page.goto說明
等待DOM出現
通常會需要等到頁面載入某個DOM出現
才能接著執行後續動作
因此可以看到Puppeteer文件有著各種類型的waitFor method
我最常用的則是waitForSelector(透過document.querySelectorAll選擇DOM)
或是waitForXPath(透過XPath來選擇DOM)
取得DOM內的文字
首先透過page.waitFor取得ElementHandle
並透過以下方式取得DOM內的文字(text)
const dom = await this.page.waitForSelector('input[class*="foobar"]')
const textObject = await targetDom.getProperty('textContent')
const text = textObject._remoteObject.value
截圖
透過page.screenshot method即可輕鬆接圖並透過path存到指定位置
await this.page.screenshot({
path: '/tmp/foobar.png',
})
其他常用設定
viewPort
透過page.setViewPort method可設定分頁的view port size
當截圖希望模擬指定裝置大小的時候很好用
await this.page.setViewport({
width: 1600,
height: 900,
})
Chroem語言
若需要分頁開啟時指定語言
可使用此方式來指定
await this.page.evaluateOnNewDocument(() => {
Object.defineProperty(navigator, 'language', {
get: () => 'zh-TW'
});
Object.defineProperty(navigator, 'languages', {
get: () => ['zh-TW', 'zh'],
});
});
停用網站的通知請求dialog
有些網站會使用Notification.requestPermission來跳出dialog請求通知權限
若不希望出現此dialog
可使用args參數加入--disable-notifications選項停用notification
this.browser = await puppeteer.launch({
executablePath: '/usr/bin/google-chrome',
args: ['--disable-notifications']
})