/** * Standard Browser 启动:puppeteer-extra + StealthPlugin */ const fs = require('fs'); const path = require('path'); const puppeteer = require('puppeteer-extra'); const StealthPlugin = require('puppeteer-extra-plugin-stealth'); const { BASE_LAUNCH_ARGS, assertChromeExecutable, buildBrowserLaunchEnv, ensureRuntimeSubdir, } = require('./constants'); // Stealth 必须在 launch 之前注册 puppeteer.use(StealthPlugin()); /** * 启动 standard profile Browser * @param {string[]} [extraArgs] * @returns {Promise} */ async function launchStandardBrowser(extraArgs = []) { const executablePath = assertChromeExecutable(); const userDataDir = fs.mkdtempSync(path.join(ensureRuntimeSubdir('chrome-profiles'), 'run-')); try { const browser = await puppeteer.launch({ executablePath, headless: 'new', args: [...BASE_LAUNCH_ARGS, ...extraArgs], env: buildBrowserLaunchEnv(), userDataDir, }); const originalClose = browser.close.bind(browser); browser.close = async () => { try { await originalClose(); } finally { try { fs.rmSync(userDataDir, { recursive: true, force: true }); } catch (_) { /* 清理失败不影响主流程 */ } } }; return browser; } catch (err) { try { fs.rmSync(userDataDir, { recursive: true, force: true }); } catch (_) { /* ignore */ } throw err; } } module.exports = { launchStandardBrowser };