当前位置: 首页 > news >正文

实战复盘:用Python+Requests搞定那个烦人的WIPO六宫格验证码(附完整代码)

实战复盘:用Python+Requests攻克WIPO六宫格验证码的完整技术方案

在专利数据采集领域,WIPO(世界知识产权组织)数据库是许多研究者和企业的重要信息来源。然而,其复杂的反爬机制常常让开发者望而却步。最近我在一个项目中就遇到了这个棘手的六宫格验证码问题,经过两周的反复调试和优化,终于找到了一套稳定可靠的解决方案。本文将完整分享从验证码识别到会话管理的全流程实现细节,特别适合那些已经掌握基础爬虫技术但需要突破反爬瓶颈的中级开发者。

1. 六宫格验证码的识别策略

WIPO的六宫格验证码属于典型的图像识别类反爬手段,系统会随机展示6张图片,要求用户选择符合特定描述(如"带有汽车的图片")的图片。与传统验证码不同,这种交互式验证对自动化程序提出了更高要求。

1.1 验证码样本收集与标注

识别这类验证码的第一步是建立完整的样本库。通过观察,我发现WIPO主要使用三类验证码主题:交通工具、建筑和自然景观。每种类型需要收集至少50张样本图片才能保证识别准确率。

import os import requests from PIL import Image from io import BytesIO def collect_samples(session, sample_size=50): base_url = "https://patentscope.wipo.int" sample_types = ['vehicle', 'building', 'landscape'] for category in sample_types: os.makedirs(f"./wipo_samples/{category}", exist_ok=True) count = 0 while count < sample_size: resp = session.get(f"{base_url}/captcha") if resp.status_code == 200: img = Image.open(BytesIO(resp.content)) img.save(f"./wipo_samples/{category}/{count}.png") count += 1

注意:样本收集需要间隔至少5秒,避免触发频率限制。建议使用代理IP轮询以提高效率。

1.2 图像相似度比对算法

经过对比测试,我发现结构相似性指数(SSIM)在WIPO验证码识别中表现优于传统的像素比对。以下是优化后的识别核心代码:

from skimage.metrics import structural_similarity as ssim import cv2 import numpy as np def compare_images(img1_path, img2_path): # 转换为灰度图并调整尺寸 img1 = cv2.resize(cv2.imread(img1_path, 0), (100, 100)) img2 = cv2.resize(cv2.imread(img2_path, 0), (100, 100)) # 计算SSIM指数 score = ssim(img1, img2) return score def identify_captcha(session, prompt_text): # 根据提示文本确定样本目录 category = "vehicle" if "vehicle" in prompt_text else "building" if "building" in prompt_text else "landscape" samples_dir = f"./wipo_samples/{category}" # 获取验证码图片 resp = session.get("https://patentscope.wipo.int/captcha") captcha_img = Image.open(BytesIO(resp.content)) # 与样本库比对 best_match = {"score": 0, "index": 0} for i in range(6): sample_path = f"{samples_dir}/{i}.png" current_score = compare_images(sample_path, captcha_img) if current_score > best_match["score"]: best_match = {"score": current_score, "index": i} return best_match["index"] if best_match["score"] > 0.7 else -1

2. 会话管理与Cookie反爬破解

WIPO采用了多层会话绑定机制,简单的requests.Session()并不足以维持有效会话。以下是关键问题的解决方案:

2.1 验证码与Session的强绑定

系统会在验证通过后生成新的view_state值,必须及时更新会话状态:

def handle_captcha(session): max_attempts = 3 for _ in range(max_attempts): # 获取验证码提示文本 resp = session.get("https://patentscope.wipo.int/search") prompt = extract_prompt(resp.text) # 自定义提取函数 # 识别并提交验证码 captcha_index = identify_captcha(session, prompt) if captcha_index == -1: continue post_data = {"captcha_index": captcha_index} resp = session.post("https://patentscope.wipo.int/validate", data=post_data) # 检查是否验证成功 if "验证成功" in resp.text: update_session_state(session, resp) # 更新view_state等参数 return True return False

2.2 CSS链接的Cookie刷新机制

这是最隐蔽的反爬措施之一 - 详情页数据获取前必须访问特定的CSS文件:

步骤操作关键参数等待时间
1访问详情页session_id2秒
2提取CSS链接view_state1秒
3访问CSS文件css_token0.5秒
4再次访问详情页updated_cookie1秒

实现代码示例:

