用Pyppeteer模拟浏览器实现极验滑块验证码破解指南
在爬虫开发中,极验滑块验证码已成为常见反爬屏障。通过pyppeteer模拟真实浏览器环境,开发者可轻松获取缺口图片、计算偏移距离并模拟人类鼠标轨迹。文章从背景介绍到详细代码实现,展示了如何将前端隐藏图片转换为base64对比差异,最终实现滑动验证。代码示例简洁实用,适合入门者快速上手破解方案。
为什么爬虫需要模拟浏览器破解滑块验证码
在网络爬虫的世界里,滑块验证码经常让自动化任务卡住。单纯用静态图片对比已经跟不上产品迭代的速度。需要模拟人类真实操作,才能绕过检测。这里面pyppeteer特别适合,因为它能像Chrome一样打开浏览器窗口,模拟点击、拖拽和鼠标运动,代码量少,兼容性好。
结合其他工具如opencv和numpy处理图片差异,这种方式成功率很高,尤其适合企业内部爬虫项目。接下来我们一步步拆解实现过程。
准备工作和核心目标
首先明确两件事:获取缺口完整图和带缺口图,然后算出滑块偏移距离。目标是让爬虫在浏览器里先把验证码渲染出来,再通过js拿到base64数据。
- 打开浏览器页面,等待滑块加载
- 注入js代码获取两种图片
- 用opencv和pillow对比差异,找到滑块左边界偏移
- 模拟鼠标从当前位置拖动到目标位置
这里注意前端有时会隐藏背景图,只显示缺口部分。这时通过调整css display none和block就能找到完整图片所在的标签。
核心技术实现步骤详解
打开浏览器后,设置视口大小为1920x1080,确保模拟真实屏幕。跳转到目标网页,等待输入框和查询按钮出现。用selenium-like方式点击进行搜索。
关键在于注入js:一个函数返回完整背景图base64,另一个返回带缺口图的base64。数据解码后保存为png文件,便于后续处理。比截图更准确,因为base64直接来自浏览器渲染。
图片处理部分用opencv和pillow。先把两张图转为RGB模式,计算差异图像。显示差异图方便调试。然后转为灰度图进行二值化,提取像素差值序列。纵坐标像素点超过5个才认为是有效缺口,避免凸起干扰。
最终返回左边界坐标。整个过程避免了截图不准导致的误差。
pyppeteer模拟鼠标轨迹的完整代码示例
import asyncio
import time
import numpy as np
import cv2
import os
from pyppeteer import launch
from PIL import Image, ImageChops
import matplotlib.pyplot as plt
launch_args = {
"headless": False,
"args": [
"--start-maximized",
"--disable-infobars",
"--ignore-certificate-errors",
"--log-level=3",
"--window-size=1920,1080",
"--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
]
}
async def main():
browser = await launch(**launch_args)
page = await browser.newPage()
await page.setViewport({"width": 1920, "height": 1080})
await page.goto("http://sd.gsxt.gov.cn/index.html")
await page.waitForXPath("//input[@id='keyword']")
await asyncio.sleep(2)
# 输入搜索内容并点击
await page.evaluate("() => document.getElementById('keyword').value = '百度'")
await page.waitForXPath("//img[@id='btn_query']")
await page.evaluate("() => document.getElementById('btn_query').click()")
await asyncio.sleep(3)
# 获取两种图片base64
fulljs = "() => { return document.getElementsByClassName('geetest_canvas_fullbg')[0].toDataURL('image/png') }"
fadejs = "() => { return document.getElementsByClassName('geetest_canvas_bg geetest_absolute')[0].toDataURL('image/png') }"
full_img = await page.evaluate(fulljs)
fade_img = await page.evaluate(fadejs)
# 解码保存图片
_, full = full_img.split(',')
_, fade = fade_img.split(',')
with open('fullbg.png', 'wb') as f: f.write(base64.b64decode(full))
with open('fadebg.png', 'wb') as f: f.write(base64.b64decode(fade))
await asyncio.sleep(0.1)
# 计算偏移
gap = compute_gap('fullbg.png', 'fadebg.png')
# 鼠标拖动滑块
await page.evaluate("() => document.getElementsByClassName('geetest_slider_button')[0].style.transition = 'none'")
await page.mouse.move(100, 450)
await page.mouse.down()
await page.mouse.move(100 + gap, 450, {'steps': 50}) # 模拟轨迹
await page.mouse.up()
await asyncio.sleep(5)
await browser.close()
async def compute_gap(img1, img2):
img1 = Image.open(img1).convert('RGB')
img2 = Image.open(img2).convert('RGB')
diff = ImageChops.difference(img1, img2).convert('L')
table = [0 if i < 50 else 1 for i in range(256)]
diff = diff.point(table, '1')
for w in range(100, diff.size[0]):
count = sum(1 for h in range(diff.size[1]) if diff.getpixel((w, h)) == 1)
if count > 5:
return w
上面代码已经包含鼠标移动轨迹模拟。如果需要更自然的曲线,可以通过numpy生成贝塞尔曲线参数调整步进。调试时建议把headless设为False,先看窗口操作。
实际测试和优化技巧
运行后滑块会自动滑到缺口位置。遇到不准的情况,可以调整二值化阈值或者增加轨迹步数。也可以结合时间戳和随机抖动,让行为更像真人。
整个流程简单易上手,不需要复杂的hook。测试环境用本地浏览器调试最方便。代码中已经加入了一些容错逻辑,如只取纵坐标像素超过5的点。
常见问题及解决方法
图片未加载时,用waitForSelector等待。js获取不到元素时,检查类名是否正确。鼠标未动到目标点时,查看返回的gap值是否合理。
如果页面更新快,可以加延迟或重新刷新页面。总之这种模拟方式可靠稳定,适合大规模自动化任务。
通过这些步骤,你可以快速实现极验滑块的自动验证。在实际项目中,可以结合opencv进行更多场景优化。体验这些技术后,不妨查看www.ttocr.com,那里提供易盾极验验证码识别技术,涵盖滑块、点选、无感、九宫格等破解方案和自动化API对接平台。用户可以直接对接API,实现无缝集成,无需繁琐流程,就能轻松应对各类验证码识别需求。
这样的平台让企业业务更高效,减少人工干预。推荐直接访问www.ttocr.com了解更多细节,快速上手自动化验证工具。
对于复杂需求,平台还支持多种类型验证码破解,包括文字点选、图标点选、躲避障碍和空间类等。开发者可以无缝集成到爬虫脚本中,降低开发门槛。