玩转puppeteer

188 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 20 天,点击查看活动详情

前言

最近因为总是在测试方面花太多的时间,挤掉了很多摸鱼的时间,这是得不偿失,于是自己想做一个自动化测试工具,可以改变屏幕大小,可以截图,于是首选pupeteer, 那么要使用它,得先把他常用的api研究一下, 今天这节课就是pupeteer的启蒙课程

pupeteer

  • puppeteerChrome团队开发的一个node
  • 可以通过api来控制浏览器的行为,比如点击,跳转,刷新,在控制台执行js脚本等等
  • 通过这个工具可以用来写爬虫,自动签到,网页截图,生成pdf,自动化测试等

安装pupeteer

npm i puppeteer -D

玩转puppeteer

常用浏览器设置

 const browser = await puppeteer.launch({
    headless: false, // true不会打开浏览器. 默认为true
    timeout: 15000, //设置超时时间,
  }); //打开浏览器

打开一个新的标签页

  const page = await browser.newPage(); //打开一个空白页

页面跳转

  // 建议使用这种方式,可以防止浏览器超时
  await page.goto("https://www.baidu.com", { timeout: 3000 }).then(() => {
    console.log('跳转百度页面成功');
  }, () => {
    console.log('跳转成功,加载超时');
  }); //在地址栏输入网址并等待加载

设置页面大小,方便多屏幕测试

  await page.setViewport({
    width: 400,
    height: 300,
    isMobile: true // 要不要包含`meta viewport` 标签. 默认 `false`。
  });

截图功能

  await page.screenshot({
    path: "baidu.png", // 图片保存路径
    fullpage: true  // 是否截取全屏幕
  }); //截个图

在输入框输入内容,并点击按钮

await page.type('#index-kw', 'puppeteer') 
await page.click('#index-bn')
(async () => { 
    const browser = await puppeteer.launch();//打开浏览器 
    const page = await browser.newPage();//打开一个空白页 
    await page.goto('https://www.baidu.com');//在地址栏输入网址并等待加载 
    await page.screenshot({ path: 'baidu.png' });//截个图 
    await browser.close();//关掉浏览器 
})();
const puppeteer=require('puppeteer'); 
const fs=require('fs'); 
(async function () { 
    const browser=await puppeteer.launch({headless:false}); 
    const page=await browser.newPage(); 
    await page.goto('https://juejin.im/tag/%E5%89%8D%E7%AB%AF', { waitUntil: 'networkidle2' }); 
    await page.waitFor(500); 
    let comments = await page.$$eval('a.title', els => { return els.map(item => item.innerText); }); fs.writeFileSync('comments.txt',comments.join('\r\n'),'utf8'); 
    await browser.close(); 
})();

等待导航成功


 await page.waitForNavigation({
    waitUntil: 'domcontentloaded',
    timeout: 600000
  });

我再使用这个waitForNavigation一直发生超时的问题

Error: Navigation Timeout Exceeded: 30000ms exceeded

解决方案以及原因可以参考这篇文章

waitForNavigation doesn't work after clicking a link #1412

waitUntil

waitUntil代表什么时候才认为导航加载成功。

  • load: window.onload事件被触发时候完成导航,某些情况下它根本不会发生。
  • domcontentloaded: Domcontentloaded事件触发时候认为导航成功
  • networkidle0: 在 500ms 内没有网络连接时就算成功(全部的request结束),才认为导航结束
  • networkidle2: 500ms 内有不超过 2 个网络连接时就算成功(还有两个以下的request),就认为导航完成。

我们对比了下加载时长 networkidle0> networkidle2>load>domcontentloaded

使用networkidle0的时候,随时可能网络加载时间在2s以上。我们希望500ms的时长是可配置的,因为500ms太长了。

完整代码

const puppeteer = require("puppeteer");

(async () => {
  const browser = await puppeteer.launch({
    headless: false, // true不会打开浏览器. 默认为true
    timeout: 15000, //设置超时时间,
  }); //打开浏览器

  const page = await browser.newPage(); //打开一个空白页
  await page.setViewport({
    width: 400,
    height: 300,
    isMobile: true
  });

  // 建议使用这种方式,可以防止浏览器超时
  await page.goto("https://www.baidu.com", { timeout: 60000 }).then(() => {
    console.log('跳转百度页面成功');
  }, () => {
    console.log('跳转成功,加载超时');
  }); //在地址栏输入网址并等待加载

  await page.type('#kw', '你好');
  page.click('#su');

  await page.waitForNavigation({
    waitUntil: 'domcontentloaded',
    timeout: 60000
  });


  await page.screenshot({
    path: "baidu.png", // 图片保存路径
    fullpage: true  // 是否截取全屏幕
  }); //截个图
  await browser.close(); //关掉浏览器
})();

参考