You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Puppeteer执行多任务时仅使用单个浏览器实例绕过反爬检测

Puppeteer 单浏览器实例多任务复用实现方案

核心思路是将浏览器实例做全局缓存,仅在首次调用时初始化,后续所有任务直接复用该实例创建新页面执行操作,完全避免重复创建浏览器触发反爬。

场景1:单脚本批量执行多任务

适合本地批量爬取多个页面的场景,代码如下:

const puppeteer = require('puppeteer');

// 全局缓存浏览器实例
let browser = null;

// 浏览器初始化方法,全程仅执行一次
async function initBrowser() {
    if (!browser) {
        browser = await puppeteer.launch({
            headless: 'new', // 采用新版无头模式,指纹更接近普通浏览器
            args: [
                '--no-sandbox',
                '--disable-setuid-sandbox',
                // 移除自动化标识,降低被检测概率
                '--disable-blink-features=AutomationControlled'
            ]
        });
        // 全局统一设置UA,保持指纹一致性
        await browser.userAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36');
    }
    return browser;
}

// 单任务执行逻辑,每个任务单独创建、销毁页面
async function execTask(targetUrl) {
    const browser = await initBrowser();
    const page = await browser.newPage();
    try {
        // 可单独为当前页面设置视窗、cookie、代理等,不影响其他页面
        await page.setViewport({ width: 1920, height: 1080 });
        await page.goto(targetUrl, { timeout: 30000, waitUntil: 'networkidle2' });

        // 此处编写你的爬虫业务逻辑
        const pageTitle = await page.title();
        console.log(`爬取成功,页面标题:${pageTitle}`);
        
        return pageTitle;
    } catch (err) {
        console.error(`爬取页面${targetUrl}失败:`, err);
        return null;
    } finally {
        // 任务执行完毕立即关闭页面,释放内存资源
        await page.close();
    }
}

// 批量任务调度示例
(async () => {
    // 待爬取的URL列表
    const taskList = [
        'https://example.com/1',
        'https://example.com/2',
        'https://example.com/3'
    ];

    // 控制并发数,避免同时打开过多页面导致浏览器卡顿
    const concurrencyLimit = 2;
    for (let i = 0; i < taskList.length; i += concurrencyLimit) {
        const currentBatch = taskList.slice(i, i + concurrencyLimit);
        await Promise.all(currentBatch.map(url => execTask(url)));
    }

    // 所有任务全部执行完成后,再关闭浏览器实例
    await browser.close();
})();

场景2:服务端常驻按需执行任务

适合用Express等框架做爬虫服务、接收到请求才执行爬取任务的场景,代码如下:

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

let browser = null;

// 服务启动时一次性初始化浏览器实例
app.listen(3000, async () => {
    browser = await puppeteer.launch({
        headless: 'new',
        args: ['--no-sandbox', '--disable-blink-features=AutomationControlled']
    });
    console.log('服务启动完成,浏览器实例已初始化');
});

// 爬取接口
app.get('/crawl', async (req, res) => {
    const { url } = req.query;
    if (!url) return res.status(400).send('缺少url参数');

    const page = await browser.newPage();
    try {
        await page.goto(url, { timeout: 30000 });
        const pageContent = await page.content();
        res.send(pageContent);
    } catch (err) {
        res.status(500).send(`爬取失败:${err.message}`);
    } finally {
        await page.close();
    }
});

注意事项

  • 复用浏览器实例时,每个页面的配置(代理、cookie、UA等)互相独立,可按需单独配置不会互相影响
  • 建议控制单浏览器实例的并发页面数在5以内,并发过高会导致浏览器响应变慢、请求超时
  • 可添加浏览器心跳检测逻辑,出现实例崩溃的情况自动重新初始化,保证服务可用性
  • 除了复用浏览器实例,还需保持页面请求间隔、指纹的一致性,避免异常行为触发反爬

内容的提问来源于stack exchange,提问作者Jack Caycedo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 14:36:02