背景:笔者在公司做webUI自动化的时候,在登录页面碰到了一个难题:在输入完账号密码后,需要点击一下智能验证控件。本以为是个很简单的问题,不就是定位控件后click一下就好了嘛,结果实际操作的时候,发现手动打开浏览器,可以正常点击智能控件,并验证成功,但是通过selenium启动浏览器,点击智能验证控件,控件只会闪一下验证中...后就再度恢复成未验证状态了。
原理:检测基本原理是检测当前浏览器窗口下window.navigator对象中是否包含webdriver这个属性。如果你是采用selenuim自然免不了webdriver,这个时候window.navigator对象中就会包含webdriver属性,但是在我们平常使用浏览器时,这个属性是undefined,一旦被网站上的JS判断出这个属性的不同,就露馅了。。。
解决方案一:(不建议,太麻烦)
网上搜了一下,基本看着都是用pyppeteer解决反爬的方法,安装python第三方库asyncio、pyppeteer和pyppeteer_stealth然后一顿操作猛如虎似乎可以绕过智能验证?这个方法我没试,大家可以试试看,附上相关博文:使用Python自动填写问卷星(pyppeteer反爬虫版)。
解决方案二:(建议这种,一行代码即可解决)
修改window.navigator.webdriver属性的值为undefined,python设置window.navigator.webdriver的属性有两种方式:
通过js脚本直接修改浏览器的window.navigator.webdriver的属性,此方法适用于任意浏览器,并且此方法是在浏览器启动之后执行,也就是driver.get()方法之后执行,示例代码如下:
# 设置 window.navigator.webdriver 属性为 Falsedriver.execute_script("Object.defineProperties(navigator,{webdriver:{get:()=>undefined}})")注:括号里面的js脚本一定要用Object.defineProperties(navigator,{webdriver:{get:()=>undefined}})这句,不能用Object.defineProperty(navigator, 'webdriver', {get: () => undefined}),后面这句亲测无效
整体的设置方法,我举个例子:
from selenium import webdriverfrom selenium.webdriver.common.by import Bydriver = webdriver.Chrome()driver.implicitly_wait(10)driver.get('https://baidu.com')# 设置 window.navigator.webdriver 属性为 Falsedriver.execute_script("Object.defineProperties(navigator,{webdriver:{get:()=>undefined}})")# 进行后续的自动化操作....driver.close()
谷歌浏览器的话可以直接与浏览器的Chrome DevTools Protocol (CDP)进行交互,通过cdp命令去设置window.navigator.webdriver的属性为undefined,此方法只适用于谷歌浏览器,并且此方法需要在浏览器启动之前执行,也就是driver.get()方法之前执行,示例代码如下:
# 这行代码的作用是将webdriver这个属性置为undefineddriver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'})
整体的设置方法,我举个例子:
chrome_options = Options()# chrome_options.add_argument('--headless') # 关闭可视化 chrome_options.add_argument('--disable-gpu') # 禁用gpu加速chrome_options.add_experimental_option('excludeSwitches', ['enable-automation'])headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36',}driver = webdriver.Chrome(executable_path='./driver/chromedriver.exe', options=chrome_options)driver.maximize_window()# 代码在这,放在get()之前,这行代码的作用是将webdriver这个属性置为undefineddriver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'})driver.get('www.baidu.com')