木偶:如何检查浏览器是否仍在打开并正常工作

时间:2018-08-27 19:09:22

标签: javascript puppeteer

我试图在一个浏览器实例中打开多个选项卡,完成后我关闭这些选项卡,然后每隔x秒重新打开这些选项卡...但是我想保持浏览器本身处于打开状态,所以我没有登录每个循环的每个标签页

因此浏览器保持打开状态,标签页会打开和关闭

这是我的简化代码,请忽略语法错误

var  global_browser = false ;
async function init_puppeteer( settings ) {



    if(global_browser === false )
        global_browser = await puppeteer.launch({headless: false  , args:['--no-sandbox']});

    for(var i = 0  ; i < settings.length ; i++ )
    {
        var setting = settings[i];
        open_tab($setting);
    }
}



 async function open_tab( setting ){
    const page    = await global_browser.newPage();
    // do stuff 
    page.close();   
}

setInterval(function (){
    init_puppeteer(settings)
}, 50000 );

这是问题所在,有时浏览器崩溃或由于某种原因而关闭,但是global_browser仍然是伪造者的对象/实例...诅咒当我尝试使用该实例打开标签页时,它将无法正常工作,我得到类似的东西

(node:5720) UnhandledPromiseRejectionWarning: Error: WebSocket is not open: readyState 3 (CLOSED)

这是我的问题,我该如何检查并确保我在global_browser中有一个正在运行的/开放的puppeteer实例?这样我就可以创建一个新实例,如果上一个实例已关闭,则可以替换它

3 个答案:

答案 0 :(得分:3)

使用browser.on('disconnected')

您可以使用browser.on('disconnected')来侦听关闭或崩溃的浏览器,或者是否调用了browser.disconnect()方法。

然后,您可以自动重新启动浏览器,然后继续执行程序。

以下类将启动浏览器,并在触发'disconnected'事件时自动重新启动浏览器:

class BrowserHandler
{
    constructor ()
    {
        const launch_browser = async () =>
        {
            this.browser = false;
            this.browser = await puppeteer.launch();
            this.browser.on( 'disconnected', launch_browser );
        };

        ( async () => { await launch_browser(); } )();
    }
}

BrowserHandler.browser在断开连接后将返回false

此外,以下功能将使您能够强制程序等待浏览器完成启动之后再继续操作:

const wait_for_browser = browser_handler => new Promise( ( resolve, reject ) =>
{
    const browser_check = setInterval( () =>
    {
        if ( browser_handler.browser !== false )
        {
            clearInterval( browser_check );

            resolve( true );
        }

    }, 100 );
});

完整示例:

'use strict';

const puppeteer = require( 'puppeteer' );

/**
 * Class: BrowserHandler
 *     Relaunch Browser when Closed
 *     Return false when Browser is Disconnected
 */

class BrowserHandler
{
    constructor ()
    {
        const launch_browser = async () =>
        {
            this.browser = false;
            this.browser = await puppeteer.launch();
            this.browser.on( 'disconnected', launch_browser );
        };

        ( async () => { await launch_browser(); } )();
    }
}

/**
 * Function: wait_for_browser
 *     Wait for Browser to Finish Launching
 */

const wait_for_browser = browser_handler => new Promise( ( resolve, reject ) =>
{
    const browser_check = setInterval( () =>
    {
        if ( browser_handler.browser !== false )
        {
            clearInterval( browser_check );

            resolve( true );
        }

    }, 100 );
});

// Main Program

( async () =>
{
    // Open Browser

    const browser_handler = new BrowserHandler;

    await wait_for_browser( browser_handler );

    // Open New Page

    let page = await browser_handler.browser.newPage();

    await page.goto( 'https://www.example.com/' );

    // Disconnect and Automatically Reconnect Browser

    browser_handler.browser.disconnect();

    if ( browser_handler.browser === false )
    {
        console.log( 'The browser has been disconnected.' );

        await wait_for_browser( browser_handler );
    }

    console.log( 'The browser has been reconnected.' );

    // Close and Automatically Reopen Browser

    await browser_handler.browser.close();

    if ( browser_handler.browser === false )
    {
        console.log( 'The browser has been closed.' );

        await wait_for_browser( browser_handler );
    }

    console.log( 'The browser has been reopened.' );

    // Force Close Puppeteer

    process.exit();
})();

结果:

  

浏览器已断开连接。

     

浏览器已重新连接。

     

浏览器已关闭。

     

浏览器已重新打开。

答案 1 :(得分:1)

您可以创建一个非常简单的函数来了解浏览器进程是否被杀死。

async function wasBrowserKilled(browser){
  const procInfo = await browser.process();
  return !!procInfo.signalCode; // null if browser is still running
}

我们可以在这里使用它,

const browserKilled = await wasBrowserKilled(global_browser);
if(global_browser === false || browserKilled)

它将检查浏览器是否被杀死,否则将替换它。

这只是API提供的众多方法中的一种。

这是我用来测试的代码,请查看我在browser.close()部分中注释掉后输出的变化。

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  // comment out to keep browser open
  await browser.close();
  console.log({browserKilled: await wasBrowserKilled(browser)});
});

async function wasBrowserKilled(browser){
  const procInfo = await browser.process();
  return !!procInfo.signalCode;
}

登录此处

➜  puppeteer-xvfb git:(direct-script) ✗ node temp/interval_tab.js
{ browserKilled: true }
➜  puppeteer-xvfb git:(direct-script) ✗ node temp/interval_tab.js
{ browserKilled: false }
_

这与事件不同。我专门制作了此代码段,以检查此特定问题的过程,并在此检查并在需要时运行它。

请注意,这只会在浏览器崩溃或以某种方式关闭时产生结果。

答案 2 :(得分:1)

如果您仅关闭所有标签页(或浏览器窗口),但浏览器进程仍然存在(但没有任何窗口)。

disconnected事件不会被触发。

然后,您可以检查是否通过以下方式关闭了所有标签页:

        if ((await browser.pages()).length === 0) {
          // no tabs opening, do stuff
        }