首页 > 解决方案 > page.evaluate 和 page.$ 的不同行为具有后续功能

问题描述

我有一个要加载的页面。以下page.$eval()代码有效:

const productName = await page.$eval('h1[role="main"]', el =>
    [].reduce.call(
      el.childNodes,
      (a, b) =>
        a +
        (b.nodeType === 3
          ? b.textContent
              .replace(/[\r\n]+/gm, "")
              .replace(/\s+/g, " ")
              .trim()
          : ""),
      ""
    )
  );

通过作品,我的意思是它返回预期的产品名称。我在主函数中运行它。

我现在想将代码外包给原始上下文之外的自己的函数(以供重用)。

我在主函数中调用函数,如下所示:

  const productName = await page
    .$('h1[role="main"]')
    .then(el => getProductNameFromSelector(el))
    .catch(err => console.log("failure product name", err));

外包的功能是这样的:

const getProductNameFromSelector = async el =>
  el
    .evaluate(
      el,
      [].reduce.call(
        el.childNodes,
        (a, b) =>
          a +
          (b.nodeType === 3
            ? b.textContent
                .replace(/[\r\n]+/gm, "")
                .replace(/\s+/g, " ")
                .trim()
            : ""),
        ""
      )
    )
    .then(result => result)
    .catch(err => console.log("error in function", err, el));

它遇到以下错误:

failure product name TypeError: Cannot read property 'evaluate' of null
    at reduce (<anonymous>)
    at getProductNameFromSelector (pathToFile.js:395:17)
    at page.$.then.el (pathToFile.js:119:21)
    at process._tickCallback (internal/process/next_tick.js:68:7)

我应该收到一个ElementHandlefrom page.$('h1[role="main"]')。它undefined虽然说。

标签: javascriptnode.jspuppeteer

解决方案


evaluate函数需要期望元素作为el参数

const getProductNameFromSelector = async el =>
  el
    .evaluate(el =>  //HERE
      [].reduce.call(
        el.childNodes,
        (a, b) =>
          a +
          (b.nodeType === 3
            ? b.textContent
                .replace(/[\r\n]+/gm, "")
                .replace(/\s+/g, " ")
                .trim()
            : ""),
        ""
      )
    )
    .then(result => result)
    .catch(err => console.log("error in function", err, el));

您也可以等待选择器:

const productName = await page
    .waitForSelector('h1[role="main"]')
    .then(el => getProductNameFromSelector(el))
    .catch(err => console.log("failure product name", err));

推荐阅读