12306验证码破解技术概述
12306网站使用复杂的验证码系统来防止自动化程序,主要包括两种类型:滑动验证码和点选验证码。本教程将教你如何使用Python处理这两种验证码。
滑动验证码
需要将滑块拖动到缺口位置,难点在于识别缺口位置和模拟人类拖动行为。
点选验证码
需要按顺序点击图片中的文字或物体,难点在于文字识别和位置定位。
重要提示:本教程仅用于学习目的,请勿用于非法抢票或攻击12306系统。
环境准备
在开始之前,确保安装以下Python库:
- Selenium - 浏览器自动化工具
- OpenCV - 图像处理库
- Pillow - 图像处理
- NumPy - 数值计算
- Requests - HTTP请求库
使用以下命令安装:
pip install selenium opencv-python pillow numpy requests
处理滑动验证码
滑动验证码破解分为四个步骤:获取图片、识别缺口、计算距离、模拟拖动。
步骤1:获取验证码图片
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
import requests
from PIL import Image
driver = webdriver.Chrome()
driver.get('https://kyfw.12306.cn/otn/resources/login.html')
# 切换到账号登录
driver.find_element(By.CLASS_NAME, 'login-hd-account').click()
time.sleep(1)
# 点击触发验证码
driver.find_element(By.ID, 'J-userName').send_keys('your_username')
driver.find_element(By.ID, 'J-password').send_keys('your_password')
driver.find_element(By.ID, 'J-login').click()
time.sleep(2)
# 获取验证码图片
captcha = driver.find_element(By.ID, 'J-loginImg')
captcha.screenshot('captcha.png')
步骤2:识别缺口位置
import cv2
import numpy as np
def detect_gap(bg_path, tp_path):
# 读取背景图片和缺口图片
bg_img = cv2.imread(bg_path)
tp_img = cv2.imread(tp_path)
# 边缘检测
bg_edge = cv2.Canny(bg_img, 100, 200)
tp_edge = cv2.Canny(tp_img, 100, 200)
# 匹配模板
result = cv2.matchTemplate(bg_edge, tp_edge, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
return max_loc[0] # 返回缺口x坐标
# 使用示例
gap_x = detect_gap('captcha_bg.png', 'captcha_slider.png')
print(f"缺口位置在: {gap_x}px")
步骤3:模拟人类拖动
from selenium.webdriver import ActionChains
def simulate_drag(driver, slider, distance):
# 创建动作链
actions = ActionChains(driver)
# 点击并按住滑块
actions.click_and_hold(slider).perform()
# 模拟人类拖动行为(先快后慢)
total_tracks = []
current = 0
mid = distance * 4 / 5
t = 0.2
while current < distance:
if current < mid:
# 快速移动阶段
a = 2
else:
# 慢速移动阶段
a = -3
v0 = 1
move = v0 * t + 0.5 * a * t * t
current += move
# 添加随机偏移
if current < distance:
total_tracks.append(round(move))
# 添加最后的微调
total_tracks.append(round(distance - sum(total_tracks)))
# 执行拖动操作
for track in total_tracks:
actions.move_by_offset(track, 0).perform()
time.sleep(0.02)
# 释放滑块
actions.release().perform()
# 使用示例
slider = driver.find_element(By.ID, 'nc_1_n1z')
simulate_drag(driver, slider, gap_x)
处理点选验证码
点选验证码需要识别图片中的文字并点击对应位置。
步骤1:获取验证码图片和提示文字
# 获取提示文字
prompt_text = driver.find_element(By.CLASS_NAME, 'code-tip').text
print(f"提示文字: {prompt_text}")
# 获取验证码图片
captcha = driver.find_element(By.ID, 'J-loginImg')
captcha.screenshot('click_captcha.png')
步骤2:使用OCR识别文字位置
import pytesseract
from PIL import Image
def recognize_text(image_path):
# 预处理图像
img = Image.open(image_path)
img = img.convert('L') # 灰度转换
img = img.point(lambda x: 0 if x < 128 else 255) # 二值化
# 使用OCR识别文字
text = pytesseract.image_to_string(img, lang='chi_sim')
return text.strip()
# 使用示例
captcha_text = recognize_text('click_captcha.png')
print(f"识别的文字: {captcha_text}")
步骤3:点击对应位置
def click_positions(driver, positions):
# 获取验证码元素位置
captcha = driver.find_element(By.ID, 'J-loginImg')
x = captcha.location['x']
y = captcha.location['y']
# 点击每个位置
actions = ActionChains(driver)
for pos in positions:
# 计算相对位置
target_x = x + pos[0]
target_y = y + pos[1]
# 移动并点击
actions.move_by_offset(target_x, target_y).click().perform()
time.sleep(0.5)
# 提交验证
driver.find_element(By.ID, 'J-login').click()
# 使用示例
# positions = [(50, 30), (120, 80)] # 根据识别结果确定的位置
# click_positions(driver, positions)
常见问题与解决方案
Q: 验证码识别率低怎么办?
A: 尝试以下方法:
- 使用更高质量的OCR服务(如百度AI、腾讯AI)
- 增加图像预处理步骤(去噪、锐化、二值化)
- 使用深度学习模型训练专用识别器
Q: 被12306封IP怎么办?
A: 采取以下措施:
- 使用代理IP池轮换IP地址
- 降低请求频率,模拟人类操作间隔
- 使用不同的User-Agent
Q: 如何提高模拟拖动的成功率?
A: 优化拖动行为:
- 添加随机停顿和偏移量
- 模拟加速度变化(先快后慢)
- 添加垂直方向的随机抖动
- 最后添加微调动作
发表评论