当前位置: 首页 > 知识库问答 >
问题:

自定义函数未定义Puppeteer

陈欣荣
2023-03-14

我做了这个自定义函数,并把它放在全局之外,这通常会工作。我也试着在主异步木偶函数中移动它,但也不起作用。这是一个简单的函数。在每个page evaluate函数中,我调用它并传递选择器。但是,它的说法没有定义和promise拒绝,这是奇怪的,因为函数不是promise....请帮助

const grabDomConvertNodlistToArray = (grabDomHtmlPath) => {
  // grabbing node list from html selector all
  const nList = document.querySelectorAll(grabDomHtmlPath);
  // converting nodelist to array to be returned
  const array = Array.from(nList);
  return array;
};

我尝试将函数转换为异步函数,添加了一个新的参数页。然后,我将async添加到我的评估函数中,然后将puppeteer页面作为参数传递,仍然出错且不起作用。

const grabDomConvertNodlistToArray = async (page, grabDomHtmlPath) => {
  try {
    // grabbing node list from html selector all
    const nList = await page.document.querySelectorAll(grabDomHtmlPath);
    // converting nodelist to array to be returned
    const array = Array.from(nList);
    return array;
  } catch (error) {
    console.log(error);
  }
};

在我的求值回调函数中添加了async,也就是async()=>{}。但是,当在上面的评估函数中调用我的自定义函数时,由于某种原因,它仍然不起作用。

找到了解决办法,但对我不起作用。我得到Array.foreach不是一个方法,它向我表明在我的grel腹convertnodlisttoArray函数中,它不抓取nodeList或将其转换为数组。如果是这样,那么forEach将是一个函数。

解决方案3

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(someURL);       

var functionToInject = function(){
    return 1+1;
}

var otherFunctionToInject = function(input){
    return 6
}

await page.exposeFunction("functionToInject", functionToInject)
await page.exposeFunction("otherFunctionToInject", otherFunctionToInject)

var data = await page.evaluate(async function(){
    console.log('woo I run inside a browser')
    return await functionToInject() + await otherFunctionToInject();
});

    return data
const grabDomConvertNodlistToArray = (grabDomHtmlPath) => {
    // grabbing node list from html selector all
    const nList = document.querySelectorAll(grabDomHtmlPath);
    // converting nodelist to array to be returned
    const array = Array.from(nList);
    return array;
  };
const rlData = async () => {
  const browser = await puppeteer.launch(
    {
      headless: true,
    },
    {
      args: ["--flag-switches-begin", "--disable-features=OutOfBlinkCors", "--flag-switches-end"],
    }
  );

const pageBodies = await browser.newPage();
  await pageBodies.goto("https://test.com/bodies", {
    waitUntil: "load",
  });

  const grabDomConvertNodlistToArray = (grabDomHtmlPath) => {
    // grabbing node list from html selector all
    const nList = document.querySelectorAll(grabDomHtmlPath);
    // converting nodelist to array to be returned
    const array = Array.from(nList);
    return array;
  };

  await pageBodies.exposeFunction("grabDomConvertNodlistToArray", grabDomConvertNodlistToArray);

  const rlBodyNames = await pageBodies.evaluate(async () => {
    // grabs all elements in html to make nodelist & converts it to an array
    const array = grabDomConvertNodlistToArray(".testbodies > div > h1");
    // push the data collected from array into data array and returned
    const data = [];
    array.forEach((element) => {
      data.push(element.textContent);
    });
    return data;
  });
}
rlData();

我放弃了让这个工作的尝试,决定只是这样做。是的,如果你有更多的页面要刮,它会使你的代码重复,所以你会多次使用相同的代码,这是我试图避免的,但是,puppeteer是更糟糕的重构你的代码,也许下一行,该软件包的开发人员将添加能力,轻松使用自定义函数,就像我尝试的那样。

