繁体   English   中英

C# Selenium 在页面加载时注入/执行 JS

[英]C# Selenium Inject/execute JS on page load

我正在使用带有 C# 10 的 .NET Core 6。

我想要实现的是在无头模式下运行 Selenium,同时保持“不可检测”。 我按照这里的说明进行操作: https ://intoli.com/blog/not-possible-to-block-chrome-headless/ 它提供了一个页面来测试您的机器人: https ://intoli.com/blog/not- 可能阻止 chrome-headless/chrome-headless-test.html

无头模式会导致某些 JS 变量(如 window.chrome)未设置或无效,从而导致检测到机器人。

IJavaScriptExecutor 不起作用,因为它在页面加载后运行。 同一作者在本文中提到您必须捕获响应并注入 JS: https ://intoli.com/blog/making-chrome-headless-undetectable/(将其放在一起部分)

由于本文使用 python,我遵循了这个: https ://www.automatetheplanet.com/webdriver-capture-modify-http-traffic/ 和这个: Titanium Web Proxy - Can't modify request body which uses the Titanium Web Proxy library (在这里找到: https ://github.com/justcoding121/titanium-web-proxy)

为了测试,我使用了这个站点http://www.example.com并尝试修改响应(更改 HTML 中的某些内容,设置 JS 变量等)

这是代理类:

public static class Proxy
    {
        static ProxyServer proxyServer = new ProxyServer(userTrustRootCertificate: true);
        public static void StartProxy()
        {
            //Run on port 8080, decrypt ssl
            ExplicitProxyEndPoint explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8080, true);

            proxyServer.Start();
            proxyServer.AddEndPoint(explicitEndPoint);

            proxyServer.BeforeResponse += OnBeforeResponse;
        }

        static async Task OnBeforeResponse(object sender, SessionEventArgs ev)
        {
            var request = ev.HttpClient.Request;
            var response = ev.HttpClient.Response;

            //Modify title tag in example.com
            if (String.Equals(ev.HttpClient.Request.RequestUri.Host, "www.example.com", StringComparison.OrdinalIgnoreCase))
            {
                var body = await ev.GetResponseBodyAsString();

                body = body.Replace("<title>Example Domain</title>", "<title>Completely New Title</title>");

                ev.SetResponseBodyString(body);
            }
        }

        public static void StopProxy()
        {
            proxyServer.Stop();
        }
}

这是硒代码:

Proxy.StartProxy();

string url = "localhost:8080";
var seleniumProxy = new OpenQA.Selenium.Proxy 
{
    HttpProxy = url,
    SslProxy = url,
    FtpProxy = url
};

ChromeOptions options = new ChromeOptions();
options.AddArgument("ignore-certificate-errors");
options.Proxy = seleniumProxy;

IWebDriver driver = new ChromeDriver(@"C:\ChromeDrivers\103\", options);
driver.Manage().Window.Maximize();
driver.Navigate().GoToUrl("http://www.example.com");

Console.ReadLine();
TornCityBot.Proxy.StopProxy();

当 selenium 加载http://www.example.com时, <title>Example Domain</title>应该更改为<title>Completely New Title</title> ,但没有任何变化。 我尝试将代理 URL 设置为 http://localhost:8080、127.0.0.1:8080、localhost:8080 等,但没有任何变化。

作为测试,我运行了代码并让代理保持开启状态。 然后我在 git bash 中运行curl --proxy http://localhost:8080 http://www.example.com ,输出为:

<!doctype html>
<html>
<head>
    <title>Completely New Title</title>
. . .

代理正在工作,它正在修改 curl 命令的响应。 但由于某种原因,它不适用于硒。

如果你们有一个也可以在 HTTPS 上工作的解决方案,或者在页面加载时执行 JavaScript 的更好方法,那就太好了。 如果不可能,那么我可能需要忘记无头。

提前感谢您的帮助。

Selenium.WebDriver 4.3.0ChromeDriver 103

尝试使用ExecuteCdpCommand方法

var options = new ChromeOptions();
options.AddArgument("--headless");
options.AddArgument("--user-agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'");

using var driver = new ChromeDriver(options);

Dictionary<string, object> cmdParams= new();
cmdParams.Add("source", "Object.defineProperty(navigator, 'webdriver', { get: () => false });");
driver.ExecuteCdpCommand("Page.addScriptToEvaluateOnNewDocument", cmdParams);

使用这段代码,我们绕过了前两个,但是如果您按照您已经提到的指南进行操作,我认为绕过其余部分很容易。

在此处输入图像描述

更新

var initialScript = @"Object.defineProperty(Notification, 'permission', {
                        get: function () { return ''; }
                        })                                
                        window.chrome = true
                        Object.defineProperty(navigator, 'webdriver', {
                        get: () => false})  
                        Object.defineProperty(window, 'chrome', {
                        get: () => true})  
                        Object.defineProperty(navigator, 'plugins', {
                        writeable: true,
                        configurable: true,
                        enumerable: true,
                        value: 'works'})                        
                        navigator.plugins.length = 1                                
                        Object.defineProperty(navigator, 'language', {
                        get: () => 'el - GR'});
                        Object.defineProperty(navigator, 'deviceMemory', {
                        get: () => 8});
                        Object.defineProperty(navigator, 'hardwareConcurrency', {
                        get: () => 8});";

cmdParams.Add("source", initialScript);
driver.ExecuteCdpCommand("Page.addScriptToEvaluateOnNewDocument", cmdParams);

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM