如何用Python+Selenium结合2captcha API解决ReCaptcha V2点击验证码的两类问题?
解决ReCaptcha V2图片点击验证的两个核心问题
我来帮你搞定这两个问题,直接上解决方案和修改后的代码:
一、生成随机命名截图并压缩至100KB以下
要实现这个需求,我们可以结合uuid生成唯一文件名,再用PIL调整图片质量来压缩大小:
- 随机命名:用
uuid.uuid4()生成不重复的文件名,避免多次运行时覆盖旧截图 - 图片压缩:通过PIL的
Image.save()方法调整quality参数,循环尝试直到文件大小低于100KB(也可以直接设置一个合适的初始值,比如60-70,根据实际情况调整)
二、解析坐标模拟点击&验证后删除截图
对于2captcha返回的坐标格式,我们需要先解析出每个点的x/y值,再用Selenium的ActionChains模拟点击;验证完成后用os.remove()删除截图:
- 坐标解析:把返回的字符串按
;分割,逐个提取x=xxx,y=yyy中的数值 - 模拟点击:需要先定位到验证码图片的元素,因为返回的坐标是相对于验证码图片的,不是整个页面的绝对坐标
- 删除截图:添加异常处理,避免文件不存在时抛出错误
修改后的完整代码
from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains from time import sleep, time from PIL import Image import requests import uuid import os # 生成随机文件名 def get_random_filename(): return f"{uuid.uuid4()}.jpg" # 压缩图片至指定大小以下(单位:KB) def compress_image(input_path, output_path, max_size_kb=100): quality = 80 # 初始质量 while True: with Image.open(input_path) as img: img.save(output_path, "JPEG", quality=quality, optimize=True) file_size = os.path.getsize(output_path) / 1024 # 转成KB if file_size <= max_size_kb or quality <= 10: break quality -= 5 # 每次降低5%质量 return output_path # 打开注册页面 browser = webdriver.Chrome('D:\\chromedriver') browser.get('http://testing-ground.scraping.pro/recaptcha') browser.maximize_window() # 点击复选框 recaptcha_checkbox = browser.find_element_by_xpath("//*[@role='presentation']") sleep(3) recaptcha_checkbox.click() sleep(3) # 生成随机截图并压缩 temp_screenshot = get_random_filename() browser.get_screenshot_as_file(temp_screenshot) compressed_screenshot = compress_image(temp_screenshot, temp_screenshot) # 覆盖原文件 # 发送POST请求到2captcha api_key = "你的2captcha密钥" url = 'http://2captcha.com/in.php' files = {'file': open(compressed_screenshot, 'rb')} data = { 'key': api_key, 'method': 'post', 'coordinatescaptcha': '1', 'textinstructions': 'click on fire hydrant' } resp = requests.post(url, files=files, data=data) if resp.ok: captcha_id = resp.text[3:] print(f"验证码ID:{captcha_id}") # 轮询获取验证结果 fetch_url = f"http://2captcha.com/res.php?key={api_key}&action=get&id={captcha_id}" captcha_result = None for i in range(1, 10): sleep(5) # 等待5秒 resp = requests.get(fetch_url) if resp.text.startswith('OK|'): captcha_result = resp.text[3:] break if captcha_result: print(f"验证结果:{captcha_result}") # 定位验证码图片元素(需要根据实际页面调整定位方式) captcha_image = browser.find_element_by_xpath("//div[@class='rc-image-tile-wrapper']") # 解析坐标 coordinates = captcha_result.split(';') actions = ActionChains(browser) for coord in coordinates: if coord.strip(): x_str, y_str = coord.split(',') x = int(x_str.split('=')[1]) y = int(y_str.split('=')[1]) # 相对于验证码图片点击 actions.move_to_element_with_offset(captcha_image, x, y).click().perform() sleep(0.5) # 每次点击间隔0.5秒,模拟真人操作 # 等待验证完成 sleep(3) else: print("验证码验证超时或失败") # 清理截图文件 try: if os.path.exists(temp_screenshot): os.remove(temp_screenshot) print("截图已删除") except Exception as e: print(f"删除截图失败:{str(e)}") # 关闭浏览器(可选) browser.quit()
关键细节说明
- 随机文件名:用
uuid保证每次运行生成的文件名唯一,不会和之前的截图冲突 - 图片压缩:循环调整质量参数,确保最终文件大小低于100KB,符合2captcha的要求
- 坐标点击:必须基于验证码图片元素的相对坐标,否则点击位置会偏移(如果页面有滚动,还要先滚动到验证码可见区域)
- 截图清理:添加
try-except处理,避免文件已被删除或权限问题导致报错
内容的提问来源于stack exchange,提问作者Saeed Alipoor
相关产品推荐
相关产品推荐

