undetected_chromedriver解决网页被检测(转载)

该文章已生成可运行项目,

一、问题分析

selenium打开浏览器模仿人工操作是诸多爬虫工作者最万能的网页数据获取方式,但是在做自动化爬虫时,经常被检测到是selenium驱动。比如前段时间selenium打开维普高级搜索时得到的页面是空白页,懂车帝对selenium反爬也很厉害。

二、Selenium为何会被检测

    主要原因是selenium打开的浏览器指纹和人工操作打开的浏览器指纹是不同的,比如最熟知的window.navigator.webdriver关键字,在selenium打开的浏览器打印返回结果为true,而正常浏览器打印结果返回为undefined,我们可以在(https://bot.sannysoft.com/)网站比较各关键字。

三、Selenium防检测方法
1. 修改window.navigator.webdriver关键字返回结果

from selenium import webdriver
options = webdriver.ChromeOptions()

# 此步骤很重要,设置为开发者模式,防止被各大网站识别出来使用了Selenium
driver = webdriver.Chrome(options=options)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
            "source": """
            Object.defineProperty(navigator, 'webdriver', {
              get: () => undefined
            })
            """
        })

但是因为浏览器指纹很多,这种方法的局限性是显而易见的。

2. 使用stealth.min.js文件防止selenium被检测

import time
from selenium.webdriver import Chrome
from selenium.webdriver.chrome.options import Options

chrome_options = Options()
chrome_options.add_argument("--headless")
chrome_options.add_argument('user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36')
driver = Chrome('./chromedriver', options=chrome_options)

with open('/Users/kingname/test_pyppeteer/stealth.min.js') as f:
    js = f.read()

driver.execute_cdp_cmd("Page.add`在这里插入代码片`ScriptToEvaluateOnNewDocument", {
  "source": js
})

stealth.min.js文件来源于puppeteer,有开发者给 puppeteer 写了一套插件,叫做puppeteer-extra。其中,就有一个插件叫做puppeteer-extra-plugin-stealth专门用来让 puppeteer 隐藏模拟浏览器的指纹特征。

python开发者就需要把其中的隐藏特征的脚本提取出来,做成一个 js 文件。然后让 Selenium 或者 Pyppeteer 在打开任意网页之前,先运行一下这个 js 文件里面的内容。

puppeteer-extra-plugin-stealth的作者还写了另外一个工具,叫做extract-stealth-evasions。这个东西就是用来生成stealth.min.js文件的。
三、使用undetected_chromedriver

undetected_chromedriver 可以防止浏览器特征被识别,并且可以根据浏览器版本自动下载驱动。不需要自己去下载对应版本的chromedriver。

import undetected_chromedriver as uc
driver = uc.Chrome()
driver.get('目标网址')

 四、undetected_chromedriver自定义功能

import undetected_chromedriver as uc
 
#specify chromedriver version to download and patch
#this did not work correctly until 1.2.1
uc.TARGET_VERSION = 78    
 
# or specify your own chromedriver binary to patch
undetected_chromedriver.install(
    executable_path='c:/users/user1/chromedriver.exe',
)
from selenium.webdriver import Chrome, ChromeOptions
opts = ChromeOptions()
opts.add_argument(f'--proxy-server=socks5://127.0.0.1:9050')
driver = Chrome(options=opts)
driver.get('目标网址')

有时候会报chrome的版本不匹配,undetected_chromedriver可以根据浏览器版本自动下载驱动,自然不存在版本不匹配问题,最终发现是undetected_chromedriver只支持chrome96及以上的版本,需将chrome浏览器版本升级。
五、undetected-chromedriver 代理插件

import os
import shutil
import tempfile

import undetected_chromedriver as webdriver


