undetected_chromedriver解决网页被检测

news2024/11/24 5:47:45

一、问题分析

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

image-20230529142325435

二、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()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/648649.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【React】setState原理,SCU,不可变对象,Ref,受控组件,高阶组件,封装轮播图组件

❤️ Author&#xff1a; 老九 ☕️ 个人博客&#xff1a;老九的CSDN博客 &#x1f64f; 个人名言&#xff1a;不可控之事 乐观面对 &#x1f60d; 系列专栏&#xff1a; 文章目录 setState原理setState异步更新 SCU不可变对象RefRef获取DOMRef获取组件 非受控组件受控组件高阶…

word目录怎么自动生成,3个步骤轻松搞定!

案例&#xff1a;我在做策划案的时候&#xff0c;需要制作目录。我觉得自己手动制作目录很困难&#xff0c;通过word的可以自动生成目录&#xff0c;但是我不知道具体的操作方法。有没有小伙伴可以分享一下&#xff1f; 在制作任务书、书写论文的时候&#xff0c;经常需要添加…

vue+java+springboot企业办公人事oa办公管理系统2142g

本企业OA管理系统有管理员和用户。管理员功能有个人中心&#xff0c;用户管理&#xff0c;公告信息管理&#xff0c;客户关系管理&#xff0c;通讯录管理&#xff0c;日程安排管理&#xff0c;车辆信息管理&#xff0c;文件信息管理&#xff0c;工作日志管理&#xff0c;上班考…

0基础学习VR全景平台篇第42篇:编辑器底部菜单-分组管理

大家好&#xff0c;欢迎观看蛙色VR官方系列——后台使用课程&#xff01; 本期为大家带来蛙色VR平台&#xff0c;底部菜单—分组管理功能操作。 功能位置示意 一、本功能将用在哪里&#xff1f; 分组管理&#xff0c;指观看者可点击不同分组&#xff0c;查看不同类型全景内容…

learn C++ NO.9——string(2)

引言&#xff1a; 现在是北京时间的2023年6月15日早上的10点14分。时间过得飞快&#xff0c;现在已经大一的最后一个星期了。明天也是大一最后一次课&#xff0c;线下的实训课。线下实训内容为c语言二级的内容&#xff0c;对我来说跟学校的课效率太低下了&#xff0c;我还是比…

初识网络之再看udp协议

目录 一、端口号 1. 五元组 2. 端口号范围划分 3. 一些知名端口号 4. 进程与端口号 5. 两个常用网络工具 5.1 netstat 5.2 pidof 二、UDP协议 1. udp协议格式 2. udp报文解包 3. udp报文分用 4. udp的特点 5. 缓冲区 5.1 tcp缓冲区 5.2 udp缓冲区 6. 一些常见…

函数重载异常的常见原因

函数重载异常的常见原因 使用重载函数时&#xff0c;如果数据类型不匹配&#xff0c;C尝试使用类型转换与形参进行匹配&#xff0c;如果转换后有多个函数能匹配上&#xff0c;编译将报错。引用可以作为函数重载的条件&#xff0c;但是&#xff0c;调用重载函数的时候&#xff0…

Linux:端口

端口是设备与外界进行通讯的出入口&#xff0c;端口可以分为物理端口和虚拟端口 物理端口&#xff1a;又叫接口&#xff0c;是可见的端口&#xff0c;比如HDMI端口、USB接口虚拟端口&#xff1a;是指计算机内部的端口&#xff0c;用来操作系统和外部进行交互使用 通过IP地址只能…

6.python高频函数-处理缺失值isnull()、fillna()、dropna()

前言 如何判断pandas.DataFrame、Series是否包含缺失值NaN以及如何处理缺失值NaN。 Part.1 isnull() 函数 使用 isnull()、isna() 确定每个元素的缺失值 如果值为 NaN&#xff0c;则值为 True&#xff0c;如果不是&#xff0c;则值为 False。 读取数据集 panel_data pd.r…

从C语言到C++_19(容器适配器+stack和queue模拟实现+优先级队列priority_queue)

目录 1. 容器适配器 1.1 什么是适配器 1.2 STL标准库中stack和queue的底层结构 2. stack和queue的模拟实现 2.1 stack模拟实现 2.2 queue的模拟实现 3. deque的介绍(了解) 3.1 deque的实现原理 3.2 deque的缺陷和使用场景 4. 优先级队列 priority_queue 4.1 priorit…

