puppeteer,新款headless chrome!

puppeteer

puppeteer是一種谷歌開發的Headless Chrome,由於puppeteer的出現,業內許多自動化測試庫中止維護,好比PhantomJS,Selenium IDE for Firefox 。javascript

puppeteer是幹啥用的?

官方給了一些功能:前端

  • 頁面生成pdf
  • 爬spa/ssr類的網站
  • 自動提交表單,模擬用戶操做,ui測試等等
  • 提供自動化測試環境
  • 分析網頁性能問題,基於chrome timeline

其實對於這麼一個瀏覽器,咱們能作的還有不少,好比前端監控,按期查詢頁面異常。這種思想產生的page-monitor。主要的功能其實就是基於它是一個瀏覽器,它能夠模擬用戶輸入。能作什麼依賴你的想象。java

用code介紹一下puppeteer

頁面生成pdf

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('http://open.toutiao.com', {waitUntil: 'networkidle2'});
  await page.pdf({path: 'hn.pdf', format: 'A4'});
  await browser.close();
})();

puppeteer是基於node v6.4.0,可是await/async的語法須要node v7.6.0以上才支持。node

能夠npm i puppeteer而後在命令行看一下效果。
代碼都是api沒有什麼能夠講的。須要說的一點就是open.toutiao.com下面的文章內容都是異步接口請求,puppeteer是怎麼獲取內容的?git

page.goto的配置項waitUntil:networkidle2, 等待一直到500ms內的請求數不超過2個。其實不保證準確得到內容,那把等待時間寫長一點就能夠了。
await page.waitFor(2000);github

調試

  • puppeteer並非只有headless模式,打開puppeteer的ui界面:puppeteer.launch({headless: false),再放慢puppeteer執行的動做puppeteer.launch({headless: false, slowMo: 250}),就能夠輕鬆調試。
  • ‘打call?’ page.on('console', msg => console.log('PAGE LOG:', msg.text())); 事件監聽輕鬆打出頁面的log。

爬蟲

這裏爬一下頭條的新聞標題:chrome

(async () => {
  const browser = await puppeteer.launch({headless: false, slowMo: 250});
  const page = (await browser.pages())[0];
  page.on('console', msg => console.log('PAGE LOG:', msg.text()));
  await page.goto('https://open.toutiao.com');

  await page.evaluate(() => console.log(`url is ${location.href}`));

  const newsTitle = await page.evaluate((sel) => {
    const $els = document.querySelectorAll(sel);
    return Array.from($els).map((v) => {
        console.log(v.innerText); // 會被page.on 'console' 監聽到
        return v.innerText
    })
  }, 'section h3');
  console.log(newsTitle) // 能夠處理新聞標題。
  await page.screenshot({path: 'toutiao.png'}); // 屏幕快照
  await browser.close();
})();

模擬用戶操做

這個功能用途挺多的,好比自動登錄,e2e測試,刷贊,搶票什麼的,固然若是能跳過驗證碼的話。npm

github 登錄

模擬輸入用戶名和密碼。json

await page.goto('https://github.com/login');
    await page.click('#login_field');
    await page.type('username');

    await page.click('#password');
    await page.type('password');

    await page.click('#login > form > div.auth-form-body.mt-3 > input.btn.btn-primary.btn-block');

    await page.waitForNavigation();

puppetter提供了page.focus,page.click,page.type,page.$eval(獲取dom屬性)等等api,鼠標位置,按鍵按下,tap,頁面跳轉衆多用戶可操做的api,均可以經過程序來模擬。api

對這種模擬登錄,puppeteer還貼心的提供了這種api - -!page.type('#mytextarea', 'World', {delay: 100}); // Types slower, like a user

ui測試

以前分享過的testcafe,跟puppeteer的api很是像,testcafe是一個自動化測試框架,他與puppeteer不一樣的一點就是他集成了mocha斷言庫。
puppeteer和testcafe都提供了一套自動化測試的環境。puppeteer作e2e的測試須要本身選一個斷言庫,不過無傷大雅。

請求攔截/模擬請求

puppeteer比testcafe好的一點就是支持請求攔截,記得當初用testcafe測試請求是否被髮出用了不少黑科技,提過issue。。

const puppeteer = require('puppeteer');

puppeteer.launch({headless: false, slowMo: 250}).then(async browser => {
  const page = await browser.newPage();
  await page.setRequestInterception(true);
  page.on('console', msg => console.log('PAGE LOG:', msg.text()));
  page.on('request', interceptedRequest => {
    if (interceptedRequest.url().endsWith('.png') || interceptedRequest.url().endsWith('.jpg'))
      interceptedRequest.abort();
    else
      interceptedRequest.continue();
  });
  await page.goto('https://open.toutiao.com');
//   await browser.close();
});

提供了request,response事件,能夠攔截請求,首先須要打開這個開關await page.setRequestInterception(true);
這裏的例子就是停掉全部的png和jpg請求。
攔截能作的東西有不少,好比一些爬蟲能夠經過攔截請求捕獲一些數據,來處理一些東西。

修改環境

puppeteer能夠經過page.setViewport,page.setUserAgent來修改訪問的環境。

await page.setViewport({
  width: 1920,
  height: 1080
});

await page.setUserAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36');

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); // emulate的配置有Viewport,UserAgent等等。以前的setUserAgent等方法是它的語法糖。
  await page.goto('https://www.google.com');
  // other actions...
  await browser.close();
});

性能測試

能夠生成一個trace.json的文件,供chrome控制檯解析,await page.metrics()還能夠給出一些性能測試的數據。

const puppeteer = require('puppeteer');
(async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.tracing.start({path: 'trace.json'})
    await page.goto('https://open.toutiao.com')
    await page.tracing.stop()
    const metrics = await page.metrics()
    console.log(metrics)
    await browser.close();
})();
// output
{ Timestamp: 27888.820538,
  Documents: 2,
  Frames: 1,
  JSEventListeners: 58,
  Nodes: 171,
  LayoutCount: 20,
  RecalcStyleCount: 26,
  LayoutDuration: 0.042335,
  RecalcStyleDuration: 0.010091,
  ScriptDuration: 0.124838,
  TaskDuration: 0.000039,
  JSHeapUsedSize: 6388448,
  JSHeapTotalSize: 10334208 }
相關文章
相關標籤/搜索