【问题标题】:Is is possible to include a source file in nodejs+puppeteer to add functions?是否可以在 nodejs+puppeteer 中包含源文件来添加功能?
【发布时间】:2018-05-24 11:42:00
【问题描述】:

我知道

await page.evaluateOnNewDocument(fs.readFileSync('./helperFunctions.js', 'utf8'));

将函数添加到evaluate() 上下文中,非常方便。

但是任何人都可以提供任何示例以在主要上下文中具有相同的含义吗?举个例子,说我要加一个

page.existsText()

existsText()

使用此代码的函数来自要包含/来源的文件

existsText = (string) => {
    // code goes here
}

要走的路是什么?

【问题讨论】:

  • 所以您想在两种情况下都使用来自 fike 的相同代码?
  • 不,evaluate() 上下文的文件和 main 上下文的另一个文件

标签: javascript node.js puppeteer


【解决方案1】:

如果我正确理解您的意图,您希望将函数从文件导入全局命名空间,而不必将它们分配给中间变量。这是在节点中执行此操作的简单方法。

helperFunctions.js

(function(){
    // Assign the function to the scope from where it's called
    this.existsText = (string) => {
        console.log("Do stuff with " + string);
    }
})()

然后,当您在 node.js/puppeteer 脚本中需要它时,它会立即执行,将函数从它分配到全局范围:

require("./helperFunctions");

existsText("global scope");

结果:

在全局范围内做事


奖励:在 page.evaluate 中使用相同的函数

如果需要,可以在浏览器范围内使用相同的帮助文件:

await page.evaluateOnNewDocument(fs.readFileSync('./helperFunctions.js', 'utf8'));

await page.evaluate(() => { 
    existsText("browser scope");
});

在浏览器范围内做事

【讨论】:

    【解决方案2】:

    您可以从页面对象中添加 Page 类的一些方法,以便快速破解。

    const puppeteer = require("puppeteer");
    
    puppeteer.launch().then(async browser => {
      const page = await browser.newPage();
    
      // page constructor is Page, 
      // and we can add some other methods to it's prototype
      page.constructor.prototype.myCustomMethod = function() {
        return this._frameManager.mainFrame().url();
      };
    
      await page.goto("https://example.com");
      const customUrl = await page.myCustomMethod();
    
      console.log({ customUrl }); // Returns { customUrl: 'https://example.com/' }
      await browser.close();
    });
    

    对于一些快速的 hack 来说就这么简单。所以,让我们添加一些exists 方法。

    // get all arguments
    page.constructor.prototype.existsText = function(...args) {
      // let's assume the argument as a variable called string
      return this._frameManager.mainFrame().evaluate(string => {
        // create a new regex to find global multiline insensitive results
        const searchRegex = new RegExp(string, "gmi");
        // find all matchs
        return document.querySelector("body").outerHTML.match(searchRegex);
      }, args); // pass all arguments
    };
    const foundText = await page.existsText("more");
    console.log({ foundText }); 
    // Result: { foundText: [ 'More' ] }
    

    同样,这些都是快速的技巧,并且有其自身的局限性。随意探索。

    【讨论】:

    • 重点是包含/导入/要求来自外部文件,正如标题本身所指出的那样^^
    • 好吧,只需导入/要求/包含它并分配它;)
    • 我想将函数导出到全局范围或page 上下文,而不必执行var x = require('foobar); x.ownFunction()
    猜你喜欢
    • 2011-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-06
    • 2020-04-02
    • 2013-11-29
    • 2012-07-10
    • 2012-01-19
    相关资源
    最近更新 更多