编码规范、Git分支整理

代码命名规范 包命名规范 采用反域名命名规则&#xff0c;全部使用小写字母。一级包名为com&#xff0c;二级包名kl&#xff08;为公司名称&#xff0c;可以简写&#xff09;&#xff0c;三级包名pos&#xff08;根据应用进行命名&#xff09;&#xff0c;四级包名activity或…

芳禾数据CTO李明:数据分类分级与治理驱动下的应用革命丨数据猿专访

‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 我们进入数字化时代&#xff0c;数据已经变得比任何时候都更加关键。每天&#xff0c;我们都在生成、处理和存储海量的数据&#xff0c;这些数据在企业决策、市场研究、产品开发等方面扮演着重要的角色。然而&#xff0c;数…

Qt编写精美输入法(历时十年迭代/可换肤/支持Qt4/5/6/win/linux/mac/嵌入式等)

一、前言 大概是从2012年就开始研究用Qt写输入法&#xff0c;因为项目需要&#xff0c;嵌入式板子上&#xff0c;没有对应的输入法&#xff0c;当初使用过很多NVR&#xff0c;里面也是鼠标按下弹出输入法面板进行输入&#xff0c;可以切换数字和字母及中文&#xff0c;于是借鉴…

5大趋势与10大应用场景!未来的智能工厂要这么建...

在经济下行压力、人口红利消失、消费结构升级、疫情冲击等多种因素推动下&#xff0c;制造企业加快转型步伐&#xff0c;工厂正向高效化、智能化、绿色化方向跃迁升级&#xff0c;不断涌现出技术创新、应用领先、成效显著的智能工厂。 近日&#xff0c;中国信息通信研究院发布…

常见的台账在线、可视化数据看板工具

目前已知和常见的一些在线可视化数据看板工具&#xff1a; Trello&#xff1a;Trello 是一种流行且直观的看板工具&#xff0c;可让创建看板、列表和卡片来管理任务和项目。它提供了一个可视化界面&#xff0c;可以在其中跨工作流程的不同阶段拖放卡片。还可以添加截止日期、标…

cesium调用celestrak接口获取卫星数据

celestrak是一家免费开源提供卫星空间数据的非营利性组织 接口调用 import axios from "axios";const BASE_URL "https://celestrak.org";function getTleDataFromExternal(path "") {let uri ${BASE_URL}/NORAD/elements/gp.php?GROUP${…

复习并发编程的基础知识之线程池

并发编程中&#xff0c;线程池是很重要的一块内容。 线程池是一种池化技术&#xff0c;线程池、字符串常量池和数据库链接池都属于池化技术。 使用线程池的好处&#xff1a; 1.提高了线程的利用率&#xff08;想一想&#xff0c;我们不可能每打一个电话&#xff0c;就去买一部手…

Unity编辑器扩展-第三集-添加按钮到组件菜单并且重置组件

第二集链接&#xff1a;Unity编辑器扩展-第二集-按钮排序/分组/放入右键菜单_菌菌巧乐兹的博客-CSDN博客 一、本节目标效果展示 1.把按钮放到组件菜单上 2.做一个类似Reset功能&#xff0c;点一下能改变里面的数据 二、 把按钮放到组件菜单上 如上图&#xff0c;我的的组件名…

echarts 配置相关

echarts更多模板链接 http://chart.majh.top/ 1、echarts.clear()是清空当前实例&#xff0c;会移除实例中所有的组件和图表。 echarts.dispose()是销毁实例&#xff0c;销毁后实例无法再被使用。 this.chart.dispose() this.chart.clear(); // 清空图表2、series虽然是[] 数…

BRC20赛道的刚需基础设施,BrccSwap如何延续新的造富神话?

引言 BRC20代币和去中心化交易所的背景 BRC20代币赛道的刚需SWAP BrccSwap如何延续新的造富神话 结语 引言 随着加密货币市场的不断发展&#xff0c;BRC20代币和去中心化交易所成为了越来越受欢迎的概念。BRC20代币是建立在比特币区块链上的代币&#xff0c;具有高级别的…