如何通过 Python 使用 GeckoDriver 和 Firefox 使 Selenium 脚本无法检测?

How can I make a Selenium script undetectable using GeckoDriver and Firefox through Python?

有没有办法使用 geckodriver 让您的 Selenium 脚本在 Python 中检测不到?

我正在使用 Selenium 进行抓取。我们是否需要使用任何保护措施才能使网站无法检测到 Selenium?

事实上 selenium 驱动 Firefox / GeckoDriver 被检测到 并不依赖于任何特定的 GeckoDriverFirefox 版本。 Websites 本身可以检测网络流量并可以识别 Browser ClientWeb Browser 作为 WebDriver 控制.

根据 WebDriver Interface in the latest editor's draft of WebDriver - W3C Living Document the webdriver-active flag which is initially set as false, is set to true when the user agent is under remote control i.e. when controlled through 的文档。

现在 NavigatorAutomationInformation 接口不应暴露在 WorkerNavigator.

所以,

webdriver
    Returns true if webdriver-active flag is set, false otherwise.

其中,

navigator.webdriver
    Defines a standard way for co-operating user agents to inform the document that it is controlled by WebDriver, for example so that alternate code paths can be triggered during automation.

所以,底线是:

Selenium identifies itself


然而,一些避免在网络抓取时被检测到的通用方法如下:

  • 网站可以确定您的 script/program 的首要属性是通过您的 显示器大小 。所以建议不要使用常规的Viewport.
  • 如果您需要向一个网站发送多个请求,则需要在每个请求中不断更改 User Agent。在这里您可以找到关于
  • 的详细讨论
  • 为了模拟人类行为,您可能需要减慢脚本执行速度甚至超过WebDriverWait and expected_conditions inducing time.sleep(secs). Here you can find a detailed discussion on

有多种方法可以避免网站检测到 Selenium 的使用。

  1. navigator.webdriver的值在使用Selenium时默认设置为true。此变量将出现在 Chrome 以及 Firefox 中。此变量应设置为“未定义”以避免检测。

  2. 也可以使用代理服务器来避免检测。

  3. 一些网站能够使用浏览器的状态来确定您是否在使用 Selenium。您可以将 Selenium 设置为使用自定义浏览器配置文件来避免这种情况。

下面的代码使用了所有这三种方法。

profile = webdriver.FirefoxProfile('C:\Users\You\AppData\Roaming\Mozilla\Firefox\Profiles\something.default-release')

PROXY_HOST = "12.12.12.123"
PROXY_PORT = "1234"
profile.set_preference("network.proxy.type", 1)
profile.set_preference("network.proxy.http", PROXY_HOST)
profile.set_preference("network.proxy.http_port", int(PROXY_PORT))
profile.set_preference("dom.webdriver.enabled", False)
profile.set_preference('useAutomationExtension', False)
profile.update_preferences()
desired = DesiredCapabilities.FIREFOX

driver = webdriver.Firefox(firefox_profile=profile, desired_capabilities=desired)

代码为 运行 后,您将能够手动检查浏览器 运行 by Selenium 现在是否具有您的 Firefox 历史记录和扩展。您还可以在开发工具控制台中输入“navigator.webdriver”来检查它是否未定义。

根据当前 WebDriver W3C Editor's Draft 规范:

The webdriver-active flag is set to true when the user agent is under remote control. It is initially false.

因此,readonly boolean 属性 webdriver returns 如果设置了 webdriver-active 标志,则为 true,否则为 false .

进一步规范进一步阐明:

navigator.webdriver Defines a standard way for co-operating user agents to inform the document that it is controlled by WebDriver, for example so that alternate code paths can be triggered during automation.


有无数次讨论要求 Feature: option to disable navigator.webdriver == true ? and @whimboo in his comment 得出以下结论:

that is because the WebDriver spec defines that property on the Navigator object, which has to be set to true when tests are running with webdriver enabled:

https://w3c.github.io/webdriver/#interface

Implementations have to be conformant to this requirement. As such we will not provide a way to circumvent that.


一般性结论

从以上讨论可以得出结论:

Selenium identifies itself

并且无法隐藏浏览器受 驱动的事实。


建议

然而,一些用户建议的方法可以通过使用 and 来隐藏 Mozilla Firefox 浏览器是 WebDriver 控制的事实,如下所示:

compatible code

from selenium.webdriver import Firefox
from selenium import webdriver
from selenium.webdriver.firefox.service import Service
from selenium.webdriver.firefox.options import Options

profile_path = r'C:\Users\Admin\AppData\Roaming\Mozilla\Firefox\Profiles\s8543x41.default-release'
options=Options()
options.set_preference('profile', profile_path)
options.set_preference('network.proxy.type', 1)
options.set_preference('network.proxy.socks', '127.0.0.1')
options.set_preference('network.proxy.socks_port', 9050)
options.set_preference('network.proxy.socks_remote_dns', False)
service = Service('C:\BrowserDrivers\geckodriver.exe')
driver = Firefox(service=service, options=options)
driver.get("https://www.google.com")
driver.quit()

其他选择

观察到在一些具体的 variants a couple of diverse settings/configuration can bypass the 检测中,如下:

compatible code block

from selenium import webdriver
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.chrome.service import Service

options = Options()
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('excludeSwitches', ['enable-logging'])
options.add_experimental_option('useAutomationExtension', False)
options.add_argument('--disable-blink-features=AutomationControlled')
s = Service('C:\BrowserDrivers\geckodriver.exe')
driver = webdriver.Chrome(service=s, options=options)

可能的解决方案

一个可能的解决方案是使用 浏览器,如下所示:

compatible code

from selenium.webdriver import Firefox  
from selenium import webdriver
from selenium.webdriver.firefox.service import Service
from selenium.webdriver.firefox.options import Options
import os

torexe = os.popen(r'C:\Users\username\Desktop\Tor Browser\Browser\TorBrowser\Tor\tor.exe')
profile_path = r'C:\Users\username\Desktop\Tor Browser\Browser\TorBrowser\Data\Browser\profile.default'
firefox_options=Options()
firefox_options.set_preference('profile', profile_path)
firefox_options.set_preference('network.proxy.type', 1)
firefox_options.set_preference('network.proxy.socks', '127.0.0.1')
firefox_options.set_preference('network.proxy.socks_port', 9050)
firefox_options.set_preference("network.proxy.socks_remote_dns", False)
firefox_options.binary_location = r'C:\Users\username\Desktop\Tor Browser\Browser\firefox.exe'
service = Service('C:\BrowserDrivers\geckodriver.exe')
driver = webdriver.Firefox(service=service, options=firefox_options)
driver.get("https://www.tiktok.com/")

这听起来可能很简单,但是如果你看看网站是如何通过跟踪动作来检测 selenium(或机器人)的,那么如果你可以让你的程序稍微像人类浏览网站一样,你可以获得更少的验证码,例如在操作之间添加 cursor/page 滚动动作 ,以及其他模仿浏览的动作。因此,在两个操作之间尝试添加一些其他操作,添加一些延迟等。这会使您的机器人变慢并且可能无法被发现。

谢谢