const testNames = await pageBodies.evaluate(() => {
    const nodeList = document.querySelectorAll(".test > div h2");
    const array = Array.from(nodeList);
    const data = [];
    array.forEach((element) => {
      data.push(element.textContent);
    });
    return data;
  });

共有1个答案

孔鹤龄
2023-03-14

exposeFunction()不适合您的情况:公开的函数用于在浏览器和Node.js上下文之间传输数据,因此可以将其包装在代码中,这些代码对参数和返回的数据进行序列化和反序列化,一些不可序列化的数据(如DOM元素)可能会丢失。请尝试以下操作:

const rlData = async () => {
  const browser = await puppeteer.launch(
    {
      headless: true,
    },
    {
      args: ["--flag-switches-begin", "--disable-features=OutOfBlinkCors", "--flag-switches-end"],
    }
  );

  const pageBodies = await browser.newPage();

  await pageBodies.evaluateOnNewDocument(() => {
    window.grabDomConvertNodlistToArray = function grabDomConvertNodlistToArray(grabDomHtmlPath) {
      // grabbing node list from html selector all
      const nList = document.querySelectorAll(grabDomHtmlPath);
      // converting nodelist to array to be returned
      const array = Array.from(nList);
      return array;
    }
  });

  await pageBodies.goto("https://test.com/bodies", {
    waitUntil: "load",
  });

  const rlBodyNames = await pageBodies.evaluate(() => {
    // grabs all elements in html to make nodelist & converts it to an array
    const array = grabDomConvertNodlistToArray(".testbodies > div > h1");
    // push the data collected from array into data array and returned
    const data = [];
    array.forEach((element) => {
      data.push(element.textContent);
    });
    return data;
  });
}
rlData();
 类似资料:
  • 我试图显示一个关于成功promise的弹出式通知,但我一直收到“ReferenceError:doNotification未定义”。如果我在html中单击按钮时触发doNotification,它就会工作。我的电子邮件功能和控制台一样工作。日志将适当的参数打印到控制台。我不确定在我的电子邮件功能中调用doNotification时为什么会出现此错误?

  • 我是wordpress的新手,正在尝试定义和调用一个函数,但无法让它工作。 以下代码出现在使用get_template_part从content.php文件调用的php文件中。 我在function.php文件的底部添加了以下代码: 单击该元素时,它将返回: (index): 363未捕获引用错误:没有定义check AllTopicCheckBox。 有人能帮帮我吗?

  • 在index.js,我有: 我从以下地方复制粘贴了代码:https://firebase.google.com/docs/functions/get-started 不知何故,当我使用 我得到: 错误:分析函数触发器时出错。ReferenceError:未在对象上定义函数。(/home/[USERNAME HERE]/functions/index.js:1:87)在模块中_在对象处编译(modu

  • XQuery提供编写自定义函数的功能。 下面列出了创建自定义函数的准则。 使用关键字来定义函数。 使用当前XML架构中定义的数据类型 将函数体包含在花括号内。 使用XML命名空间前缀函数的名称。 创建自定义函数时使用以下语法。 语法 示例 以下示例显示如何在XQuery中创建用户定义的函数。 XQuery表达式 输出结果 - 验证结果 要测试上述函数,用上面的XQuery表达式替换books.xq

  • 我在理解group_by如何在tidyverse中工作时遗漏了一些东西。示例将阐明: 我已经创建了下面的函数,它采用很少的参数,并计算tibble内部的最佳权重(可能不是最漂亮的,但似乎工作): 当我在tibble中只有一个组时,这个函数可以很好地工作。我创建函数的方法是尝试通过在一个函数上进行测试来实现它,希望在我稍后对数据进行切片时它会起作用。 然后,我希望可以使用mutate为我的多个组创建

  • 2. 自定义函数 我们不仅可以调用C标准库提供的函数,也可以定义自己的函数,事实上我们已经这么做了:我们定义了main函数。例如: int main(void) { int hour = 11; int minute = 59; printf("%d and %d hours\n", hour, minute / 60); return 0; } main函数的特殊之处在于执行程序时它自动