木偶不关闭浏览器

Eli*_*iss 2 puppeteer

我在express / node / ubuntu上运行puppeteer,如下所示:

var puppeteer = require('puppeteer');
var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
    (async () => {
        headless = true;
        const browser = await puppeteer.launch({headless: true, args:['--no-sandbox']});
        const page = await browser.newPage();
        url = req.query.url;
        await page.goto(url);
        let bodyHTML = await page.evaluate(() => document.body.innerHTML);
        res.send(bodyHTML)
        await browser.close();
    })();
});
Run Code Online (Sandbox Code Playgroud)

多次运行此脚本会留下数百个僵尸:

$ pgrep chrome | wc -l
133
Run Code Online (Sandbox Code Playgroud)

哪个阻塞了srv,

我该如何解决?

kill从Express JS脚本运行可以解决吗?

除了木偶戏和无头镀铬之外,还有没有更好的方法来获得相同的结果?

Ram*_*jan 23

啊!这是一个简单的疏忽。如果发生错误并且您await browser.close()永远不会执行,从而使您陷入僵局怎么办。

使用shell.js似乎是解决这个问题的一种hacky 方式。

更好的做法是使用try..catch..finally. 原因是您希望浏览器关闭,而不管流程是否顺利或抛出错误。与其他代码片段不同的是,您不必尝试在catch块和finally块中关闭浏览器。finally无论是否抛出错误,块总是被执行。

所以,你的代码应该看起来像,

const puppeteer = require('puppeteer');
const express = require('express');

const router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  (async () => {
    const browser = await puppeteer.launch({
      headless: true,
      args: ['--no-sandbox'],
    });

    try {
      const page = await browser.newPage();
      url = req.query.url;
      await page.goto(url);
      const bodyHTML = await page.evaluate(() => document.body.innerHTML);
      res.send(bodyHTML);
    } catch (e) {
      console.log(e);
    } finally {
      await browser.close();
    }
  })();
});

Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!

  • `browser` 需要在外部作用域中声明,以便它位于 `finally` 块的作用域内,否则您将得到 `ReferenceError: browser is not Define`。这段代码还创建了各种全局变量,“headless”和“url”。始终使用“const”或“let”来正确确定变量的范围。 (2认同)

com*_*tos 13

根据我的经验,调用 close 后浏览器关闭过程可能需要一些时间。无论如何,您可以检查浏览器进程属性以检查它是否仍未关闭并强制终止它。

if (browser && browser.process() != null) browser.process().kill('SIGINT');
Run Code Online (Sandbox Code Playgroud)

我还在下面发布了我的木偶资源管理器的完整代码。看一眼bw.on('disconnected', async () => {

if (browser && browser.process() != null) browser.process().kill('SIGINT');
Run Code Online (Sandbox Code Playgroud)


Mic*_*zuk 7

我今天自己也遇到了这个问题,并且找到了解决方案。Chromium 未关闭的问题似乎是由于页面未关闭所致。在调用之前关闭所有页面browser.close(),一切都应该没问题:

const pages = await browser.pages();
for (let i = 0; i < pages.length; i++) {
    await pages[i].close();
}
await browser.close()
Run Code Online (Sandbox Code Playgroud)

希望这对某人有帮助!


Eli*_*iss 5

我用https://www.npmjs.com/package/shelljs解决了

var shell = require('shelljs');
shell.exec('pkill chrome')
Run Code Online (Sandbox Code Playgroud)

  • 这个答案很糟糕,因为它会杀死所有 chrome 实例。在原始代码中,很明显puppeteer是在一个API中运行的,这意味着如果同时有超过1个api请求,其他请求将会失败。 (4认同)
  • 不敢相信这是公认的答案。不是为了答案本身,而是因为我们几乎被迫这样做只是为了简单地关闭 puppeteer 进程 (2认同)

Muk*_*esh 5

像这样将代码包装在try-catch中,看看是否有帮助

headless = true;
const browser = await puppeteer.launch({headless: true, args:['--no-sandbox']});
try {
  const page = await browser.newPage();
  url = req.query.url;
  await page.goto(url);
  let bodyHTML = await page.evaluate(() => document.body.innerHTML);
  res.send(bodyHTML);
  await browser.close();
} catch (error) {
  console.log(error);
  await browser.close();
} finally {
  await browser.close();
}
Run Code Online (Sandbox Code Playgroud)

  • 好点,10 倍。但是,我认为 `try` 应该在 `const browser =...` 之后,以便在 `catch/finally` 中使用它,不是吗? (2认同)
  • “try”和“catch”块中的“await browser.close();”是多余的。无论是否抛出错误,“finally”都会在两个块之后运行。使用 `const url` 和 `const headless` 来避免不必要的、容易出错的全局变量。 (2认同)

归档时间:

查看次数:

4450 次

最近记录:

6 年,2 月 前