我们书接上文,这篇文章持续列出常用的十个 puppeteer 中常用的办法,希望各位大佬提出宝贵的定见。

11. 输入 input 框

这段代码界说了一个异步函数 editInput,它承受三个参数:page(表明当前操作的页面目标),selector(用于挑选 input 元素的 CSS 挑选器),和 inputVal(要输入到 input 框中的值)。函数首要经过 page.$(selector) 查找页面上的 input 元素,假如找不到则输出错误信息并完毕进程。假如找到了,就经过三次点击选中 input 框中的内容(这儿点击三次是为了保证选中一切内容,但具体次数或许需要根据实际状况调整),等候 300 毫秒后,运用 page.type 办法将 inputVal 输入到 input 框中,再等候 300 毫秒以保证输入完结。

const editInput = async (page,selector,inputVal) => {
  // 查找地址输入框
  const addressEl = await page.$(selector);
  if(!addressEl){
    console.error(`Error:找不到 ${selector} 元素!`);
    process.exit(1); // 完毕进程,检测失利
  }
  // 填写地址
  await page.click(selector, { clickCount: 3 });
  await page.waitForTimeout(300);
  await page.type(selector, inputVal);
  await page.waitForTimeout(300);
}

12. 清空 input 框

这儿提供了四种清空 input 框的办法:

  • 办法一办法二:直接经过 page.evaluateframe.$eval 修改 input 元素的值。这两种办法简略直接,但或许不会触发页面上的监听事情。
  • 办法三:经过获取 input 框的当前值,然后运用循环和 page.keyboard.press('Backspace') 模仿按键删去操作来清空 input 框。这种办法能够触发监听键盘事情的处理程序。
  • 办法四:类似于办法一和办法二,可是经过屡次点击 input 框来选中其内容,然后再输入空字符串来“清空”它。同样,这种办法或许不会触发一切类型的监听事情。
// 办法一:请留意 这种计划仅仅给input的值清空了,页面有或许还有侦听事情,是不能触发的。
await page.evaluate( () => document.getElementById("inputID").value = "")
// 办法二:请留意 这种计划仅仅给input的值清空了,页面有或许还有侦听事情,是不能触发的。
await frame.$eval('inputID', el => el.value = '')
// 办法三:模仿键盘删去事情,有多少字符删去多少次
const inputValue = await page.$eval('#inputID', el => el.value);
for (let i = 0; i < inputValue.length; i  ) {  
    await page.keyboard.press('Backspace');
}
// 办法四:模仿 input屡次点击 操作,屡次点击后会选中input的值,再次输入你想输入的字符
const input = await page.$('#inputID');
await input.click({ clickCount: 3 });
await input.type("", { delay: 100 });

13. 模仿 input 框失焦(position:fixed)

关于悬浮(position: fixed)和非悬浮两种状况,代码别离进行了处理。关于悬浮的状况,它首要运用 page.focus 将焦点设置到指定的 input 元素上,然后在页面上下文中履行 JavaScript 代码来设置 input 的值并使其失焦(经过调用 blur 办法)。关于非悬浮的状况,它直接点击 input 框并输入文本(这儿假设 playname 是一个现已获取的 input 元素目标)。

// 假如待输入的 input 弹窗有悬浮【position:fixed】和在页面文档流中两种办法,则下面两个状况的代码均要写入检测脚本,避免任何一种状况检测不经过
// 【弹窗为悬浮状况】检测输入标题
await page.focus('input[name=input-playlist-title]');
await page.evaluate((selector) => {
    if(document.querySelector(selector)){
        document.querySelector(selector).value = "曲目2050";
        document.querySelector(selector).blur();
    }
}, 'input[name=input-playlist-title]');
// 【弹窗为不是悬浮状况】检测输入标题
await playname.click({ clickCount: 3 }); // playname 是输入框目标 page.$()
await playname.type("曲目2050");

14. 单选表单

这段代码首要经过 CSS 挑选器定位到一个单选按钮并点击它。然后,它运用 page.$$eval 和一个过滤器函数来获取一切选中的单选按钮的值。可是,留意这儿的 CSS 挑选器语法好像有误(input[(type = "radio")][(name = "gender")] 应该是 input[type="radio"][name="gender"]),而且 checkVal 的获取办法或许不会按预期作业,因为过滤器函数中的条件或许不正确(它应该查看 el.checked 是否为 true 而不是仅仅查看 el.checked 的存在性)。

   //点击单选中的一个单选按钮
   await page.click("input[type=radio][name=gender]#female"); 
    // 获取单选选中的值
   const checkVal = await page.$$eval(
     input[(type = "radio")][(name = "gender")],
     (els) => Array.from(els).filter((el) => el.checked)[0].value
   );

15. 多选表单

