zoukankan      html  css  js  c++  java
  • puppeteer,新款headless chrome

    puppeteer

    puppeteer是一种谷歌开发的Headless Chrome,因为puppeteer的出现,业内许多自动化测试库停止维护,比如PhantomJS,Selenium IDE for Firefox 。

    puppeteer是干啥用的?

    官方给了一些功能:

    • 页面生成pdf
    • 爬spa/ssr类的网站
    • 自动提交表单,模拟用户操作,ui测试等等
    • 提供自动化测试环境
    • 分析网页性能问题,基于chrome timeline

    其实对于这么一个浏览器,我们能做的还有很多,比如前端监控,定期查询页面异常。这种思想产生的page-monitor。主要的功能其实就是基于它是一个浏览器,它可以模拟用户输入。能做什么依赖你的想象。

    用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以上才支持。

    可以npm i puppeteer然后在命令行看一下效果。
    代码都是api没有什么可以讲的。需要说的一点就是open.toutiao.com下面的文章内容都是异步接口请求,puppeteer是怎么获取内容的?

    page.goto的配置项waitUntil:networkidle2, 等待一直到500ms内的请求数不超过2个。其实不保证准确获得内容,那把等待时间写长一点就可以了。
    await page.waitFor(2000);

    调试

    • 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。

    爬虫

    这里爬一下头条的新闻标题:

    (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测试,刷赞,抢票什么的,当然如果能跳过验证码的话。

    github 登陆

    模拟输入用户名和密码。

        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,都可以通过程序来模拟。

    对这种模拟登陆,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({
       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 }
  • 相关阅读:
    2019年CSP-J初赛试题(普及组)试题详解
    开放课件
    猴子选大王 (约瑟夫问题)
    后缀表达式转中缀表达式
    JDBC的使用
    JDBC
    MySQL第五天
    MySQL第四天
    MySQL第三天
    MySQL第二天
  • 原文地址:https://www.cnblogs.com/amiezhang/p/10018993.html
Copyright © 2011-2022 走看看