【问题标题】:reuse browser instance puppeterr重用浏览器实例 puppeteer
【发布时间】:2021-09-03 08:11:45
【问题描述】:

我想知道是否有可能有一个 .js 文件打开浏览器实例,创建新页面/选项卡登录到网站(使用用户名/密码)并保持空闲状态。
然后在第二个 .js 文件中使用文件一个浏览器实例及其页面。

1.js

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch({ 
        headless: true,
        args: ['--no-sandbox'], 
        ignoreDefaultArgs: ["--hide-scrollbars"]
    });

    const page = await browser.newPage();
    const response = await page.goto('https://google.com');

    console.log('Browser open in the background (headless)!');
    //await browser.close();
})();

2.js

const puppeteer = require('puppeteer');

(async () => {
    // instructions on browser instance/page from 1.js ...
})();

【问题讨论】:

  • 在1.js中创建一个类并保持浏览器/页面状态,并添加相关的登录功能。在2.js中创建第一个类的实例并与之交互。如果你想让它保持空闲,请将超时设置为 0 以禁用它。
  • @mbit 对不起,我是 nodejs 的新手,你能解释一下:如何保持浏览器状态以及如何创建第一个类的实例。谢谢

标签: node.js puppeteer


【解决方案1】:

爬虫对象保持浏览器实例的状态和 无论您在哪里调用/传递该实例,它都指的是相同的铬 在“背景”中。如果这是一个矫枉过正,而你只是想 使用 puppeteer 连接到已经运行的铬,你可以做到 使用 puppeteer.connect。看看这个: How to "hook in" puppeteer into a running Chrome instance/tab - mbit

是的,我想这对我来说太过分了:)。但是您发布的链接是我想要的,但有 2 个问题。

这是我所拥有的样本。

// 1.js
// open chromium, new tab, go to google.com, print browserWSEndpoint, disconnect
const puppeteer = require('puppeteer');

(async () => {
    var browser = await puppeteer.launch({headless: false});
    var page = await browser.newPage();
    var response = await page.goto('https://google.com');

    var browserWSEndpoint = browser.wsEndpoint();
    console.log(browserWSEndpoint); // prints: ws://127.0.0.1:51945/devtools/browser/6462daeb-469b-4ae4-bfd1-c3bd2f26aa5e

    browser.disconnect();
})();

// 2.js
// connect to the open browser with the browserWSEndpoint manualy put in, ... , disconect. 
const puppeteer = require('puppeteer');

(async () => {
    var browser = await puppeteer.connect({browserWSEndpoint: 'ws://127.0.0.1:51945/devtools/browser/6462daeb-469b-4ae4-bfd1-c3bd2f26aa5e'});

    // somehow use the tab that is open from 1.js (google.com)

    await browser.disconnect();
})();

我从 console.log 1.js 获取 browserWSEndpoint 字符串。 效果很好,但我有两个困难。

1 - 我如何使用来自 1.js 的变量 browserWSEndpoint,这样我就不必总是将其复制粘贴到 2.js。

2- 如果我在 1.js 上打开一个新页面/标签,然后去谷歌并断开连接 (browser.disconnect()),如何在 2.js 上使用该页面/标签。

【讨论】:

  • 更新:对于 1,在 1.js 上使用了 fs.writeFileSync,在 2.js 上使用了 fs.readFileSync,所以我只是这样获取端点的值,但我想知道该怎么做如果可能的话,另一种方式。对于 2,我使用了 browser.pages(),它返回一组打开的页面/标签页,效果很好。
【解决方案2】:

工作测试代码 getEmail.js 是实际页面的导出位置。在 cmets 中要求澄清。

getBrowser.js

const puppeteer = require("puppeteer");
module.exports = {
browser: {},
pptr_instance_url:"",
getBrow: async function(){  try {
    console.log("line6",this.pptr_instance_url);
    this.browser = await puppeteer.connect({browserWSEndpoint: this.pptr_instance_url}).catch(async e =>{
        console.log("end point",this.pptr_instance_url);
        this.browser = await puppeteer.launch({timeout: 0});
        this.pptr_instance_url = this.browser.wsEndpoint();
        console.log("line 11",this.pptr_instance_url);
        return this.browser;
    });
    return this.browser;
}catch (e){
    console.log(e)
} }
}

pageRenderer.js

const abc = require("../getBrowsernew")
const pageRenderer = async (request) => {
const {reactProjectUrl} = constants, uuidStorageKey = uuidv4(),
    localStorageObject = {[uuidStorageKey]: request.body};

const browser = await abc.getBrow();
let url = "someurl.com"
await setLocalStorage(browser, url, localStorageObject);
const page = await browser.newPage();
const response = await page.goto(
    url,
    {
        waitUntil: "networkidle0"
    }, {waitUntil: 'load', timeout: 0}
);
return page;
}

module.exports = pageRenderer;

getEmail.js

const pageRenderer = require("./pageRenderer");

const getEmail =async (request) =>{

const page = await pageRenderer(request)
const emailbody =  await page.content();
page.close();
return emailbody;
  }

module.exports = getEmail;

【讨论】:

  • 请在您的回答中提供更多详细信息。正如目前所写的那样,很难理解您的解决方案。
【解决方案3】:

您可以通过多种方式实现此功能,例如使用具有功能的单独模块或不同的类,这取决于您的特定需求。

您可以拥有一个启动浏览器并创建页面以及一些额外功能的类。

//1.js
const puppeteer = require('puppeteer');

class Crawler {
    constructor() {
        //init with whatever values you'll need in your class
        //or throw an error if the object wasn't created through build
    }
    static async build() {
        let crawler = new Crawler();
        await crawler._init();
        return crawler;
    }
    async _init() {
        //launch the browser and keep its state
        this._browser = await puppeteer.launch({timeout: 0});
        //create a page and keep its state
        this._page = await this._browser.newPage();
    }
    //getter
    get browser() {
        return this._browser;
    }
    //getter
    get page() {
        return this._page;
    }
    async login(url) {
         await this._page.goto(url);
         //do whatever is related to the login process
    }
}

module.exports = {Crawler};

请注意,我们不能在构造函数中使用异步函数。由于启动浏览器是异步的,我们在创建对象时使用类似build 的函数来启动浏览器。然后我们像这样创建爬虫对象:

//2.js
const {Crawler} = require('./1.js');

(async() => {
    let crawler = await Crawler.build(); 
    await crawler.login("https://example.com");
    //access crawler's page
    console.log(crawler.page.url());
})();

请注意,这只是一个示例,绝不能代表最佳做法。所以首先,你需要了解你想从这种封装中实现什么,然后采用最适合你的方法。

阅读更多关于 JS 类的信息here

【讨论】:

    猜你喜欢
    • 2021-12-15
    • 1970-01-01
    • 2018-01-29
    • 2021-01-05
    • 1970-01-01
    • 1970-01-01
    • 2018-08-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多