【问题标题】:Intergrate puppeteer tasks into one single task将 puppeteer 任务集成到一个任务中
【发布时间】:2020-04-18 02:31:23
【问题描述】:

我创建了几个如下所示的 javascript 文件:

const somedata = ""
const puppeteer = require('puppeteer');
(async () => {
  const browser = await puppeteer.launch();
  const pages = await browser.pages();
  const page = pages[0];
  await page.goto('https://somewebsite.com');

  ///Do some task

  browser.close();
})();

我设法使用每个单独的文件执行单个操作。现在,我只想创建一个浏览器实例并执行这些单独文件中指定的任务。我想在每个任务中传递一些数据。同样,一次只能打开五个页面。

我正在使用 puppeteer 和 NodeJS。

【问题讨论】:

    标签: javascript node.js puppeteer


    【解决方案1】:

    您可以创建一个BrowserService,它是一个单例并封装页面创建和删除:

    // BrowserService.ts
    export class BrowserService {
        public static instance: BrowserService | null = null;
    
        public static async getInstance(): Promise<BrowserService> {
            if (this.instance == null) {
                this.instance = new BrowserService();
                await this.instance.initialise();
            }
    
            return this.instance;
        }
    
        private browser: PuppeteerBrowser;
    
        private numberPages: number = 0;
    
        private constructor() { }
    
        /**
         * Get a browser page.
         */
        public async getPage(): Promise<PuppeteerPage> {
            // Handle the logic of page creation and limit the number of created pages.
    
            // ...
            const page = (await this.browser.pages())[0];
            // ...
    
            return page;
        }
    
        /**
         * Close a page.
         */
        public async closePage(page: PuppeteerPage): Promise<void> {
            // Handle the logic of page deletion and browser closing.
    
            // ...
            if(this.numberPages === 0) {
                await this.browser.close();
                BrowserService.instance = null;
            }
            // ...
        }
    
        /**
         * Initialise the instance.
         */
        public async initialise(): Promise<void> {
            this.browser = puppeteer.launch();
        }
    }
    

    并在您的代码中使用它:

    // myPuppeteerTask.ts
    const somedata = ""
    const puppeteer = require('puppeteer');
    (async () => {
        const browserService: BrowserService = await BrowserService.getInstance();
        const page = await browserService.getPage();
        await page.goto('https://somewebsite.com');
    
        ///Do some task
    
        browserService.closePage(page);
    })();
    

    BrowserService 是手动创建的单例,但您可以使用 NestJs 或 Awilix 等依赖注入来改进此架构。您可以获得更好的可维护性、可读性和可测试性。

    看起来像这样:

    // myPuppeteerTask.ts
    export class MyPuppeteerTask {
    
        // Inject the BrowserService into the task.
        public constructor(private browserService: BrowserService) { }
    
        public async execTask(): Promise<void> {
            const page = await this.browserService.getPage();
            await page.goto('https://somewebsite.com');
    
            ///Do some task
    
            this.browserService.closePage(page);
        }
    }
    

    【讨论】:

    • 问题是我已经分别创建了每个函数,但是它们每次都创建新的浏览器实例。我只想将这些单独的功能整合为一个。我还发现了 puppeteer-cluster,它看起来很有希望,但对我来说有点复杂。我还找到了 codeceptJS,但为此我必须从头开始编写整个程序。
    • 您对我提供的解决方案的预期问题是什么?
    • 我正在使用 javascript,但我怀疑其中是否有访问修饰符。
    猜你喜欢
    • 2014-08-05
    • 1970-01-01
    • 2016-06-16
    • 2010-12-25
    • 2016-10-02
    • 2021-12-30
    • 2012-07-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多