#!/usr/bin/env python3 """单图验证码识别,走 pie-xian command-a-vision。输出格式兼容 harness 的 recognize()。 用法: vision_ocr.py file.png ... -> {"file.png": {"vision": "code"}} """ import base64 import json import re import ssl import sys import urllib.request API = "https://api.pie-xian.com/v1/chat/completions" KEY = "sk-Rel8iERHrmu9NDbvQhnhwTowEUnGqVvCFXMatASH8q5O4gGP" MODEL = "command-a-vision-07-2025" UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36" PROMPT = "识别这张验证码图片中的字符。只输出字符本身,不要任何解释或标点。这是登录验证码,可能包含1-4个数字。" _CTX = ssl.create_default_context() _CTX.check_hostname = False _CTX.verify_mode = ssl.CERT_NONE def read(path): b64 = base64.b64encode(open(path, "rb").read()).decode() body = json.dumps({"model": MODEL, "messages": [{"role": "user", "content": [ {"type": "text", "text": PROMPT}, {"type": "image_url", "image_url": {"url": "data:image/png;base64," + b64}}]}], "max_tokens": 20, "temperature": 0}).encode() req = urllib.request.Request(API, data=body, headers={ "Authorization": "Bearer " + KEY, "Content-Type": "application/json", "User-Agent": UA}) d = json.loads(urllib.request.urlopen(req, timeout=90, context=_CTX).read()) return re.sub(r"[^0-9A-Za-z]", "", d["choices"][0]["message"]["content"]) def main(): out = {} for f in sys.argv[1:]: try: # 2 次读取,一致才返回;不一致返回空(harness 跳过登录) r1, r2 = read(f), read(f) code = r1 if r1 == r2 else "" out[f] = {"vision": code} except Exception as e: out[f] = {"vision": "", "err": str(e)} print(json.dumps(out, ensure_ascii=False)) if __name__ == "__main__": main()