💡需求分析
在一些网页中经常会出现验证码输入的情况,手动输入太麻烦了,如何设计让验证码自动填入十分有必要。
💡规划设置
服务端采用Python中ddddocr和FastAPI实现验证码的识别,浏览器用油猴脚本自动完成。
💡实现过程
1️⃣ FastAPI 服务器(后端)
-
接收网页验证码图片
-
使用
ddddocr
进行验证码识别 -
返回识别出的验证码文本
-
采用
FastAPI
(比 Flask 快),提高识别速度 -
支持高并发请求
-
接口地址:
http://localhost:5000/recognize
2️⃣ 油猴 (Tampermonkey) 脚本(前端)
-
自动获取验证码图片
-
调用 FastAPI 服务器识别验证码
-
填充验证码输入框
-
监听验证码变化,支持自动刷新的验证码
-
点击验证码图片时重新识别
-
提供手动“🔍 识别验证码”按钮
🎯 具体流程
1️⃣.FastAPI 服务器
-
网页上的验证码图片(Base64)发送到 FastAPI 服务器
-
FastAPI 解析 Base64 图片,并使用
ddddocr
进行验证码识别 -
返回识别结果
-
油猴脚本接收返回的验证码文本,并填充到输入框
2️⃣ 油猴脚本
-
网页加载时自动获取验证码图片
-
调用 FastAPI 服务器进行识别
-
识别成功后,将验证码填入输入框
-
监听验证码图片刷新,如果验证码图片
src
变化,则自动重新识别 -
用户点击验证码图片,触发识别逻辑,重新获取验证码
-
手动识别,用户点击“🔍 识别验证码”按钮,主动识别验证码
编码
- 服务器代码
from fastapi import FastAPI, HTTPException from pydantic import BaseModel import ddddocr import uvicorn import base64 app = FastAPI() ocr = ddddocr.DdddOcr() class ImageData(BaseModel): image: str # Base64 图片数据 @app.post("/recognize") async def recognize_captcha(data: ImageData): try: image_bytes = base64.b64decode(data.image.split(",")[1]) # 解析 Base64 code = ocr.classification(image_bytes) return {"code": code} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) # 运行服务器 if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=5000)
- 油猴代码
// ==UserScript== // @name FastAPI 自动识别验证码 // @namespace http://tampermonkey.net/ // @version 1.3 // @description 监听验证码变化、点击刷新、手动识别,使用 FastAPI 提高识别速度 // @author www.suyehe.com // @match *://*/* // @grant GM_xmlhttpRequest // @grant GM_addStyle // @grant GM_log // ==/UserScript== (function () { 'use strict'; // 配置项(修改这里适配不同网站) const SERVER_URL = "http://localhost:5000/recognize"; // FastAPI 服务器地址 const CAPTCHA_IMAGE_ID = "verifyCode"; // 验证码图片 ID const CAPTCHA_INPUT_ID = "captcha"; // 验证码输入框 ID function recognizeCaptcha() { let img = document.getElementById(CAPTCHA_IMAGE_ID); if (!img) { GM_log("❌ 验证码图片未找到"); return; } let imageUrl = img.src; GM_log("📸 获取验证码图片: " + imageUrl); // 下载验证码图片并转换为 Base64 GM_xmlhttpRequest({ method: "GET", url: imageUrl, responseType: "blob", onload: function (response) { let reader = new FileReader(); reader.readAsDataURL(response.response); reader.onloadend = function () { let base64Image = reader.result; // 发送到 FastAPI 服务器进行识别 GM_xmlhttpRequest({ method: "POST", url: SERVER_URL, headers: { "Content-Type": "application/json" }, data: JSON.stringify({ image: base64Image }), onload: function (response) { let result = JSON.parse(response.responseText); if (result.code) { let captchaInput = document.getElementById(CAPTCHA_INPUT_ID); if (captchaInput) { captchaInput.value = result.code; GM_log("✅ 识别成功: " + result.code); } else { GM_log("❌ 验证码输入框未找到"); } } else { GM_log("❌ 识别失败: " + response.responseText); } }, onerror: function (error) { GM_log("❌ 请求失败: " + error); } }); }; }, onerror: function (error) { GM_log("❌ 无法加载验证码图片: " + error); } }); } // 监听验证码图片的变化(适用于自动刷新的验证码) function observeCaptchaChange() { let img = document.getElementById(CAPTCHA_IMAGE_ID); if (img) { let observer = new MutationObserver(() => { GM_log("🔄 检测到验证码图片更新,重新识别..."); setTimeout(recognizeCaptcha, 1000); // 等待1秒再识别 }); observer.observe(img, { attributes: true, attributeFilter: ["src"] }); GM_log("👀 已开始监听验证码图片变化..."); } else { GM_log("❌ 无法监听验证码图片,未找到元素"); } } // 监听验证码图片的点击事件 function addClickListener() { let img = document.getElementById(CAPTCHA_IMAGE_ID); if (img) { img.addEventListener("click", () => { GM_log("🔄 点击验证码图片,重新识别..."); setTimeout(recognizeCaptcha, 1000); }); } else { GM_log("❌ 无法添加点击事件,验证码图片未找到"); } } // 创建一个手动触发识别的按钮 function addManualButton() { let button = document.createElement("button"); button.innerText = "🔍 识别验证码"; button.style.position = "fixed"; button.style.top = "10px"; button.style.right = "10px"; button.style.padding = "8px 12px"; button.style.fontSize = "14px"; button.style.background = "#28a745"; button.style.color = "white"; button.style.border = "none"; button.style.borderRadius = "5px"; button.style.cursor = "pointer"; button.style.zIndex = "9999"; button.addEventListener("click", recognizeCaptcha); document.body.appendChild(button); GM_log("✅ 手动识别按钮已添加"); } // 页面加载后执行 window.onload = function () { setTimeout(() => { recognizeCaptcha(); // 初次识别 addClickListener(); // 点击验证码重新识别 observeCaptchaChange(); // 监听验证码刷新 addManualButton(); // 添加手动按钮 }, 1000); }; })();
使用方法
-
安装 FastAPI 服务器
pip install fastapi uvicorn ddddocr python server.py # 运行 FastAPI 服务器
-
安装油猴脚本
- 安装 Tampermonkey 插件
-
新建脚本
-
复制油猴代码并保存
-
打开网页,自动识别验证码
- 根据网站修改脚本18、19行中的验证码图片 ID和验证码输入框 ID
const CAPTCHA_IMAGE_ID = "verifyCode"; // 验证码图片 ID
const CAPTCHA_INPUT_ID = "captcha"; // 验证码输入框 ID
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
暂无评论内容