此文由 Mix Space 同步更新至 xLog
為獲得最佳瀏覽體驗,建議訪問原始鏈接
https://www.do1e.cn/posts/code/nju-captcha
前言#
之前寫的 NJUlogin 中帳號密碼登錄需要進行驗證碼識別,當時採用了 ddddocr 並且有了不錯的精度。
同時也部署了一個服務端並找朋友幫忙寫了一個油猴腳本,讓我在每次需要登錄時自動填充驗證碼(帳號密碼瀏覽器會自動填充),因此只需要點擊登錄即可。
不過最近想着想把識別模型做得更加輕量一些,更方便邊緣端部署,於是有了這個項目。(求個 Star 好嗎 >︿<,如果你只想使用,並不想了解相關技術,直接拉到最後,推薦 NJU server api 版本)
數據採集#
https://github.com/Do1e/NJUcaptcha/tree/main/build_dataset
數據集集構建基本上是自動化進行的,主要依賴以下兩個工具:
稍微魔改了一下 NJUlogin 判斷識別的正確與否,然後分別保存到不同的文件夾下,識別錯誤(大概幾百張?)的手動重命名一下即可。
為了採集者 100,000 張圖片,在後台跑了大概 3~4 天,time.sleep
還不能太小,不然會封 IP。 >︿<
於是有了這個數據集,歡迎下載使用,包含 100,000 張驗證碼圖片,文件命名格式為 {驗證碼文本}_{圖片md5}.jpg
,驗證碼文本均為小寫。
數據集下載鏈接:NJU-captcha-dataset.7z
解壓密碼:@Do1e
Dataset 如下:
https://github.com/Do1e/NJUcaptcha/blob/main/model/dataset.py
識別模型#
https://github.com/Do1e/NJUcaptcha/tree/main/model
有了數據之後就可以設計模型並進行訓練了。模型設計這次我完全交給了 AI 幫我完成,效果也還算 OK。
模型大小 12.98MiB -> 2.25MiB
模型精度 99.37% -> 99.83%
吞吐率 173.95 images/sec -> 1076.56 images/sec [AMD Ryzen 7 8845H]
https://github.com/Do1e/NJUcaptcha/blob/main/model/model.py
也許可以再小一點?留著下次升級吧
服務端部署#
https://github.com/Do1e/NJUcaptcha/tree/main/service
之前也使用 fastapi 簡單實現了一個識別伺服器,識別接收到的 base64 圖片並返回驗證碼的內容,這次也借著開源的機會部署到了 vercel 上。Linux 下測試命令:
curl -s -L "https://authserver.nju.edu.cn/authserver/captcha.html" -o "captcha.jpg" && [ -f "captcha.jpg" ] && curl -s -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "captcha=$(base64 -i captcha.jpg | tr -d '\n')" "https://njucaptcha.vercel.app" || { echo "Failed to download captcha image"; exit 1; }
油猴腳本自動填充#
正如前言所述,為了實現登錄時不用人工識別並輸入驗證碼,寫了油猴腳本自動填充。之前的版本為基於服務端的:
https://github.com/Do1e/NJUcaptcha/blob/main/njucaptcha.user.js
開源代碼裡用的還是 vercel 的服務,速度很慢,而且必須登錄 p.nju,而在需要登錄 p.nju 時不起作用。 ( ̄﹃ ̄)
我自己的解決方案是在校內搭建服務並通過 frp 映射到我公網的伺服器,並且在登錄 p.nju 時訪問內網服務:
const url_pub = 'https://example.com/';
const url_nju = 'https://nju.example.com/';
const currentUrl = window.location.href;
const serverUrl = currentUrl.includes('//p.nju.edu.cn') ? url_nju : url_pub;
這次整個項目最難的還是如何直接在客戶端執行 onnx 的推理,借助 AI 工具捣鼓了好幾個小時才成功搞定。使用 ONNX Runtime Web 實現。
https://github.com/Do1e/NJUcaptcha/blob/main/njucaptcha_onnx.user.js
onnx 版本的一個缺點是在沒有緩存時需要聯網並科學上網下載一些必要的推理依賴,不過還在第一次使用後能緩存(ort-wasm-simd-threaded.jsep.mjs
和 ort-wasm-simd-threaded.jsep.wasm
只能緩存 7 天,也不算太長,如果有大佬有辦法實現像 @resource
一樣的近乎永久緩存,歡迎提交 PR)。
總之上述兩種方案各有優缺點吧,最推薦的還是按照我的方式自行部署使用,或者直接使用我在文末給的 NJU server api 版本。
上述版本的油猴腳本可點擊下面的鏈接直接安裝(在已安裝油猴插件的前提下):
| | vercel api 版本 | NJU server api 版本 | onnx 本地推理版本 |
| :--- | :--- | :--- |
| 優點 | 不用科學上網 | 最佳實踐,個人認為比較完美 | 很快,頁面加載完成前就已經填充完畢,且能夠在登錄 p.nju 時使用(有緩存的前提下) |
| 缺點 | 很慢,且無法登錄 p.nju 時使用 | 需要有校內外伺服器進行部署,我畢業後將無法使用 | 無緩存需要科學上網緩存部分文件,無法登錄 p.nju 時使用,且緩存僅有 7 天 |
注:這次的代碼使用 GPL-3.0 開源協議,請忽略下述有關開源協議的說明。懶得改網頁代碼,我的網站解釋權在我沒毛病吧