Python爬虫实战:自动提交表单与验证码识别的终极指南

✨前言

在信息获取自动化越来越重要的今天,Python 爬虫技术成为数据采集的首选工具。在自动化登录、用户行为模拟、批量抓取等操作中,自动提交表单是一个核心环节。然而,验证码的存在成为拦路虎,意在防止机器人攻击。

本篇博客将通过 最新的 Python 工具链和深度学习模型,深入剖析如何自动提交带验证码的表单,做到从页面解析、验证码下载、图像识别到数据提交的全流程自动化。全文包含:

  • Python爬虫核心库介绍
  • 表单识别与构造
  • 验证码识别模型设计
  • 自动登录/提交实现
  • 完整代码展示与实战总结

本文将以某些经典示例站点为例,展示通用技术。请遵守目标网站robots.txt与使用协议。


️一、Python爬虫技术栈总览

我们将使用以下技术栈:

类型 工具/库 功能
网络请求 requests + httpx 表单交互与多线程
HTML解析 BeautifulSoup4 + lxml 提取表单结构
验证码识别 Pillow, tesserocr, EasyOCR, CNN 图像预处理与识别
模拟行为 selenium JS动态页面处理
模型训练 PyTorch 字符识别深度学习模型
数据处理 pandas, numpy 结构化存储与分析
日志与异常处理 logging 调试与日志持久化

二、理解表单与验证码的交互机制

典型表单的 HTML 长这样:

html
复制编辑

表单构成要素:

  • 表单地址action="/login" 是提交地址
  • 请求方式POST
  • 隐藏字段:如 CSRF token
  • 验证码:img 标签指向验证码图片地址

三、验证码识别原理与实践

验证码类型:

  1. 纯数字/字母验证码(静态图像)
  2. 滑动验证(需要 JS 模拟)
  3. 语义验证码(需 NLP 处理)

我们重点攻克第一类。处理流程:

  1. 下载验证码图像
  2. 图像预处理(去噪、灰度、二值化)
  3. 分割字符(如有需要)
  4. OCR识别或自定义CNN模型识别

四、核心代码实现

1. 获取验证码图片并保存

python
复制编辑
import requests
from PIL import Image
from io import BytesIO

captcha_url = 'https://example.com/captcha.jpg'
session = requests.Session()

response = session.get(captcha_url)
image = Image.open(BytesIO(response.content))
image.save('captcha.jpg')

2. 图像预处理

python
复制编辑
from PIL import ImageFilter, ImageOps

def preprocess_image(img_path):
    img = Image.open(img_path).convert('L')  # 灰度化
    img = ImageOps.invert(img)               # 黑白翻转
    img = img.filter(ImageFilter.MedianFilter())  # 中值滤波去噪
    threshold = 128
    img = img.point(lambda p: p > threshold and 255)
    return img

3. 使用OCR识别验证码(tesserocr)

python
复制编辑
import tesserocr

def ocr_recognize(img):
    return tesserocr.image_to_text(img).strip()

img = preprocess_image('captcha.jpg')
captcha_text = ocr_recognize(img)
print(f"识别验证码:{captcha_text}")

4. 使用CNN模型识别验证码(可选)

如识别准确率较低,可以自训练CNN模型:

python
复制编辑
# 简化版CNN结构
import torch.nn as nn

class CaptchaCNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(1, 32, 3, 1),
            nn.ReLU(),
            nn.MaxPool2d(2),
        )
        self.fc = nn.Sequential(
            nn.Linear(32 * 13 * 30, 128),
            nn.ReLU(),
            nn.Linear(128, 36)  # 数字 + 字母
        )

    def forward(self, x):
        x = self.conv(x)
        x = x.view(-1, 32 * 13 * 30)
        return self.fc(x)

建议使用EasyOCR或预训练模型来避免重复造轮子。


5. 构造表单并提交

python
复制编辑
form_data = {
    'username': 'myuser',
    'password': 'mypassword',
    'captcha': captcha_text
}

headers = {
    'User-Agent': 'Mozilla/5.0',
    'Referer': 'https://example.com/login'
}

response = session.post('https://example.com/login', data=form_data, headers=headers)
print('登录结果:', response.status_code)

六、完整项目结构展示

css
复制编辑
auto_captcha_login/
├── main.py
├── captcha.jpg
├── model/
│   └── cnn_model.pt
├── utils/
│   └── image_utils.py
│   └── ocr.py
├── logs/
│   └── app.log

七、实战案例:模拟登录并爬取数据

python
复制编辑
# main.py
from utils.image_utils import preprocess_image
from utils.ocr import recognize_captcha
import requests

session = requests.Session()
img_url = 'https://example.com/captcha'
form_url = 'https://example.com/login'

# 1. 下载验证码
resp = session.get(img_url)
with open('captcha.jpg', 'wb') as f:
    f.write(resp.content)

# 2. 图像识别
img = preprocess_image('captcha.jpg')
captcha_text = recognize_captcha(img)

# 3. 表单提交
payload = {
    'username': 'admin',
    'password': '123456',
    'captcha': captcha_text
}
r = session.post(form_url, data=payload)
print("登录响应:", r.text)

八、验证码识别常见对策与破解策略

网站策略 爬虫对策
增加验证码复杂度 用深度学习提升识别
加入CSRF Token 提前解析网页并携带 token
滑块/拖动验证 使用 selenium 模拟行为
OCR干扰字符 图像增强 + 分割 + 模型

⚙️九、用 Selenium 自动操作验证码登录

对于 JavaScript 动态生成验证码或需要模拟点击场景,Selenium 是必备工具:

python
复制编辑
from selenium import webdriver
from selenium.webdriver.common.by import By
import time

driver = webdriver.Chrome()
driver.get('https://example.com/login')

# 下载验证码
captcha_img = driver.find_element(By.ID, 'captcha_img')
captcha_img.screenshot('captcha.png')

# 识别并填表
captcha = recognize_captcha(preprocess_image('captcha.png'))
driver.find_element(By.NAME, 'username').send_keys('admin')
driver.find_element(By.NAME, 'password').send_keys('123456')
driver.find_element(By.NAME, 'captcha').send_keys(captcha)
driver.find_element(By.ID, 'login_btn').click()

time.sleep(3)
driver.quit()

十、多线程与反爬策略应对

添加请求头和延迟

python
复制编辑
headers = {'User-Agent': fake_user_agent.random}
time.sleep(random.uniform(1, 3))

使用代理池

python
复制编辑
proxies = {
    "http": "http://123.123.123.123:8080",
    "https": "http://123.123.123.123:8080"
}
r = requests.get(url, proxies=proxies)

随机User-Agent

python
复制编辑
from fake_useragent import UserAgent
ua = UserAgent()
headers = {'User-Agent': ua.random}

十一、总结与建议

自动提交表单,尤其是含验证码的交互,是高级爬虫工程中的必备能力。本文完整演示了:

  • 如何下载并识别验证码(tesserocr/CNN)
  • 如何自动构造并提交登录请求
  • 如何使用 Selenium 提高适配性
  • 多线程、伪装和日志记录技巧

推荐进一步学习:

  • OCR模型训练(如 CRNN + CTC)
  • Selenium无头浏览器部署
  • JS逆向与加密参数还原

你可能感兴趣的:(python,爬虫,开发语言,数据库,selenium)