Cloudflare、滑块、JS盾:我用 Python 是怎么一步步绕过它们的?
序章:遭遇“三重门”
最近,我盯上了一个数据网站。本以为是个轻松的活儿,没想到一头撞上了反爬界的“终极Boss”。它部署了堪称“三重门”的防御体系:
- 第一道门: Cloudflare的“五秒盾”,一个强制的JS挑战页面。
- 第二道门: 登录页的滑块验证码,需要精确操作。
- 第三道门: 隐藏在风平浪静之下的浏览器指纹检测,无声无息地将你拒之门外。
普通的爬虫脚本在它面前,存活不超过三秒。这反而激起了我的好胜心,我决定用我最熟悉的Python武器库,和它来一场堂堂正正的较量。
第一关:Cloudflare的“五秒盾” (JS Challenge)
我的第一次尝试,自然是requests
库,简单直接。结果毫不意外,返回的HTML内容是“Checking your browser before accessing…”,我的程序被永远地挡在了门外。
失败原因: 这个页面需要浏览器在5秒内执行一段复杂的JavaScript代码,计算出一个“答案”并提交,以证明自己是个真实的浏览器。requests
只是一个HTTP客户端,它不会执行任何JS。
破局之法:请出“真实浏览器”Playwright。
这道门的“钥匙”就是JS执行能力。Playwright驱动的是一个真实的、完整的浏览器内核(如Chromium),它能完美地执行页面上的任何JS代码。因此,破解这道门,甚至不需要任何花哨的操作。
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False) # 方便观察,先开启有头模式
page = browser.new_page()
# 直接访问,Playwright会自动处理JS挑战和跳转
page.goto('https://the-target-website.com')
# 等待登录框出现,证明我们已成功进入内页
page.wait_for_selector('#username')
print("成功突破第一道门:Cloudflare JS盾!")
# ... 暂停一下,手动关闭浏览器
page.pause()
运行脚本,我看到浏览器自动打开,显示了5秒的加载动画,然后顺利跳转到了登录页。第一关,轻松通过。
第二关:登录页的“拦路虎” (滑块验证码)
登录页上,一个滑块验证码赫然出现。这需要精确的图像识别和鼠标操作。
策略: 我决定再次祭出我的老朋友OpenCV
。
- 截图: 用Playwright对带缺口的背景图和滑块小图分别截图。
- 计算: 用OpenCV的模板匹配算法,精确计算出滑块需要移动的像素距离。
- 模拟: 生成一段“先快后慢,略带抖动”的人性化鼠标移动轨迹。
# (承接上文,假设page对象已存在)
# ... 此处省略了截图和用OpenCV计算距离的代码 ...
# distance = find_gap_position('background.png', 'slider.png')
# track = generate_mouse_trajectory(distance)
# 定位到滑块按钮
slider_button = page.locator('.slider-captcha-handle')
box = slider_button.bounding_box()
# 模拟鼠标拖拽
page.mouse.move(box['x'] + box['width'] / 2, box['y'] + box['height'] / 2)
page.mouse.down()
# 沿轨迹移动
for x, y in track:
page.mouse.move(box['x'] + x, box['y'] + y)
page.mouse.up()
print("成功突破第二道门:滑块验证码!")
我将图像处理和轨迹生成的代码封装成函数,然后在主流程中调用。看着脚本控制着鼠标,以一种略显笨拙但极其逼真的方式将滑块拖到了正确位置,我知道,第二关也过了。
第三关:无形的“暗哨” (浏览器指纹)
我满怀信心地填入用户名和密码,点击登录。然而,最诡异的事情发生了:页面刷新后,提示“验证失败”,或者干脆跳回了登录页。反复尝试,皆是如此。
诊断分析: 我意识到,我遇到了最难缠的对手——浏览器指纹检测。虽然我通过了表面的验证,但我的“DNA”暴露了我的身份。网站在后台悄悄执行JS,检测到了navigator.webdriver
这个在自动化浏览器中为true
的致命标志,以及其他几十个能够标识我为“机器人”的特征。
终极武器:“隐身衣”stealth.min.js
要对抗指纹检测,就必须在网站的JS执行之前,把我的浏览器环境伪装得天衣无缝。puppeteer-extra-plugin-stealth
项目就是为此而生的神器,它的核心stealth.min.js
文件,集成了大量反-反爬虫的技巧。
我下载了这个JS文件,并用Playwright的add_init_script
方法,在页面加载前就将其注入。
# (在创建page对象后,goto之前)
with open('stealth.min.js', 'r') as f:
stealth_script = f.read()
page.add_init_script(stealth_script)
这行代码的意义非凡:它相当于在网站的“安检员”上班之前,就给我的爬虫穿上了一件完美的“隐身衣”,抹去了所有自动化的痕迹。
收官之战:最后的拼图
临门一脚:换上“平民”IP。
我意识到,即使我的浏览器伪装得再好,如果我的IP地址来自一个云服务器(如AWS、阿里云),Cloudflare的IP黑名单数据库也会将我拒之门外。于是,我配置了一个高质量的住宅代理,让我的爬虫看起来就像一个普通的家庭上网用户。
最终的完整脚本,融合了所有智慧:
# final_script.py
from playwright.sync_api import sync_playwright
# ... 导入其他必要的库和函数 ...
with sync_playwright() as p:
# 配置住宅代理
proxy_server = {
"server": "http://<YOUR_RESIDENTIAL_PROXY_ADDRESS>"
}
browser = p.chromium.launch(headless=True, proxy=proxy_server)
page = browser.new_page()
# 1. 穿上“隐身衣”
with open('stealth.min.js', 'r') as f:
page.add_init_script(f.read())
# 2. 访问网站,自动通过JS盾
page.goto('https://the-target-website.com')
print("第一关突破!")
# 3. 解决滑块
# ... (截图、计算、拖拽代码) ...
print("第二关突破!")
# 4. 登录
page.fill('#username', 'my_user')
page.fill('#password', 'my_pass')
page.click('#login-button')
# 5. 验证登录成功
page.wait_for_selector('.user-dashboard')
print("第三关突破!登录成功,可以开始采集数据了!")
# ... 你的数据采集逻辑 ...
browser.close()
当我运行这个最终版的脚本时,一切都如行云流水般顺畅。三重门被依次攻破,我成功登录并看到了后台的数据。那一刻,成就感无与伦比。
结语:这是一场“层层深入”的博弈
这次经历让我深刻地理解到,现代反爬不再是单一技术的对抗,而是一场关于代理质量
、浏览器环境
和用户行为
三位一体的、层层深入的博弈。只有像剥洋葱一样,耐心、细致地分析并破解每一层防御,才能最终抵达数据的核心。
Comments
Post a Comment