尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Python Selenium绕过Cloudflare人机验证:从指纹伪装到行为模拟的实战指南

Python Selenium绕过Cloudflare人机验证:从指纹伪装到行为模拟的实战指南 1. 项目概述当自动化脚本遭遇“人机验证”高墙如果你用Python的Selenium库写过网页自动化脚本尤其是数据采集类的大概率见过这个熟悉的页面“请确认你是不是机器人”或者更直白地告诉你“正在验证浏览器环境”。这背后站着的往往是Cloudflare这样的安全服务。它像一道智能闸门专门拦截那些行为像机器人的访问请求保护网站免受恶意爬虫和自动化攻击的侵扰。对于我们这些只是想合法、合规地自动化一些网页操作比如监控价格、聚合信息、测试功能的开发者来说这道墙就成了一个必须面对的技术挑战。这个项目的核心就是探讨如何让我们的Selenium自动化脚本在Cloudflare的“法眼”下表现得更像一个真实的人类用户从而顺利通过验证访问到目标页面。这绝不是教大家去攻击或破坏网站安全而是在理解和尊重安全机制的前提下寻找合法自动化操作的可行路径。我经历过无数次脚本在验证页面“卡死”浏览器窗口里那个旋转的圆圈仿佛是对自动化努力的无声嘲讽。经过大量实战和踩坑我总结出了一套组合策略其有效性取决于Cloudflare防护的严格等级从简单的“5秒盾”到复杂的浏览器指纹验证。下面我就把这些经验、原理和具体代码毫无保留地分享出来。2. 核心思路从“伪装”到“协作”的进阶策略面对Cloudflare验证最天真的想法可能就是“找个漏洞绕过”。但Cloudflare的防护是动态、多层且不断更新的不存在一劳永逸的“银弹”。我们的策略应该是一个从易到难、层层递进的工具箱。核心思路可以概括为降低自动化特征模拟人类行为并在必要时寻求更底层的协作方式。2.1 策略一基础伪装与参数调优这是第一道防线目的是让Selenium驱动的浏览器看起来不那么“标准”。Cloudflare会检测大量浏览器指纹比如WebDriver属性、浏览器语言、屏幕分辨率、插件列表等。通过Selenium的Options我们可以修改这些参数。2.2 策略二行为模式模拟即使浏览器指纹伪装好了如果你的脚本打开网页就立刻疯狂点击或抓取也会被识别。模拟人类的浏览行为——如随机延迟、鼠标移动轨迹、滚动页面——至关重要。2.3 策略三使用第三方反反爬服务当网站防护等级较高时前两种策略可能失效。这时可以考虑借助专业服务如undetected-chromedriver或selenium-stealth库它们集成了更多高级的隐藏技巧。2.4 策略四终极方案——直接调用已认证的会话如果目标只是获取数据且网站有API这无疑是最佳选择。如果没有另一种思路是手动在浏览器中登录并通过验证然后将完整的Cookies和会话信息如User-Agent提供给Selenium脚本使用。这相当于让脚本“继承”一个已经通过验证的人类会话。在本项目中我们将重点深入策略一、二和三因为它们是编程解决的核心。策略四虽然高效但更偏向于流程技巧。3. 环境准备与核心工具解析工欲善其事必先利其器。我们的战场是Python 3.7核心武器是Selenium。但要想打好这场“伪装战”还需要一些特别的装备。3.1 基础环境搭建首先确保安装了Python和pip。然后安装Selenium库pip install selenium接下来你需要一个浏览器驱动。以Chrome为例你需要下载与本地Chrome浏览器版本匹配的chromedriver。将其放在系统PATH路径下或者直接在代码中指定路径。版本不匹配是新手最常见的错误之一。3.2 关键工具undetected-chromedriver这是一个社区维护的、专门用于对抗Cloudflare和类似检测的强化版Chrome驱动。它自动处理了许多指纹隐藏问题是当前相对最有效的方案之一。pip install undetected-chromedriver它的核心优势在于它修补了原生ChromeDriver中容易被检测到的cdc_等关键属性并且可以更好地集成代理等设置。在后面的实战中我们将以它为主要工具。3.3 可选工具selenium-stealth这是另一个流行的隐身库可以进一步添加各种反检测指纹。pip install selenium-stealth它通常与标准Selenium配合使用通过执行一段JavaScript代码来修改浏览器环境。我们可以将其作为undetected-chromedriver的补充。3.4 辅助工具代理IP池对于高频访问即使通过了人机验证单一IP的频繁请求也可能被限制。准备一个可靠的代理IP池注意需使用支持HTTPS的代理是生产级爬虫的必备。这不仅能分散请求有时也能帮助绕过基于IP的初步风控。注意请务必从合法渠道获取代理服务并遵守目标网站的robots.txt协议。我们的所有技术讨论均基于合规、节制的自动化访问前提。4. 实战代码构建你的“隐形”浏览器理论说再多不如一行代码。让我们从最简单的Selenium脚本开始一步步将它武装起来使其能够应对更严格的Cloudflare检查。4.1 基础版Selenium脚本极易被拦截这是一个最原始的脚本几乎100%会触发Cloudflare验证from selenium import webdriver import time driver webdriver.Chrome() driver.get(https://目标网站.com) time.sleep(5) print(driver.title) driver.quit()这个脚本的问题在于它使用的webdriver.Chrome()实例带有明显的自动化标签Cloudflare可以轻易通过检测navigator.webdriver属性为true来识别它。4.2 进阶版使用undetected-chromedriver与基础伪装现在我们引入undetected-chromedriver并进行一些基础配置import undetected_chromedriver as uc import time from selenium.webdriver.common.by import By def create_stealth_driver(): options uc.ChromeOptions() # 1. 禁用自动化控制标志重要 options.add_argument(--disable-blink-featuresAutomationControlled) # 2. 设置常规的用户代理可以轮换多个 options.add_argument(--user-agentMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36) # 3. 禁用GPU加速某些环境下可减少特征 # options.add_argument(--disable-gpu) # 4. 以非沙盒模式运行某些Linux环境需要 # options.add_argument(--no-sandbox) # 5. 禁用DevShmUsage避免共享内存问题 # options.add_argument(--disable-dev-shm-usage) # 使用undetected_chromedriver启动它会自动尝试匹配Chrome版本 driver uc.Chrome(optionsoptions) # 执行额外的JS脚本清除webdriver痕迹uc已内置此为双重保险 driver.execute_script(Object.defineProperty(navigator, webdriver, {get: () undefined})) return driver driver create_stealth_driver() try: driver.get(https://nowsecure.nl) # 这是一个著名的反爬虫测试网站 time.sleep(10) # 等待可能的验证页面加载和自动处理 # 检查是否成功跳过了验证进入了真实页面 if NowSecure in driver.title: print(成功绕过基础验证) # 这里可以开始你的自动化操作例如查找元素 # element driver.find_element(By.TAG_NAME, body) # print(element.text[:500]) else: print(可能仍处于验证页面需要进一步处理。) # 可以截图查看当前状态 driver.save_screenshot(cf_challenge.png) finally: driver.quit()这个版本已经能应对许多中等强度的“5秒盾”。undetected_chromedriver在启动时做了大量隐藏工作。我们添加的--disable-blink-featuresAutomationControlled参数和手动执行的JS脚本是为了进一步清除痕迹。4.3 强化版集成selenium-stealth与行为模拟对于更顽固的网站我们可以结合selenium-stealth和人类行为模拟。import undetected_chromedriver as uc from selenium_stealth import stealth import time import random from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.by import By def create_ultimate_stealth_driver(use_proxyFalse, proxy_urlNone): options uc.ChromeOptions() # 基础伪装参数 options.add_argument(--disable-blink-featuresAutomationControlled) options.add_argument(--user-agentMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36) options.add_argument(--window-size1920,1080) # 设置一个常见的窗口大小 # 可选添加代理 if use_proxy and proxy_url: options.add_argument(f--proxy-server{proxy_url}) # 启动浏览器可以设置headless模式但无头模式更容易被检测 # options.add_argument(--headlessnew) # 谨慎使用无头模式 driver uc.Chrome(optionsoptions) # 应用selenium-stealth的强化隐身 stealth(driver, languages[en-US, en], vendorGoogle Inc., platformWin32, webgl_vendorIntel Inc., rendererIntel Iris OpenGL Engine, fix_hairlineTrue, ) return driver def human_like_mouse_move(driver, elementNone): 模拟人类鼠标移动轨迹 action ActionChains(driver) if element: # 移动到某个元素 action.move_to_element(element) else: # 在页面内随机移动 width driver.execute_script(return document.documentElement.scrollWidth) height driver.execute_script(return document.documentElement.scrollHeight) target_x random.randint(0, width // 2) target_y random.randint(0, height // 2) action.move_by_offset(target_x, target_y) action.perform() time.sleep(random.uniform(0.5, 2.0)) # 随机停顿 def human_like_scroll(driver): 模拟人类滚动页面 scroll_height driver.execute_script(return document.body.scrollHeight) current_scroll 0 scroll_step random.randint(200, 500) while current_scroll scroll_height: driver.execute_script(fwindow.scrollTo(0, {current_scroll});) current_scroll scroll_step time.sleep(random.uniform(0.8, 2.5)) # 滚动后随机等待 # 偶尔进行小幅度回滚更像人类 if random.random() 0.7: driver.execute_script(fwindow.scrollBy(0, {-random.randint(50,150)});) time.sleep(random.uniform(0.3, 1.0)) # 使用强化版驱动 driver create_ultimate_stealth_driver() try: url https://目标网站.com driver.get(url) # 关键增加首次加载后的随机等待让验证有足够时间自动处理或手动观察 initial_wait random.uniform(8, 15) print(f初始等待 {initial_wait:.2f} 秒用于加载和潜在验证...) time.sleep(initial_wait) # 检查页面标题或特定元素判断是否还在验证页 page_title driver.title page_source driver.page_source if challenge in page_source.lower() or cloudflare in page_source.lower() or just a moment in page_title.lower(): print(检测到可能仍在验证页面。尝试行为模拟...) # 模拟人类鼠标移动 human_like_mouse_move(driver) # 模拟人类滚动 human_like_scroll(driver) # 再次等待 time.sleep(random.uniform(5, 10)) # 再次检查 if challenge not in driver.page_source.lower(): print(行为模拟后可能已通过验证。) else: print(验证可能较复杂需要考虑其他策略如Cookies注入或手动干预。) driver.save_screenshot(still_on_challenge.png) else: print(f似乎已成功访问目标页面。标题: {page_title}) # 成功后的操作也应加入人类行为模拟 human_like_scroll(driver) # ... 执行你的数据抓取或自动化任务 ... finally: driver.quit()这个版本集成了高级隐身库和行为模拟。selenium_stealth修改了更多的浏览器指纹如navigator.plugins,navigator.languages, WebGL渲染器等。而human_like_mouse_move和human_like_scroll函数则让脚本的操作模式脱离了机械的节奏。5. 高级策略与疑难问题排查即使使用了上述所有方法某些高度防护的网站如使用Cloudflare高级版或Turnstile验证的站点可能仍然无法自动绕过。这时我们需要更深入的策略和排查手段。5.1 策略Cookies与会话复用这是绕过复杂验证的“捷径”。思路是手动完成一次验证然后将浏览器的Cookies导出供自动化脚本使用。使用我们配置好的“隐形”浏览器手动访问目标网站。如果出现验证手动完成它如点击复选框、识别图像等直到进入目标页面。在浏览器控制台F12执行document.cookie获取Cookies字符串或使用Selenium的driver.get_cookies()方法获取Cookies列表。将获取的Cookies保存到文件如JSON。在自动化脚本启动浏览器后先加载目标网站域名可能是一个空白页或验证页然后通过driver.add_cookie()方法添加所有保存的Cookies。再次导航到目标网址。由于会话已认证通常可以直接跳过验证。代码示例Cookies加载部分import json import undetected_chromedriver as uc def load_cookies_from_file(driver, filepath, domain): 从文件加载Cookies到当前浏览器会话 driver.get(fhttps://{domain}) # 先导航到该域名以设置Cookie的上下文 time.sleep(2) with open(filepath, r) as f: cookies json.load(f) for cookie in cookies: # 确保cookie有必要的字段如‘name’和‘value’并处理可能的‘expiry’类型问题 if expiry in cookie: # Selenium期望expiry是整数 cookie[expiry] int(cookie[expiry]) try: driver.add_cookie(cookie) except Exception as e: print(f添加Cookie {cookie.get(name)} 时出错: {e}) print(Cookies加载完毕。) driver.refresh() # 刷新页面使Cookies生效 time.sleep(3) # 使用 driver uc.Chrome() try: # 先加载Cookies load_cookies_from_file(driver, my_saved_cookies.json, 目标网站.com) # 再访问需要认证的页面 driver.get(https://目标网站.com/受保护页面) time.sleep(5) # ... 检查是否成功 ... finally: driver.quit()实操心得Cookies有生命周期会话Cookie或持久Cookie。手动获取的Cookies可能会过期需要定期更新。此外某些网站会将Cookies与IP地址或浏览器指纹绑定更换IP或浏览器环境后可能失效。5.2 策略处理JavaScript挑战有时Cloudflare会返回一个JavaScript计算挑战要求浏览器执行一段JS并返回结果才能继续。undetected-chromedriver通常能自动处理这类简单挑战。但如果遇到问题可以尝试手动提取并执行。在验证页面通过driver.page_source查找包含计算逻辑的JS代码可能隐藏在script标签或表单值中。使用Python的execjs或js2py库来执行这段JS计算出答案。将答案通过Selenium提交到相应的表单或URL。这个过程比较繁琐需要针对特定网站进行逆向工程通用性不强。5.3 常见问题排查清单当你的脚本仍然失败时请按以下步骤排查问题现象可能原因排查与解决思路直接显示“禁止访问”或“拒绝连接”IP地址被拉黑、请求频率过高、基础指纹暴露明显。1. 更换代理IP。2. 大幅降低请求频率增加随机延迟。3. 检查user-agent是否有效尝试更换。4. 确保使用了undetected-chromedriver并正确配置了Options。一直停留在“正在验证”或“旋转”页面浏览器指纹未能完全隐藏触发了需要用户交互的挑战如点击。1. 使用driver.save_screenshot()截图确认页面状态。2. 检查控制台driver.get_log(browser)是否有JS错误或警告。3. 尝试添加selenium-stealth进行深度伪装。4. 尝试在代码中模拟点击验证按钮需定位元素。5. 考虑是否必须手动解决一次然后复用Cookies。成功通过验证但很快又被阻断行为模式异常如速度太快、模式固定、同一会话请求过多。1. 在所有操作点击、翻页、滚动中加入随机延迟。2. 模拟更复杂的人类鼠标轨迹。3. 在不同任务之间切换不同的用户代理如果可行。4. 使用多个浏览器实例或会话轮换操作。undetected-chromedriver启动报错Chrome浏览器版本与驱动不匹配、端口冲突、权限问题。1. 确保已安装最新Chrome。2. 尝试指定Chrome二进制路径uc.Chrome(browser_executable_path/path/to/chrome)。3. 关闭所有Chrome进程再试。4. 查看库的GitHub Issues寻找类似问题。无头模式Headless下失败率极高无头模式具有更多可检测特征是Cloudflare的重点监控对象。最直接的方案避免在生产中长时间使用纯无头模式。可以尝试1. 使用uc.Chrome(headlessTrue)它进行了一些优化。2. 使用“虚拟显示”工具如Xvfb on Linux运行非无头浏览器使其“认为”有显示界面。5.4 终极考量道德、法律与效率在投入大量精力研究绕过技术之前务必思考合规性你的自动化行为是否违反了网站的robots.txt协议或服务条款是否对网站服务器造成了不当压力法律风险在某些司法管辖区绕过技术保护措施可能涉及法律问题。效率成本与网站提供的官方API相比维护一个脆弱的、需要不断对抗更新的爬虫其长期成本可能更高。始终优先寻找和利用官方接口。尊重与沟通如果是为了合法、合理的目的如学术研究、个人数据备份有时直接联系网站所有者说明情况并请求数据接口或豁免可能是最有效、最体面的方式。6. 一个完整的实战案例流程假设我们需要从某个受Cloudflare保护的电商网站example-shop.com上每日监控特定商品的价格变化。我们将整合上述所有策略构建一个健壮的监控脚本。步骤1环境侦察与手动测试手动访问example-shop.com/product/123观察是否出现验证以及验证的类型是简单的5秒等待还是需要点击的挑战。打开浏览器开发者工具F12在“网络”(Network)选项卡中观察页面加载过程中的请求特别是验证通过后对真实页面的请求有何特征。步骤2基础脚本开发与Cookies获取编写一个使用undetected-chromedriver和selenium-stealth的脚本。首次运行可能会遇到验证。手动完成这次验证。验证通过后在脚本中调用driver.get_cookies()并将Cookies以JSON格式保存到本地文件cf_cookies.json。同时记录下当前的user-agent。步骤3生产脚本编写集成Cookies加载与行为模拟import undetected_chromedriver as uc from selenium_stealth import stealth import time import random import json from selenium.webdriver.common.by import By class ProductMonitor: def __init__(self, cookie_filecf_cookies.json): self.cookie_file cookie_file self.driver self._create_driver() def _create_driver(self): options uc.ChromeOptions() options.add_argument(--disable-blink-featuresAutomationControlled) # 使用之前手动获取的User-Agent options.add_argument(--user-agentMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...) options.add_argument(--window-size1380,900) driver uc.Chrome(optionsoptions) stealth(driver, languages[en-US, en], vendorGoogle Inc., platformWin32, fix_hairlineTrue, ) return driver def load_cookies(self, domain): 加载Cookies到浏览器 self.driver.get(fhttps://{domain}) time.sleep(random.uniform(2,4)) try: with open(self.cookie_file, r) as f: cookies json.load(f) for cookie in cookies: self.driver.add_cookie(cookie) print(f已从 {self.cookie_file} 加载 {len(cookies)} 个Cookies.) self.driver.refresh() time.sleep(random.uniform(3,6)) except FileNotFoundError: print(未找到Cookie文件将以全新会话启动。) except Exception as e: print(f加载Cookies时发生错误: {e}) def check_price(self, product_url): 访问商品页面并提取价格 self.driver.get(product_url) # 随机等待模拟人类阅读时间 time.sleep(random.uniform(5, 10)) # 检查是否还在挑战页面 if challenge in self.driver.page_source.lower(): print(检测到验证挑战尝试行为模拟...) self._simulate_human_behavior() time.sleep(8) # 如果还在挑战页本次任务失败可能需要更新Cookies if challenge in self.driver.page_source.lower(): print(无法通过验证请手动更新Cookie文件。) return None # 尝试定位价格元素需要根据实际网站HTML调整 try: # 示例选择器需根据实际情况修改 price_element self.driver.find_element(By.CSS_SELECTOR, .product-price .current) price_text price_element.text.strip() print(f成功获取价格: {price_text}) return price_text except Exception as e: print(f提取价格时出错: {e}) # 可以截图用于调试 self.driver.save_screenshot(ferror_{int(time.time())}.png) return None def _simulate_human_behavior(self): 模拟人类滚动和轻微移动 scroll_pixels random.randint(300, 800) self.driver.execute_script(fwindow.scrollBy(0, {scroll_pixels});) time.sleep(random.uniform(1.5, 3)) # 可能的小幅度回滚 if random.random() 0.5: self.driver.execute_script(window.scrollBy(0, -100);) time.sleep(random.uniform(0.5, 1.5)) def run(self, product_url): self.load_cookies(example-shop.com) price self.check_price(product_url) return price def close(self): self.driver.quit() # 使用示例 if __name__ __main__: monitor ProductMonitor() try: current_price monitor.run(https://example-shop.com/product/123) if current_price: # 这里可以添加逻辑与之前价格比较发送通知等 print(f当前监控价格: {current_price}) finally: monitor.close() print(监控任务结束。)步骤4部署与维护将脚本部署到服务器使用cron或systemd timer定时运行例如每6小时一次。设置一个监控机制如果脚本连续多次失败返回None则通过邮件或短信告警提示可能需要手动更新Cookies。定期如每周手动运行一次脚本确保Cookies未过期如果过期则重新手动获取并更新cf_cookies.json文件。这个案例展示了一个相对完整、健壮的工作流。它结合了技术手段高级驱动、行为模拟和流程技巧Cookies复用在自动化与反自动化之间找到了一个可持续的平衡点。记住与Cloudflare的对抗是一场“军备竞赛”没有永恒的胜利只有持续的适应和调整。保持对目标网站变化的关注并随时准备更新你的策略是长期成功的关键。
返回列表