爬蟲利器-Puppeteer初探

模擬瀏覽器操做神器Puppeteer初探

介紹

  剛接觸到puppeteer,並非用來作爬蟲,只是想作一個後臺數據推送及性能數據抓取的功能,須要模擬登錄內部系統爬取數據截圖。一開始想到利用不少方案,像wkhtmltopdf, phantomjs等等,他們都是類瀏覽器的環境,由於以前使用過,都知道他們或多或少都存在些問題。再後來發現了headless,谷歌的無頭瀏覽器服務,這個最接近真實瀏覽器的東西(應該說就是個瀏覽器吧),而後決定採用headless,網上最多的是採用lighthouse做爲操做headless的nodejs接口工具,後來看到puppeteer,和lighthouse差很少,但畢竟是谷歌團隊本身維護的工具,固然就選擇了它,後來看了看,果真仍是它用起來比較方便。javascript

  官方對於puppeteer的介紹(翻譯過來):css

puppeteer由Chrome團隊開發的Node庫。它提供了一個高級API來控制無頭(或完整)Chrome。它與Phantom和NightmareJS等其餘自動化測試庫相似,但它只適用於最新版本的Chrome。 除此以外,Puppeteer還可用於輕鬆截取屏幕截圖,建立PDF,導航頁面以及獲取有關這些頁面的信息。若是您想快速自動化瀏覽器測試,我建議使用該庫。它隱藏了DevTools協議的複雜性,並負責啓動Chrome的調試實例等冗餘任務>html

  看起來很強大對不對,實時上除了無頭模式,Puppeteer也能夠操做真實瀏覽器進行工做,你會發現它除了能夠作完美的爬蟲以外,對於自動化的ui測試也是利器。目前也有了中文文檔,使用起來也是極其方便的java

截圖

讓咱們先來看一下它的api,首先是puppteer對象,用於啓動一個Chromium實例,例子:node

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  await page.goto('https://www.google.com');
  // 其餘操做...
  await browser.close();
});
複製代碼

  上圖實際是打開了一個瀏覽器應用,lauch方法支持一個對象類型的參數,其中能夠指定headless爲true仍是false,當指定爲true是,能夠觀察到實際行爲,在咱們測試的時候仍是頗有用處的,當咱們設置爲true是能夠觀察到,browser對象針對的是整個瀏覽器窗口,而page對象針對的是每一個tab頁籤,當關閉browser對象時,全部page對象都會被銷燬,若是想要單獨銷燬page對象能夠調用page.close();   在實際應用中,page對象是咱們最經常使用的對象,下面是使用page對象打開一個頁面並進行截圖的例子:git

const puppeteer = require('puppeteer');
puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  await page.goto('https://www.baidu.com');
  // 截圖...
  await page.screenshot({path:'xx/xx.png',type:'png',quality:100,fullPage:true});
  await browser.close();
});
複製代碼

這裏介紹下截圖的幾個參數:github

  • path:圖片存儲路徑
  • type: 圖片格式,默認png
  • quality: 圖片質量0-100的值,png格式無效
  • fullpage: 是否截取整個頁面,若是不設置,截取的是窗口打開部分,並非全頁面,默認打開的窗口是800x600大小,若是想截取更完美的大小須要調整視窗大小,經過設置launch的defaultViewport參數。

性能數據獲取

puppteer也支持咱們在打開頁面時進行一些性能數據的採集,page.metrics()方法能夠幫咱們獲取到頁面打開過程當中的性能參數:web

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  await page.goto('https://www.target.com');
  // 獲取頁面性能數據...
  const result = await  page.metrics();
  console.log(result);
  await browser.close();
});
複製代碼

返回結果包括:chrome

  • Timestamp 時間點(when the metrics sample was taken)
  • Documents 頁面的documents數量。
  • Frames 頁面的iframe數量。
  • JSEventListeners 頁面的js事件數量。
  • Nodes 頁面的dom節點數量。
  • LayoutCount 整頁面或部分頁面的佈局數量。
  • RecalcStyleCount 頁面樣式從新計算數量。
  • LayoutDuration 頁面佈局總時間。
  • RecalcStyleDuration 頁面樣式從新計算總時間。
  • ScriptDuration 頁面js代碼執行總時間。
  • TaskDuration 頁面任務執行總時間。
  • JSHeapUsedSize 頁面佔用堆內存大小。
  • JSHeapTotalSize 總的頁面堆內存大小。 還有另一個api,用於獲取咱們平時利用瀏覽器觀察頁面加載性能的performance視圖,它會生成和谷歌瀏覽器中profile.json同樣的一個json數據,咱們能夠導入瀏覽器中查看
    屏幕快照 2019-04-13 22.14.01.png

相關代碼:json

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  await page.tracing.start({path: 'trace.json'});
  await page.goto('https://www.target.com');
  await page.tracing.stop();
  await browser.close();
  
});
複製代碼

咱們拿到.json文件後也能夠訪問DevTools Timeline Viewer導入去查看頁面加載的詳細信息。

那麼對於性能數據來講,咱們最經常使用的手機api就是performance.timing這個對象了,那麼咱們若是在puppteer中去獲取並收集數據呢?下面看一個例子:

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  await page.goto('https://www.target.com',{
  waitUntil:'networkidle0'
  });
  const timing = await page.evaluate(() => (window.performance.timing.toJSON()));
  console.log(timing);
  await browser.close();
  
});
複製代碼

上面的goto方法內我加了一個參數networkidle0,意思是再也不有任何網絡鏈接時觸發(至少500毫秒後)後纔算頁面跳轉完成,這麼作是爲了等頁面徹底加載結束,得到最準確的數據,在evaluate方法內可使用page對象內的上下文,也就是當前頁面的dom對象都是可使用的,這樣就拿到了timing數據。

最後

除此以外,也能夠利用puppteer的Coverage對象獲取js以及css的代碼覆蓋率,這裏就不作過多介紹了,感興趣的同窗能夠自行研究。 參考文章:developers.google.com/web/updates…        zhaoqize.github.io/puppeteer-a…

相關文章
相關標籤/搜索