class ProxyExtension:
    manifest_json = """
    {
        "version": "1.0.0",
        "manifest_version": 2,
        "name": "Chrome Proxy",
        "permissions": [
            "proxy",
            "tabs",
            "unlimitedStorage",
            "storage",
            "<all_urls>",
            "webRequest",
            "webRequestBlocking"
        ],
        "background": {"scripts": ["background.js"]},
        "minimum_chrome_version": "76.0.0"
    }
    """

    background_js = """
    var config = {
        mode: "fixed_servers",
        rules: {
            singleProxy: {
                scheme: "http",
                host: "%s",
                port: %d
            },
            bypassList: ["localhost"]
        }
    };

    chrome.proxy.settings.set({value: config, scope: "regular"}, function() {});

    function callbackFn(details) {
        return {
            authCredentials: {
                username: "%s",
                password: "%s"
            }
        };
    }

    chrome.webRequest.onAuthRequired.addListener(
        callbackFn,
        { urls: ["<all_urls>"] },
        ['blocking']
    );
    """

    def __init__(self, host, port, user, password):
        self._dir = os.path.normpath(tempfile.mkdtemp())

        manifest_file = os.path.join(self._dir, "manifest.json")
        with open(manifest_file, mode="w") as f:
            f.write(self.manifest_json)

        background_js = self.background_js % (host, port, user, password)
        background_file = os.path.join(self._dir, "background.js")
        with open(background_file, mode="w") as f:
            f.write(background_js)

    @property
    def directory(self):
        return self._dir

    def __del__(self):
        shutil.rmtree(self._dir)


if __name__ == "__main__":
    proxy = ("64.32.16.8", 8080, "username", "password")  # your proxy with auth, this one is obviously fake
    proxy_extension = ProxyExtension(*proxy)

    options = webdriver.ChromeOptions()
    options.add_argument(f"--load-extension={proxy_extension.directory}")
    driver = webdriver.Chrome(options=options)

    driver.get("Just a moment...")
    driver.quit()

附带浏览器环境检测网址:https://bot.sannysoft.com/ 

本文章已经生成可运行项目
### 关于 `undetected_chromedriver` 的使用教程 #### 安装库 为了开始使用 `undetected_chromedriver`,需要先通过 pip 工具来安装这个 Python 库。执行以下命令可以完成安装: ```bash pip install undetected-chromedriver ``` 此命令将会下载并安装最新版本的 `undetected_chromedriver` 及其依赖项[^2]。 #### 创建驱动实例 一旦安装完毕,在编写脚本时首先要导入必要的模块,并设置好 ChromeDriver 所在的位置以及任何所需的选项。下面是一个简单的例子展示如何创建一个未被检测到的 Chrome 浏览器实例: ```python import undetected_chromedriver.v2 as uc options = uc.ChromeOptions() # 添加实验性质开关以隐藏自动化标志 options.add_argument('--disable-blink-features=AutomationControlled') driver = uc.Chrome(options=options) try: # 访问目标网址 driver.get('https://example.com') finally: # 结束会话前关闭浏览器窗口 driver.quit() ``` 这段代码中设置了自定义参数以防止某些类型的自动化特征暴露给访问的目标站点,从而提高了隐身效果[^4]。 #### 处理高级特性 对于更复杂的场景,可能还需要进一步调整浏览器行为或环境变量。例如,可以通过修改页面加载过程中 JavaScript 上下文中的属性值来规避特定的安全检查: ```python from selenium import webdriver # ... 初始化部分同上 ... # 修改 navigator.webdriver 属性使其无法被探测到 script_to_execute = ''' Object.defineProperty(navigator, 'webdriver', { get: () => undefined }) ''' driver.execute_script(script_to_execute) ``` 上述方法能够有效地让大多数基于 WebDriver 特征判断是否为机器人程序的技术失效。 #### 运行样例代码 最后给出完整的运行示例,它综合运用了前面提到的各项技术要点: ```python import time import undetected_chromedriver.v2 as uc if __name__ == "__main__": options = uc.ChromeOptions() # 设置一些额外选项增强隐蔽性 options.add_argument("--no-sandbox") # 解决DevToolsActivePort文件不存在报错问题. options.add_argument("--disable-dev-shm-usage") # 改善性能 options.add_argument("--start-maximized") # 将窗口最大化显示 options.add_argument('--disable-blink-features=AutomationControlled') try: with uc.Chrome(options=options) as driver: url = "http://www.example.org" print(f"Navigating to {url}") driver.get(url) # 等待几秒钟以便观察结果 time.sleep(5) except Exception as e: print(e) finally: pass # 此处无需显式调用 quit() 方法因为已经用了上下文管理器 ``` 以上就是有关 `undetected_chromedriver` 的基本使用指南,希望可以帮助读者快速入门并应用于实际项目当中[^1][^3].
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值