【问题标题】:Pass a function to evaluate() in puppeteer在 puppeteer 中将函数传递给 evaluate()
【发布时间】:2020-09-26 17:07:15
【问题描述】:

我正在使用 Puppeteer 在 Typescript 中开发一个网络爬虫,并制作了一个这样的辅助函数:

function evaluateXPath(page: puppeteer.Page, xpath: string): Promise<any[]> {
    return page.waitForXPath(xpath)
        .then(() => page.$x(xpath))
        .then(handles => page.evaluate((...handles) => handles.map(h => h.href), ...handles))
}

如果我想获取 xpath 的 href 字段的值,它可以正常工作,但我想让它更通用。像这样(用 'evalFunc' 替换 map() 中的 'h => h.href'):

function evaluateXPath(page: puppeteer.Page, xpath: string, evalFunc: (value: any, index: number, array: any[]) => any): Promise<any[]> {
    return page.waitForXPath(xpath)
        .then(() => page.$x(xpath))
        .then(handles => page.evaluate((...handles) => handles.map(evalFunc), ...handles))
}

这显然不起作用,因为 'evalFunc' 在浏览器上下文中不存在,但是将函数传递给浏览器的任何尝试都会失败或无法编译。将它传递到 evaluate() 函数内不起作用,因为它不能分配给“SerializableOrJSHandle”类型的参数,而且我对exposeFunction() 函数也没有运气。

谁能告诉我它是怎么做的?

【问题讨论】:

  • 您使用handles 执行什么样的操作?
  • 如果你不介意在page.evaluate中写出来,你可以把window.nameMe = function() {}放在evaluate函数中。除非我误解了你的问题...
  • 我希望能够传递任意函数(在 c 的限制下,例如获取 href/innerText 并偶尔制作一个简单的 if-case)以在浏览器上下文中进行评估。必须在辅助函数中定义我打算使用的每个函数会很不方便且难以维护。

标签: javascript node.js typescript xpath puppeteer


【解决方案1】:

我能想到两个可疑且不方便的解决方案。

  1. 在评估函数内使用eval()Function() 构造函数并将函数代码作为字符串传输(代码编写、linting 等困难——这可以通过使用Function.prototype.toString() 来缓解一点)。

  2. 将所有实用程序函数放在一个文件中并使用page.addScriptTag() 注入此文件,以便评估函数可以调用此文件中声明的任何函数(这会污染全局范围)。

编辑:

function evaluateXPath(page: puppeteer.Page, xpath: string, evalFunc: (value: any, index: number, array: any[]) => any): Promise<any[]> {
    return page.waitForXPath(xpath)
        .then(() => page.$x(xpath))
        .then(handles => page.evaluate((evalFuncStr, ...handles) =>
            handles.map(eval(`(${evalFuncStr})`)),
            evalFunc.toString(),
            ...handles))
}

【讨论】:

  • 只是一个迟来的想法。 eval(evalFuncStr) 将声明一个函数。如果你使用匿名函数或者想要函数表达式,应该是eval(`(${evalFuncStr})`)
  • 我之前没有使用过 eval 函数,也没有做过任何广泛的测试。我的编辑适用于我的特殊情况。有时间我会试试你的改变。
  • 我尝试了您的更改,并且效果也很好(就我而言)。我不知道这有什么意义,但我会接受你的建议。谢谢!
猜你喜欢
  • 2021-07-25
  • 1970-01-01
  • 1970-01-01
  • 2018-11-08
  • 2018-11-12
  • 1970-01-01
  • 1970-01-01
  • 2020-07-28
相关资源
最近更新 更多