/** * 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'); const { resolveProfileDir } = require('./profile-dir'); puppeteer.use(StealthPlugin()); /** * @param {string[]} [extraArgs] * @param {{ sessionKey?: string, profile?: 'standard'|'real' }} [options] * @returns {Promise} */ async function launchStandardBrowser(extraArgs = [], options = {}) { const executablePath = assertChromeExecutable(); const profile = options.profile === 'real' ? 'real' : 'standard'; const persistentDir = options.sessionKey ? resolveProfileDir(options.sessionKey, profile) : null; const userDataDir = persistentDir || fs.mkdtempSync(path.join(ensureRuntimeSubdir('chrome-profiles'), 'run-')); const persistent = !!persistentDir; try { const browser = await puppeteer.launch({ executablePath, headless: 'new', args: [...BASE_LAUNCH_ARGS, ...extraArgs], env: buildBrowserLaunchEnv(), userDataDir, }); if (!persistent) { const originalClose = browser.close.bind(browser); browser.close = async () => { try { await originalClose(); } finally { try { fs.rmSync(userDataDir, { recursive: true, force: true }); } catch (_) { /* ignore */ } } }; } browser.__userDataDir = userDataDir; browser.__persistentProfile = persistent; return browser; } catch (err) { if (!persistent) { try { fs.rmSync(userDataDir, { recursive: true, force: true }); } catch (_) { /* ignore */ } } throw err; } } module.exports = { launchStandardBrowser };