1. 项目概述与核心价值
最近在搞一个自动化数据采集的项目,目标网站是欧模网。这个网站的设计师案例库和素材资源非常丰富,但想批量获取信息,第一步的登录就卡住了——它用的是那种经典的滑动拼图验证码。手动操作一两次还行,但要自动化批量处理,这玩意儿就是个拦路虎。相信很多做自动化测试、数据采集或者RPA开发的朋友都遇到过类似的问题,验证码识别,尤其是需要模拟人类行为的滑动验证码,一直是自动化流程中的一个痛点。
传统的解决方案,比如自己训练图像识别模型,对于个人开发者或小团队来说,成本太高,周期也长。而一些简单的图像处理库(如OpenCV)做模板匹配,对付简单的、背景固定的验证码还行,但像欧模网这种背景有干扰、拼图边缘有阴影和渐变的,成功率就直线下降,而且代码的维护成本也不低。所以,这次我选择了一条更“务实”的路线:Selenium + 图鉴平台。
简单来说,Selenium负责模拟浏览器操作,完成打开网页、输入账号密码、点击登录按钮等流程。而最核心的验证码识别与轨迹模拟部分,则交给专业的第三方打码平台“图鉴”来处理。我们只需要调用它的API,把验证码图片传过去,它就能返回拼图缺口的位置,我们再根据这个位置,用Selenium模拟出人类的滑动轨迹,完成验证。整个过程,从环境搭建到代码调试,我花了大概一个下午就搞定了,真正核心的验证码破解部分,代码不到50行。这篇文章,我就把这个实战过程完整地拆解一遍,附上可以直接运行的Python代码,目标是让你在5分钟内理解原理,并能够复现这个自动登录流程。
这套方案有几个明显的优势:一是快,不用自己研究复杂的图像算法;二是稳,专业平台的识别率高,应对各种干扰的能力强;三是省心,API调用简单,后续维护成本低,平台会持续更新算法对抗网站的反爬升级。无论是做自动化测试需要绕过登录,还是做数据采集需要保持会话,这个方法都提供了一个非常高效的思路。
2. 核心思路与技术选型解析
2.1 为什么是Selenium + 第三方平台?
在决定技术方案之前,我们先明确需求和面临的挑战。欧模网的滑动验证码属于行为式验证码,它不仅要验证“你是谁”(账号密码),还要验证“你是不是真人”。它通过要求用户完成一个滑动拼图的操作,来采集鼠标移动轨迹、加速度、停顿等行为特征,与机器生成的直线匀速运动进行对比。
如果完全自己从零实现,我们需要解决以下几个问题:
- 缺口定位:从背景图中精准定位拼图缺口的X坐标。这需要处理图片干扰、阴影、抗锯齿等。
- 轨迹模拟:生成一条足够“拟人”的移动轨迹,包括先加速后减速、小幅抖动等特征,以绕过行为检测。
- 环境对抗:Selenium驱动浏览器会有一些特征可以被前端JavaScript检测到(例如
navigator.webdriver属性)。虽然欧模网目前检测不严,但好的实践应该预先处理。
自己实现缺口定位,意味着要深入图像处理领域;自己模拟轨迹,需要大量测试来拟合参数。这对于一个以业务目标(登录后采集数据)为导向的项目来说,性价比太低。因此,引入专业的第三方打码平台成为最优解。平台负责解决最复杂的识别问题(缺口定位),我们则专注于更擅长的浏览器自动化(Selenium)和业务流程拼接。这是一种典型的分工协作思维,用专业服务解决专业问题。
2.2 图鉴平台的工作原理与接入成本
“图鉴”这类平台本质上是一个“识别即服务”(Recognition as a Service)的提供商。它们背后有庞大的标注数据和持续优化的识别模型(包括深度学习模型),专门对付各种验证码。对于滑动验证码,其工作流程对我们开发者来说是黑盒但接口透明:
- 我们通过API上传验证码背景图和拼图块图。
- 平台服务器运行识别算法,计算出拼图块需要滑动到的准确位置(通常是缺口左上角的X坐标)。
- 将坐标结果通过API返回给我们。
接入成本极低。以图鉴为例,注册后一般会赠送少量体验点数,足够测试和轻量使用。它的收费模式通常是按识别次数计费,对于滑动验证码,一次识别可能花费1-2分钱。对于企业级应用,这点成本相对于节省的人力和开发的稳定性来说,几乎可以忽略不计。更重要的是,它极大地降低了项目的技术风险和开发周期。
2.3 整体自动化登录流程设计
基于以上分析,我们设计出如下自动化登录流程,这是一个清晰的分阶段任务:
- 初始化阶段:启动Selenium WebDriver,打开欧模网登录页面。
- 信息填充阶段:自动输入用户名和密码。
- 验证码触发与获取阶段:点击登录按钮,触发验证码弹出。然后,分别截取验证码的背景大图和滑动拼图块的小图。
- 识别外包阶段:将两张图片上传至图鉴平台API,获取缺口位置的X坐标。
- 轨迹模拟与滑动阶段:根据获得的X坐标,计算需要滑动的总距离。然后,生成一条模拟人类行为的移动轨迹,并通过Selenium控制鼠标按住滑块,沿轨迹拖动。
- 结果验证与登录完成:释放鼠标,等待页面跳转,验证是否登录成功。
这个流程将复杂的识别问题隔离在了第4步,通过一个简单的HTTP请求解决,使得整个项目的复杂度和不确定性大大降低。
3. 环境准备与核心工具详解
3.1 Selenium环境搭建与避坑指南
Selenium是我们的自动化之手。首先确保你安装了Python,然后通过pip安装Selenium库:
pip install selenium接下来是关键的一步:下载浏览器驱动。Selenium需要通过一个驱动文件来与真实的浏览器(如Chrome)进行通信。这里以Chrome为例,也是最常用的。
第一步:查看Chrome浏览器版本。打开Chrome,在地址栏输入chrome://version/,找到“Google Chrome”后面的版本号(例如,120.0.6099.110)。
第二步:下载对应版本的ChromeDriver。前往ChromeDriver的官方下载站或国内镜像站。这里有一个巨坑:驱动版本必须与你的浏览器主版本号完全一致!比如你是Chrome 120,就必须下载ChromeDriver 120.x.x.x,版本号前三位必须匹配。下载后,你会得到一个可执行文件(Windows是chromedriver.exe,Mac/Linux是chromedriver)。
第三步:配置驱动路径。有三种常用方法:
- (推荐)加入系统PATH:将
chromedriver文件所在目录添加到系统的环境变量PATH中。这样在代码里可以直接初始化。 - 指定绝对路径:在代码中初始化时,通过
executable_path参数指定文件的完整路径。 - 放在Python脚本同级目录:最简单,但管理多个项目时可能混乱。
我个人的习惯是,在项目根目录下创建一个drivers文件夹,把驱动放进去,然后在代码里使用相对路径指定,这样项目迁移起来方便。
注意:很多新手在这里卡住,报错信息通常是
'chromedriver' executable needs to be in PATH。请反复检查版本是否匹配,以及路径是否正确。另一个常见问题是浏览器自动更新后驱动版本过旧,需要重新下载匹配的驱动。
3.2 图鉴平台注册与API密钥获取
接下来是“大脑”部分——图鉴平台。我们以图鉴平台为例(其他如超级鹰、打码兔等平台流程类似)。
- 注册账号:访问图鉴官网,用手机号注册一个账号。
- 登录并获取API Key:登录后,通常在“用户中心”或“开发文档”页面,你可以找到你的
username(用户名)和password(API密钥,一串由平台生成的字符)。这两个参数是调用API的凭证,务必妥善保管,不要泄露或上传到公开的代码仓库。 - 了解计费与类型码:在后台,你通常能看到剩余点数。同时,平台会为不同类型的验证码分配一个
type(类型码)。对于滑动验证码,图鉴平台常见的类型码是9101(具体以平台最新文档为准)。这个type参数在调用API时需要传入,告诉平台你要识别的是什么类型的验证码。 - 阅读API文档:找到平台的API接口文档,主要关注“滑动验证码识别”的接口地址、请求参数和返回格式。这能让你在写代码时心里有数。
3.3 辅助Python库安装
除了Selenium,我们还需要两个辅助库:
requests:用于向图鉴平台的API发送HTTP请求,传输图片。Pillow(PIL):一个强大的图像处理库,这里我们主要用它来打开和保存图片,有时也需要做简单的图像处理(如裁剪)。
pip install requests Pillow现在,环境就绪,我们可以开始进入核心的代码实战环节了。
4. 实战代码拆解:从打开网页到完成滑动
让我们一步步把流程变成代码。我会先给出完整的代码块,然后逐段进行详细解释,并穿插我踩过的坑和优化技巧。
4.1 初始化Selenium与登录页面操作
首先,导入必要的库,并初始化浏览器。
import time import requests from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains from PIL import Image import io # 1. 初始化浏览器驱动 # 假设chromedriver放在项目根目录的drivers文件夹下 driver_path = './drivers/chromedriver' # Windows用户改为 './drivers/chromedriver.exe' options = webdriver.ChromeOptions() # 可选:添加一些选项以更好地模拟真人浏览器,避免被简单检测 # options.add_argument('--disable-blink-features=AutomationControlled') # options.add_experimental_option("excludeSwitches", ["enable-automation"]) # options.add_experimental_option('useAutomationExtension', False) driver = webdriver.Chrome(executable_path=driver_path, options=options) # 设置一个隐式等待,让元素加载更稳定 driver.implicitly_wait(10) # 2. 打开欧模网登录页 login_url = 'https://www.om.cn/login' # 请以实际登录页URL为准 driver.get(login_url) time.sleep(2) # 等待页面完全加载,可根据网络情况调整 # 3. 自动填充用户名和密码 username_input = driver.find_element(By.ID, 'username') # 根据实际页面元素ID修改 password_input = driver.find_element(By.ID, 'password') # 根据实际页面元素ID修改 your_username = 'your_username_here' your_password = 'your_password_here' username_input.send_keys(your_username) time.sleep(0.5) # 模拟人工输入间隔 password_input.send_keys(your_password) time.sleep(1)代码解读与注意事项:
- 驱动路径:
executable_path参数在较新版本的Selenium中已被弃用,建议将驱动所在目录加入系统PATH,然后直接webdriver.Chrome(options=options)。但为了清晰,这里仍展示了指定路径的方式。 - 浏览器选项:被注释掉的那几行
options配置,是用来隐藏Selenium自动化特征的,对于反爬严格的网站可能有用。欧模网目前不需要,但作为好习惯可以了解。 - 元素定位:
By.ID是最稳定快速的定位方式。你需要使用浏览器的开发者工具(F12),查看用户名和密码输入框的HTML代码,找到它们的id属性。如果页面没有ID,可以使用By.NAME,By.XPATH或By.CSS_SELECTOR。这是自动化脚本中最容易出问题的地方,因为网站前端可能改版。 - 等待策略:
implicitly_wait(10)是隐式等待,它会在查找元素时,如果没立刻找到,会轮询等待最多10秒。time.sleep(2)是强制等待,简单粗暴但有效。在关键操作后(如点击登录触发验证码)使用sleep是稳妥的做法。
4.2 触发验证码并获取图片元素
填充完信息后,点击登录按钮,验证码弹窗就会出现。
# 4. 点击登录按钮,触发验证码 login_button = driver.find_element(By.CLASS_NAME, 'login-btn') # 根据实际按钮的class修改 login_button.click() time.sleep(3) # 等待验证码图片加载完成,这个时间可以稍长一点 # 5. 定位验证码图片元素 # 通常滑动验证码由两张图组成:背景大图(带缺口)和滑块小图 # 你需要用开发者工具找到这两个图片元素的CSS选择器或XPath # 假设通过分析,我们找到了如下选择器: background_img_element = driver.find_element(By.CSS_SELECTOR, '.geetest_canvas_bg.geetest_absolute') # 背景图元素 slider_img_element = driver.find_element(By.CSS_SELECTOR, '.geetest_canvas_slice.geetest_absolute') # 滑块图元素 slider_button = driver.find_element(By.CSS_SELECTOR, '.geetest_slider_button') # 可拖动的滑块按钮重要提示:这是整个项目中最关键、最需要耐心的一步!欧模网或其他网站的前端代码千差万别,上面
By.CSS_SELECTOR里的内容只是示例,绝对不可以直接照抄。你必须自己打开浏览器的开发者工具(F12),切换到“元素”(Elements)面板,使用左上角的箭头工具,去点击页面上的验证码背景图和滑块图,从而在代码中找到它们对应的HTML元素。通常,这些图片可能是作为div的背景图(background-image),也可能是canvas画布元素。如果是canvas,我们无法直接获取图片URL,需要用到下面的截图方法。
4.3 截图、裁剪与图片预处理
由于很多现代网站的验证码使用canvas绘制,我们无法直接获取图片链接。最可靠的方法是截图。
# 6. 截图并裁剪出验证码图片 def get_element_image(driver, element): """截取指定WebElement的图片,并返回PIL.Image对象""" # 第一步:获取元素的位置和大小 location = element.location size = element.size # 第二步:获取整个页面的截图 driver.save_screenshot('full_page.png') # 临时保存全屏截图 # 第三步:根据元素坐标裁剪 left = location['x'] top = location['y'] right = left + size['width'] bottom = top + size['height'] full_page_img = Image.open('full_page.png') element_img = full_page_img.crop((left, top, right, bottom)) # 可选:保存图片用于调试 # element_img.save('debug_background.png') return element_img # 获取背景图和滑块图的PIL Image对象 background_pil_img = get_element_image(driver, background_img_element) slider_pil_img = get_element_image(driver, slider_img_element) # 将PIL Image转换为字节流,便于上传 background_bytes = io.BytesIO() slider_bytes = io.BytesIO() background_pil_img.save(background_bytes, format='PNG') slider_pil_img.save(slider_bytes, format='PNG')踩坑实录:
- 坐标偏移:
element.location获取的坐标是相对于整个文档的,而截图是相对于视口的。如果页面有滚动,或者验证码元素不在首屏,这个坐标会不准。解决方案:在截图前,用JavaScript将元素滚动到视口中央:driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", element)。 - DPI缩放:在高DPI(如4K)屏幕上,浏览器汇报的坐标和实际像素可能有一个缩放系数。这会导致裁剪出的图片错位。一个简单的检查方法是,截图后,用画图工具打开,看看你根据坐标框选的范围是否正好是验证码区域。如果不对,可能需要根据系统缩放比例调整坐标。在我的Mac上,缩放因子是2,所以坐标需要乘以2。
- 图片格式:确保保存为
PNG格式,避免JPEG压缩带来的画质损失影响识别精度。
4.4 调用图鉴API获取缺口位置
现在,我们有了两张图片的字节流,可以调用图鉴的API了。
# 7. 调用图鉴平台API识别缺口位置 def identify_gap(background_bytesio, slider_bytesio, username, password, type_id='9101'): """调用图鉴滑动验证码识别接口""" api_url = 'http://api.ttshitu.com/predict' # 图鉴API地址,请以官方最新文档为准 files = { 'background': ('bg.png', background_bytesio.getvalue(), 'image/png'), 'target': ('target.png', slider_bytesio.getvalue(), 'image/png') } data = { 'username': username, 'password': password, 'typeid': type_id, 'softid': 'your_softid' # 软件ID,可在图鉴后台创建,非必填 } try: resp = requests.post(api_url, files=files, data=data, timeout=10) result = resp.json() if result['success']: # 返回的坐标通常是缺口左上角的x坐标 gap_x = result['data']['result'] return int(gap_x) else: print(f"识别失败: {result['message']}") return None except Exception as e: print(f"API请求异常: {e}") return None # 你的图鉴账号信息 tj_username = 'your_tujian_username' tj_password = 'your_tujian_password' gap_position_x = identify_gap(background_bytes, slider_bytes, tj_username, tj_password) if gap_position_x is None: print("验证码识别失败,程序退出") driver.quit() exit() print(f"识别到的缺口X坐标: {gap_position_x}")关键点解析:
- API参数:
files参数用于上传图片文件,data参数传递账号和类型信息。softid是平台用于统计软件调用量的,可以在后台申请,不填也可以。 - 错误处理:一定要对API的返回结果进行判断。
success字段为True才表示成功。失败原因可能是点数不足、图片格式错误、类型码不对等。 - 坐标含义:API返回的
result值,通常是拼图缺口左侧边缘在背景图中的X坐标(像素)。这是我们后续计算滑动距离的基础。
4.5 模拟人类滑动轨迹与执行拖动
拿到缺口坐标后,我们不能简单地把滑块直接拖到那个位置。那样是匀速直线运动,瞬间就会被识别为机器。我们需要模拟人类的拖动行为:先加速,再减速,中间可能还有小小的停顿或抖动。
# 8. 根据缺口位置计算滑动距离,并生成模拟轨迹 def get_track(distance): """根据总距离生成模拟人类滑动的轨迹列表(每一步的位移)""" # 基础参数:总距离、加速度、减速度阈值、时间间隔 track = [] current = 0 mid = distance * 4 / 5 # 前4/5路程加速,后1/5减速 t = 0.2 # 模拟的时间间隔 v = 0 # 初速度 while current < distance: if current < mid: a = 2 # 加速阶段加速度 else: a = -3 # 减速阶段加速度 # 计算当前间隔内的位移 (s = v0*t + 0.5*a*t^2) s = v * t + 0.5 * a * (t ** 2) # 计算当前间隔结束时的速度 (v = v0 + a*t) v = v + a * t current += s track.append(round(s)) # 取整,因为像素移动是整数 # 由于计算误差,最后可能超出或不足一点,进行调整 overshoot = current - distance if overshoot > 0: # 如果超了,在轨迹最后几步微调回来 track[-1] = track[-1] - overshoot elif overshoot < 0: # 如果不足,补一步 track.append(-overshoot) return track # 计算需要滑动的总距离 # 注意:缺口坐标是相对于整个背景图的。但我们的滑块初始位置在0。 # 同时,由于截图裁剪、页面缩放等因素,可能需要一个偏移量进行校准。 # 最简单的办法:先计算一个理论距离,然后通过实际测试微调一个offset。 offset = 5 # 经验偏移值,可能需要根据实际情况调整(如-5, 0, 5等) slide_distance = gap_position_x - offset # 生成轨迹 track_list = get_track(slide_distance) print(f"滑动总距离: {slide_distance}, 轨迹步数: {len(track_list)}") # 9. 执行滑动操作 action = ActionChains(driver) action.click_and_hold(slider_button).perform() # 按住滑块 time.sleep(0.2) # 按住后稍作停顿,更像真人 for step in track_list: action.move_by_offset(step, 0).perform() # 水平移动 time.sleep(0.05) # 每步之间加入微小延迟,轨迹更真实 # 滑动到位后,模拟人的释放动作:可能有一个小小的回弹或抖动 action.release().perform() # 或者用 move_by_offset 制造一个很小的反向抖动 # action.move_by_offset(-2, 0).perform() # action.release().perform() time.sleep(2) # 等待验证结果和页面跳转轨迹模拟的精髓:
- 加速度变化:这是区分机器与人的关键。人的拖动通常是“快-慢”或“慢-快-慢”模式。上面的代码模拟了先匀加速再匀减速的过程。
- 加入随机性:更高级的模拟可以在位移中引入微小的随机扰动(如
step + random.randint(-2, 2)),在时间间隔上也加入随机sleep(random.uniform(0.03, 0.07))),让轨迹更不可预测。 - 偏移量校准:
offset变量至关重要!因为截图坐标、浏览器缩放、验证码本身的边缘留白都可能导致理论距离不准。这个值需要通过实际测试来调整。比如,如果总是差一点滑到位,就减小offset;如果滑过头了,就增大offset。
4.6 验证登录结果与资源清理
最后,我们需要检查是否登录成功,并优雅地关闭浏览器。
# 10. 验证登录是否成功 # 可以通过检查登录后才会出现的元素来判断,例如用户头像、用户名显示等 try: # 假设登录成功后,页面会出现一个class为‘user-avatar’的元素 user_element = driver.find_element(By.CLASS_NAME, 'user-avatar') print("登录成功!") # 登录成功后,你可以继续后续操作,比如跳转到目标页面采集数据 # target_url = 'https://www.om.cn/design-case' # driver.get(target_url) # time.sleep(3) except Exception as e: print("登录可能失败,未找到登录成功标志元素。") # 可以在这里保存当前页面的截图,用于调试 driver.save_screenshot('login_failed.png') print(f"错误信息: {e}") # 11. 保持会话或退出 # 如果后续还有操作,就不要quit,保持driver # 如果登录完成,暂时不需要操作,可以关闭浏览器 # input("按回车键退出...") # 用于调试时暂停查看页面 driver.quit()完整代码整合与运行:将以上所有代码段按顺序组合在一个.py文件中,替换掉其中的your_username_here、your_password_here、your_tujian_username、your_tujian_password以及最重要的——通过开发者工具查找到的正确的页面元素选择器,就可以运行了。
5. 常见问题排查与优化技巧实录
即使代码逻辑正确,在实际运行中你依然会遇到各种各样的问题。下面是我在调试过程中遇到的一些典型问题及解决方法,希望能帮你快速排雷。
5.1 元素定位失败与动态加载问题
问题现象:NoSuchElementException,找不到用户名输入框、密码框、登录按钮或验证码图片元素。
排查思路与解决:
- 检查选择器:这是最常见的原因。网站改版了,或者你复制的选择器不对。务必使用开发者工具重新确认。优先使用
id和name,其次考虑相对稳定的class或>from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 等待登录按钮出现并可点击,最多等10秒 login_button = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.CLASS_NAME, 'login-btn')) ) login_button.click()对于验证码图片,可能需要等待其canvas元素加载完成并具备一定尺寸。 - 页面嵌套(iframe):如果验证码被包裹在一个
<iframe>标签内,你必须先切换到该iframe中,才能找到里面的元素。# 找到iframe元素 iframe = driver.find_element(By.TAG_NAME, 'iframe') # 或用更具体的选择器 # 切换到iframe内部 driver.switch_to.frame(iframe) # 现在可以定位iframe内的验证码元素了 # ... 操作完成后,切回主页面 driver.switch_to.default_content()
5.2 验证码识别坐标不准或失败
问题现象:图鉴API返回了坐标,但滑动后验证失败,提示“拼图失败”或直接刷新验证码。
排查思路与解决:
- 校准偏移量(Offset):这是首要检查项。写一个简单的测试循环,让脚本只识别和滑动,但不执行后续登录。手动观察滑块最终位置与缺口的偏差。如果总是差一点,就调整
offset值。建议每次调整2-3个像素进行测试。 - 检查截图范围:确保
get_element_image函数裁剪出的图片正好是完整的验证码区域,没有多截或少截。保存裁剪出的background_pil_img和slider_pil_img到本地,用图片查看器打开,看是否完整清晰。 - 验证码类型码错误:确认你传给图鉴API的
typeid参数是正确的。不同平台的滑动验证码类型码可能不同,甚至同一平台不同网站也不同。仔细阅读图鉴后台的文档或示例。 - 图片质量问题:如果截图模糊、有半透明遮罩或者颜色异常,会影响识别。检查浏览器缩放是否为100%。尝试在截图前等待更长时间(
time.sleep(5)),确保图片完全渲染。 - 轨迹被检测:即使坐标对了,过于规律的轨迹也会被识别。尝试优化
get_track函数:- 在轨迹列表中加入1-2个极短距离(如1像素)的反向移动,模拟手抖。
- 将匀速运动改为更复杂的变速运动,例如使用匀加速-匀速-匀减速三段式,或者用正态分布生成位移序列。
- 在滑动结束后,加入一个很小的随机回弹(
action.move_by_offset(-random.randint(1,3), 0).perform())。
5.3 行为特征检测与反爬应对
问题现象:脚本在本地测试成功,但放到服务器或运行多次后,触发风控,出现“操作过于频繁”、“需要人工验证”等提示。
应对策略:
- 降低频率,加入随机延迟:在关键操作(输入、点击、滑动)前后,使用
time.sleep(random.uniform(1, 3))代替固定的sleep,让操作节奏更拟人。 - 完善浏览器指纹:使用更全面的ChromeOptions来隐藏自动化特征。
options.add_experimental_option("excludeSwitches", ["enable-automation"]) options.add_experimental_option('useAutomationExtension', False) options.add_argument('--disable-blink-features=AutomationControlled') # 可以设置一个常见的User-Agent options.add_argument('user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ...') - 使用更底层的驱动或工具:对于反爬极强的网站,Selenium可能被轻易检测。可以考虑使用Playwright或Puppeteer,它们能提供更真实的浏览器上下文,并且可以通过
stealth插件来更好地隐藏自动化特征。不过,这需要重新学习一套API。 - 代理IP池:如果登录请求过于频繁,服务器可能会封禁你的IP。对于大规模自动化,需要考虑使用代理IP池来轮换IP地址。
- 人工干预兜底:在关键环节(如最终滑动前)加入一个判断,如果连续失败N次,则暂停脚本,保存当前状态截图,并发送通知(如邮件、钉钉消息),等待人工介入处理。这是一种务实的工程思维。
5.4 代码健壮性与异常处理
一个用于生产环境的脚本,必须有良好的异常处理。
- 网络请求重试:对图鉴API的调用,可以封装一个带重试机制的函数,避免因网络波动导致的偶然失败。
import requests from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry def create_session_with_retry(retries=3, backoff_factor=0.5): session = requests.Session() retry_strategy = Retry( total=retries, backoff_factor=backoff_factor, status_forcelist=[500, 502, 503, 504] ) adapter = HTTPAdapter(max_retries=retry_strategy) session.mount("http://", adapter) session.mount("https://", adapter) return session session = create_session_with_retry() resp = session.post(api_url, files=files, data=data, timeout=10) - 流程状态记录与断点续做:对于需要处理大量账号或任务的脚本,可以将每个账号的登录状态(成功、失败、失败原因)记录到文件或数据库。如果脚本中途崩溃,重启后可以跳过已成功的任务。
- 日志记录:使用Python的
logging模块,将关键步骤、识别结果、滑动距离、异常信息等记录到日志文件,便于后期排查问题。
最后,把完整的、可运行的代码分享出来,供大家参考和测试。请再次注意,务必替换代码中的所有占位符(账号、密码、元素选择器)为你自己的信息,并根据实际网页结构进行调整。这个方案的核心思路是通用的,掌握了它,你就能应对大多数类似欧模网这样的滑动验证码登录场景。