.NET Core6+Selenium无头模式防检测:代理修改响应无效求助
解决Selenium无头模式防检测及页面预注入JS问题
方法一:通过Chrome DevTools Protocol(CDP)预注入JS
直接利用CDP的Page.addScriptToEvaluateOnNewDocument接口,可在页面所有脚本执行前注入自定义JS,完美修复window.chrome等无头模式下缺失的变量,无需依赖代理,是更可靠的方案。
实现代码
using OpenQA.Selenium; using OpenQA.Selenium.Chrome; using OpenQA.Selenium.DevTools; using OpenQA.Selenium.DevTools.V118.Page; // 版本需与ChromeDriver对应 var options = new ChromeOptions(); // 配置无头模式与基础防检测参数 options.AddArgument("--headless=new"); // Chrome 112+推荐的新无头模式,更贴近正常浏览器行为 options.AddArgument("--disable-blink-features=AutomationControlled"); options.AddArgument("--no-sandbox"); options.AddArgument("--disable-dev-shm-usage"); // 禁用自动化相关提示与扩展 options.AddExcludedArgument("enable-automation"); options.AddAdditionalChromeOption("useAutomationExtension", false); // 禁用密码管理等可能暴露自动化的配置 options.AddUserProfilePreference("credentials_enable_service", false); options.AddUserProfilePreference("profile.password_manager_enabled", false); using var driver = new ChromeDriver(options); var devToolsSession = driver.GetDevToolsSession(); // 注入修复脚本,确保页面加载前执行 await devToolsSession.SendCommandAsync(new AddScriptToEvaluateOnNewDocumentCommandSettings { Source = @" // 补全window.chrome对象 window.chrome = { app: { isInstalled: false }, webstore: { onInstallStageChanged: {}, onDownloadProgress: {} }, runtime: { PlatformOs: 'win', PlatformArch: 'x86-64', PlatformNaclArch: 'x86-64', requestUpdateCheck: () => Promise.resolve({ status: 'no_update' }) } }; // 移除navigator.webdriver标记 Object.defineProperty(navigator, 'webdriver', { get: () => undefined }); // 修复其他易被检测的属性 Object.defineProperty(navigator, 'plugins', { get: () => Array(3).fill({}) }); Object.defineProperty(navigator, 'languages', { get: () => ['zh-CN', 'zh'] }); " }); // 访问目标站点,注入脚本已提前生效 driver.Navigate().GoToUrl("https://www.example.com");
注意:DevTools命名空间版本需与ChromeDriver版本完全匹配(如ChromeDriver 118.x对应
V118),否则会出现接口调用失败。
方法二:修复Titanium Web Proxy的HTTPS配置
你遇到的curl生效但Selenium无效的问题,核心原因是Chrome未信任Titanium Web Proxy生成的根证书,导致HTTPS请求被拦截失败。以下是修复步骤:
实现代码
using Titanium.Web.Proxy; using Titanium.Web.Proxy.Models; using OpenQA.Selenium.Chrome; using System.Security.Cryptography.X509Certificates; var proxyServer = new ProxyServer(); var explicitEndPoint = new ExplicitProxyEndPoint(System.Net.IPAddress.Any, 8080, true); // 生成并导出代理根证书 proxyServer.CertificateManager.CreateRootCertificate(); var certPath = Path.Combine(Environment.CurrentDirectory, "proxy-root.cer"); proxyServer.CertificateManager.ExportRootCertificateAsCer(certPath); var rootCert = new X509Certificate2(certPath); // 注册响应修改逻辑 proxyServer.BeforeResponse += async (sender, e) => { if (e.HttpClient.Request.RequestUri.Host.Equals("www.example.com", StringComparison.OrdinalIgnoreCase) && e.HttpClient.Response.StatusCode == 200) { var originalBody = await e.GetResponseBodyAsString(); // 修改页面标题 var modifiedBody = originalBody.Replace("<title>Example Domain</title>", "<title>Modified by Proxy</title>"); await e.SetResponseBodyString(modifiedBody); } }; // 启动代理 proxyServer.AddEndPoint(explicitEndPoint); proxyServer.Start(); // 配置Chrome信任代理证书 var chromeOptions = new ChromeOptions(); chromeOptions.AddArgument($"--proxy-server=http://localhost:8080"); // 跳过证书校验,或手动将证书导入系统/Chrome配置 chromeOptions.AddArgument($"--ignore-certificate-errors-spki-list={rootCert.GetPublicKeyString()}"); // 启动Selenium并访问站点 using var driver = new ChromeDriver(chromeOptions); driver.Navigate().GoToUrl("https://www.example.com"); // 清理资源 proxyServer.Stop();
关键注意事项
- 确保ChromeDriver版本与本地Chrome浏览器版本一致,避免代理配置不兼容
- 若长期使用,建议将代理根证书导入系统信任列表,避免每次启动都需添加
--ignore-certificate-errors-spki-list参数
方案对比
| 方案 | 优点 | 缺点 |
|---|---|---|
| CDP预注入 | 无需额外依赖、执行时机精准、无证书问题 | 仅支持Chrome/Edge等基于Chromium的浏览器 |
| Titanium Web Proxy | 可修改所有HTTP/HTTPS响应、支持多浏览器 | 需处理证书信任、配置相对复杂 |
优先推荐CDP方案,更适合Selenium无头模式的防检测需求。
内容的提问来源于stack exchange,提问作者BlackHawkCH91
相关产品推荐
相关产品推荐