def get_detail_page(session, patent_id): # 首次访问详情页 detail_url = f"https://patentscope.wipo.int/detail/{patent_id}" session.get(detail_url) time.sleep(2) # 提取CSS链接 css_path = extract_css_link(session, detail_url) if not css_path: return None # 访问CSS文件刷新Cookie css_url = f"https://patentscope.wipo.int{css_path}" session.get(css_url) time.sleep(0.5) # 最终获取详情数据 resp = session.get(detail_url) time.sleep(1) return resp.json() if resp.status_code == 200 else None

3. 反反爬策略的优化实践

3.1 请求间隔的动态调整

固定sleep时间容易被识别,建议使用随机间隔:

import random import time def smart_delay(): base = 1.5 # 基础等待时间 variation = random.uniform(0.5, 2.5) # 随机变化幅度 time.sleep(base * variation)

3.2 请求头的高级伪装

WIPO会检测Header的完整性,以下是最小必需字段:

headers = { "Accept": "text/html,application/xhtml+xml", "Accept-Language": "en-US,en;q=0.9", "Connection": "keep-alive", "Referer": "https://patentscope.wipo.int/search", "Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" }

4. 完整工作流实现

将上述模块组合成端到端解决方案:

def fetch_wipo_patent(patent_id): # 初始化会话 session = requests.Session() session.headers.update(headers) # 处理验证码 if not handle_captcha(session): raise Exception("验证码处理失败") # 获取详情数据 patent_data = get_detail_page(session, patent_id) if not patent_data: raise Exception("详情页获取失败") # 提取关键字段 return { "title": patent_data.get("title"), "abstract": patent_data.get("abstract"), "applicants": patent_data.get("applicants"), "publication_date": patent_data.get("pubDate") }

在实际项目中,这套方案成功将WIPO数据采集的成功率从最初的不到30%提升到了92%以上。最难调试的部分其实是CSS链接的刷新机制,当时花了三天时间才意识到必须访问那个看似无关的CSS文件。现在回头看,这种设计确实巧妙 - 它模拟了真实用户浏览网页时的资源加载行为。

http://www.jsqmd.com/news/898925/

相关文章:

  • 解锁学术创作新思路:paperxie 论文智能撰写功能实用使用指南
  • 液体处理技术核心参数与自动化优化实践
  • 告别重复劳动!用AutoHotKey脚本一键搞定文件整理与备份(附完整代码)
  • 告别V4L2的复杂性?试试用libuvc库在Linux上更灵活地控制USB摄像头
  • RISC-V RV32I指令集编码实战:手把手教你用Python解析指令二进制(附完整代码)
  • 在 Taotoken 模型广场对比主流模型特性与定价进行选型
  • 基于Amazon Bedrock与HTTP流式传输实现Web应用实时AI摘要
  • 博弈论视角下的多域NFV资源编排:竞争与联盟策略解析
  • MRAE自编码器:混合正则化实现鲁棒特征提取
  • 深入解析STM32控制张大头闭环步进驱动器:从数据帧到多电机协同的避坑指南
  • 告别命令行恐惧!用nTopology可视化工具5分钟搞定三维Voronoi泡沫建模
  • 学术创作效率升级:paperxie 学术写作模块解锁毕业论文高效撰写模式
  • ShotgunWSD 2.0:基于k-means聚类的无监督词义消歧算法详解
  • 回声消除实战:用MATLAB手把手实现频域分块LMS(FDAF)算法
  • XSS实战:从haozi.me靶场通关看前端安全攻防演进
  • 基于RGB-D的视角不变动作识别:双流异构特征融合与协同表示分类
  • STM32CubeMX串口配置避坑指南:从HAL库到LL库,如何选择最适合你的收发方案?
  • 企业线上曝光差做GEO优化有用吗
  • 山东软体储油囊技术参数拆解与靠谱供应商指南 - 奔跑123
  • 抖音无水印视频批量下载终极方案:douyin-downloader技术深度解析
  • 学术写作新范式:paperxie 毕业论文 AI 写作功能的深度赋能与合规实践
  • FAV2G:基于雾计算与硬件加速的V2G安全认证方案深度解析
  • ARMv8-A架构下AArch32 ID_ISAR4寄存器详解与应用
  • 5分钟掌握B站视频下载神器:BiliDownloader完整指南
  • ChatGPT时间管理实战指南(职场人私藏版):92%用户未启用的3个隐藏指令+自动化日程引擎
  • ChatGPT中文场景特供手册:针对党政公文、医疗问诊、K12教学的11类专业话术库,已通过教育部语用司交叉验证
  • 广州荔湾区搬家公司 废旧物品丢弃全指南 专业清运攻略 - 从来都是英雄出少年
  • AI应用成本实时监控:从LLM API调用优化到Token级费用管理
  • 统一ECC加速器设计:自动化DSE与参数化架构优化实践
  • 深度逆向工程实战:完全解析Wallpaper Engine资源提取工具RePKG