记录一个nodejs pupepteer 的bug修复

首先说一下这是我自己封装的一个puppteer的浏览器实例池,代码如下

import puppeteer from "puppeteer";
import {EventEmitter} from 'events';
import {isImageOrVideo} from "../utils/utils.js";
import {config as browserPoolConfig} from "../config/spider.js";

const {headless, poolSize} = browserPoolConfig;
EventEmitter.setMaxListeners(0);

const queue = [];
for (let i = 0; i < poolSize; i++) {
  const browser = await puppeteer.launch({headless});
  queue.push(browser);
}

/**
 * 获取一个新的浏览器实例
 * @returns {Promise<Browser|*>}
 */
const getBrowser = async () => {
  if (queue.length === 0) {
    return await puppeteer.launch({headless});
  }
  let res = queue.shift();
  return res;
};

/**
 * 获取浏览器的网页并阻止该网页内的图片和视频请求这样可以防止超时问题
 * @param browser
 * @returns {Promise<*>}
 */
const getBrowserPageWithoutPicAndVideo = async (browser) => {
  // 获取page
  let page = await browser.newPage();
  await page.setRequestInterception(true);
  page.on('request', (request) => {
    const url = request.url();
    if (isImageOrVideo(url)) {
      request.abort();
    } else {
      request.continue();
    }
  });
  return page;
};
/**
 * 归还浏览器重新返回内存中,方便复用
 * @param browser
 */
const backBrowser = async (browser) => {
  let pages = await browser.pages();
  // 要留一个不然browser就关闭了 后面newPage就卡死了 之前写的是0
  if (pages.length > 1) {
    // 关闭页面
    for (let i = 1; i < pages.length; i++) {
      let page = pages[i];
      await page.close();
    }
  }
  if (queue.length >= poolSize) {
    await browser.close();
    return;
  }
  queue.push(browser);
};
/**
 * 销毁原来的出错的浏览器实例并创建一个新的放入缓存中
 * @param browser
 * @returns {Promise<void>}
 */
const browserUpdate = async (browser) => {
  await browser.close();
  if (queue.length >= poolSize) {
    return;
  }
  const browserNew = await puppeteer.launch({headless});
  queue.push(browserNew);
};
export default {
  getBrowser,
  backBrowser,
  browserUpdate,
  getBrowserPageWithoutPicAndVideo
};

截图看一下bug是什么。

 ProtocolError: Target.createTarget timed out. Increase the 'protocolTimeout' setting in launch/connect calls for a higher timeout if needed.
file:///C:/Users/WuFeng/Desktop/project/gupiaoTips/Server/node_modules/.pnpm/puppeteer-core@21.7.0/node_modules/puppeteer-core/lib/esm/puppeteer/common/CallbackRegistry.js:72 
            this._reject(callback, new TargetCloseError('Target closed'));
                                   ^

TargetCloseError: Protocol error (Target.createTarget): Target closed

上面两个问题都是同一个地方产生的。

然后我的调试最后发现是getBrowserPageWithoutPicAndVideo函数里面的browser.newPage()这个函数卡死在这里了,然后导致超时了。

后面分析查看打印日志都发现不了bug,然后newPage函数的前后打印,browser的数据的时候想到打印一下pages。最后发现在browser实例生成的时候就会自带一个page,所以想到在归还browser实例的时候是不是不能全部清空pages,后面测试发现就是这个问题,各种地方搜索挺久没发现这个答案,对于不明白原理的我和朋友确实挺难发现的。

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值