类似于单选表单的处理,这段代码首要点击两个多选框来选中它们(留意这儿的 CSS 挑选器语法也有误),然后运用 page.$$eval 和一个过滤器函数来获取一切选中的多选框的值。过滤器函数正确地查看了 el.checked 是否为 true

   // 点击多选按钮
   await page.click( input[type=checkbox][name=photography]) 
   await page.click( input[type=checkbox][name=reading])
   // 获取多选选中的值 
   const checkVals = await page.$$eval("input[type=checkbox]", (els) => {
      els = Array.from(els);
      return els.filter((el) => el.checked).map((el) => el.value);
   });

16. 检测激活款式是否运用

这个函数承受多个参数,用于查看一系列元素中是否有正确运用激活款式(activeClass)。它遍历指定范围内的元素,查看每个元素的类名是否包括激活款式。假如当前应该激活的元素没有运用激活款式,或者不应该激活的元素运用了激活款式,函数将输出错误信息并完毕进程。可是,留意这儿的代码有一些问题:CSS 挑选器的拼接好像有误(${selector j}) 应该是 ${selector}${j}),而且或许需要更杂乱的逻辑来正确处理类名的查看(比如运用正则表达式而不是简略的 indexOf 查看)。

const checkActiveClass = async (page,minNum,maxNum,activeNum,selector,activeClass) => {
  for (let j = minNum; j < maxNum; j  ) {
    const b = await page.evaluate((selector) => {
      return document.querySelector(selector)&&document.querySelector(selector).className;
    }, `${selector   j})`);
    if (j == activeNum && b.indexOf(activeClass) == -1) {
      console.error("Error:当前操作的标签未运用激活款式 ${activeClass}");
      process.exit(1); // 完毕进程,检测失利
    } else if (j != activeNum && b.indexOf(activeClass) > -1) {
      console.error(
        "Error:其他标签未康复默许款式(即,移除激活款式 ${activeClass}"
      );
      process.exit(1); // 完毕进程,检测失利
    }
  }
}

17. 获取元素款式

这段代码展现了两种获取元素款式的办法:一种是获取元素的 className(类名),另一种是获取元素的完好核算款式(经过 window.getComputedStyle)。page.evaluate 用于在页面上下文中履行 JavaScript 代码并回来结果,而 page.$eval 则承受一个挑选器和一个函数作为参数,并在选定的元素上履行该函数。

// 获取 className
const b = await page.evaluate((s) => {
  return document.querySelector(s)&&document.querySelector(s).className;
}, selector);
// 获取 style
const style = await page.$eval(selector, (el) =>
  el&&JSON.parse(JSON.stringify(window.getComputedStyle(el)))
);

18. waitUntil 合理运用

这段代码展现了如何运用 page.goto 办法的 waitUntil 选项来指定页面加载成功的条件。waitUntil 能够承受多个字符串值,每个值代表一种页面加载状况的查看办法。这儿列出了四种常见的选项:loaddomcontentloadednetworkidle0networkidle2,并解释了它们的含义。可是,留意这儿的注释格局有误(运用了中文冒号而不是英文冒号),而且应该去掉 load:window.onload 这一行(因为它不是 waitUntil 的有用选项)。

await page.goto(pageURL, {
      waitUntil: ["load", "domcontentloaded", "networkidle0", "networkidl2"],
});
// waitUntil 代表什么时分才以为页面加载成功。
load:window.onload //onload 事情被触发时分页面加载成功,某些状况下它根本不会发生。
domcontentloaded //Domcontentloaded事情触发时分以为导航成功
networkidle0 //在 500ms 内没有网络连接时就算成功(全部的request完毕),才以为页面加载成功
networkidle2 //500ms 内有不超过 2 个网络连接时就算成功(还有两个以下的request),就以为页面加载成功

19. 等候网络恳求完毕(在 500 ms 内没有网络连接就算成功)

这段代码好像有误:它提到了 newPage.waitForNetworkIdle(),但 newPage 并没有在之前的代码中界说(或许是 page 的误写)。正确的做法应该是运用现已存在的 page 目标调用 waitForNetworkIdle() 办法来等候网络恳求完毕。此外,留意 waitForNetworkIdle() 办法默许就是在 500 毫秒内没有网络连接时以为页面加载成功;假如需要更改这个时刻约束,能够经过传递一个选项目标作为参数来设置。

 await newPage.waitForNetworkIdle();

20. 点击列表元素其间一个

这段代码展现了如何运用 CSS 挑选器来定位并点击列表中的一个元素(这儿是第一个 .btn 类的元素)。page.click 办法承受一个挑选器作为参数,并模仿在该挑选器匹配的元素上进行点击操作。这儿的 .btn:nth-child(1) 挑选器表明挑选作为其父元素的第一个子元素的 .btn 类的元素。可是,请留意,假如 .btn 元素不是其父元素的直接子元素,或者页面上有多个具有相同挑选器的元素,这种办法或许不会按预期作业。在这种状况下,或许需要运用更具体的挑选器或额定的逻辑来保证正确定位目标元素。

 await page.click(`.btn:nth-child(1)`); // 点击第一个 btn 元素