前面寫過(guò)的phantomJs,研究幾天后發(fā)現(xiàn)phantomJs雖然在業(yè)內(nèi)有一定的影響力,但后繼乏力,主要還是缺乏維護(hù)人員,導(dǎo)致項(xiàng)目依賴的chrome內(nèi)核版本太低,無(wú)人解決的BUG太多(1000+),現(xiàn)在這個(gè)環(huán)境已經(jīng)越來(lái)越滿足不了真實(shí)的前端模擬以及各種新的特性需求(比如高版本Chrome的執(zhí)行環(huán)境特性,比如JS執(zhí)行和渲染等都相差很大),GitHub參照:點(diǎn)擊這里。
谷歌瀏覽器在17年自行開(kāi)發(fā)了Chrome Headless特性,并與之同時(shí)推出了puppeteer,可以理解成我們?nèi)粘J褂玫腃hrome的無(wú)界面版本以及對(duì)其進(jìn)行操控的js接口套裝,官方介紹參照:點(diǎn)擊這里。
借助puppeteer,我們實(shí)際上是通過(guò)調(diào)用Chrome DevTools開(kāi)放的接口與Chrome通信,Chrome DevTools的接口很復(fù)雜,但puppeteer對(duì)其進(jìn)行了封裝,我們調(diào)用起來(lái)還是很方便的。寫幾個(gè)簡(jiǎn)單例子:
Demo1:打開(kāi)百度,并保存截圖
下面代碼保存在 baidu.js中(當(dāng)然需要提前初始化package.json等操作,默認(rèn)大家都了解的):
const puppeteer = require('puppeteer');
(async () => {
? ? const browser = await puppeteer.launch({
? ? ? ? headless: true
? ? })
? ? const page = await browser.newPage()
? ? await page.goto('http://www.baidu.com')
? ? await page.screenshot({
? ? ? ? path: 'c:/temp/baidu.png'
? ? })
})()
通過(guò) node baidu.js 就可以將截圖保存下來(lái),下面是效果圖:

當(dāng)然上面的只是最簡(jiǎn)單的操作,涉及到的API也少,查看完整API可以:點(diǎn)擊這里
再來(lái)豐富下上面的操作:
Demo2:iPhoneX模式打開(kāi)百度,并保存截圖
代碼如下,相比demo1其實(shí)只是多了幾行代碼,也就是調(diào)用了 page.emulate方法按照給定設(shè)備對(duì)頁(yè)面的尺寸進(jìn)行了設(shè)定:
const devices = require('puppeteer/DeviceDescriptors')
const puppeteer = require('puppeteer');
(async () => {
? ? const browser = await puppeteer.launch({
? ? ? ? headless: true
? ? })
? ? const page = await browser.newPage()
? ? await page.emulate(devices['iPhone X'])
? ? await page.goto('http://www.baidu.com')
? ? await page.screenshot({
? ? ? ? path: 'c:/temp/baidu_iphone_X.png'
? ? })
})()
截圖如下:

針對(duì)device設(shè)備的完整列表,可以參照源碼:點(diǎn)擊這里,(PS:大家都要學(xué)會(huì)找源碼,讀源碼,項(xiàng)目中經(jīng)常碰到引用插件的問(wèn)題,通過(guò)查找源碼可以加深對(duì)問(wèn)題的理解,才可能真正解決)
上面兩個(gè)例子都是比較簡(jiǎn)單的操作,只有加載頁(yè)面和截圖,沒(méi)有用戶交互操作,我們繼續(xù)
Demo3:iPhoneX模式打開(kāi)百度,搜索puppeteer關(guān)鍵字,跳轉(zhuǎn)到查詢結(jié)果頁(yè)面后,保存截圖
這個(gè)demo真正增加的步驟也就三個(gè):
找到 輸入文本框 并填充關(guān)鍵字 puppeteer;
找到 百度一下 按鈕并點(diǎn)擊;
等待頁(yè)面跳轉(zhuǎn)顯示查詢結(jié)果;
代碼如下:
const devices = require('puppeteer/DeviceDescriptors')
const puppeteer = require('puppeteer');
(async () => {
? ? const browser = await puppeteer.launch({
? ? ? ? headless: true
? ? })
? ? const page = await browser.newPage()
? ? await page.emulate(devices['iPhone X'])
? ? await page.goto('http://www.baidu.com')
? ? await page.type('#index-kw', 'puppeteer')
? ? await page.click('#index-bn')
? ? await page.waitForNavigation({ timeout: 3000 })
? ? await page.screenshot({
? ? ? ? path: 'c:/temp/baidu_iphone_X_search_puppeteer.png'
? ? })
})()
上面的加粗的三行代碼就對(duì)應(yīng)多出的三個(gè)步驟,需要留意的是,在PC直接訪問(wèn)百度和模擬iPhoneX訪問(wèn)百度拿到的文本框和按鈕的id是不同的,也就是說(shuō),百度并不是直接拿一個(gè)站點(diǎn)做mediaQuery之類設(shè)置供PC和移動(dòng)端共享,而是兩個(gè)完全不同的頁(yè)面,這里不討論優(yōu)缺點(diǎn),如果大家想要在PC看iPhoneX訪問(wèn)的效果就要利用ChromeDevTools改下設(shè)置:

兩個(gè)紅色方框是設(shè)置的地方,藍(lán)色方框標(biāo)注兩個(gè)元素的id
最終截圖見(jiàn)下:

好了,puppeteer的入門及實(shí)踐(1)就到此為止了,總結(jié)下,puppeteer作為谷歌出品的前端利器,想象空間是很大的,在爬蟲(chóng)、測(cè)試自動(dòng)化等方面都可以很好勝任,跟其他測(cè)試工具不同,不再是模擬谷歌執(zhí)行引擎再去渲染,而是一個(gè)真正在運(yùn)行的瀏覽器,只是移除了真實(shí)的界面渲染。作為一個(gè)入門課程,很多細(xì)節(jié)都沒(méi)詳述,比如可以通過(guò)傳參 headless: false 讓puppeteer操作Chrome的過(guò)程可視化,各步驟可以指定間隔時(shí)間,還有插件可以錄制等,這些更精彩的留待后面再寫。
文中所有DEMO源碼參照:
https://github.com/wu0792/puppeteer_01