import requests import feapder.setting as setting __all__ = [ "jy_ocr", "chaojiying_platform", "chaojiying_report", "get_code", "get_code_det", "arithmetic_captcha", "swordfish_platform" ] _headers = {"accept": "application/json"} def _pack_file(file): """包装验证码格式""" if isinstance(file, str) and file.startswith("data:image"): files = {"file": file} elif isinstance(file, bytes): files = {"file": file} else: with open(file, "rb") as f: img_bytes = f.read() files = {"file": img_bytes} return files def _ocr_image(url, image): files = _pack_file(image) r = requests.post(url, headers=_headers, files=files, stream=True, timeout=10) rp_json = r.json() if "msg" in rp_json and "success" == rp_json["msg"]: return str(rp_json["r"]["code"]) return None def _simple_captcha(image): """ 普通验证码 @param image: 验证码 - 图片/base64图片编码 @return: """ return _ocr_image(f"{setting.CAPTCHA_URL}/v1/images/verify", image) def _arithmetic_captcha(image): """算术验证码""" return _ocr_image(f"{setting.CAPTCHA_URL}/v1/images/arithmetic", image) def _get_click_verify_captcha(image): """点触式验证码""" url = f"{setting.CAPTCHA_URL}/v1/images/verify_det" files = _pack_file(image) r = requests.post(url, headers=_headers, files=files, stream=True, timeout=10) return r.json() def _zhipu_ocr_captcha(image, text=None): files = _pack_file(image) if not text: url = f"{setting.CAPTCHA_URL}/v1/images/verify_z" params = None else: url = f"{setting.CAPTCHA_URL}/v1/images/verify_a" params = {"text": text} r = requests.post(url, headers=_headers, params=params, files=files, stream=True, timeout=10) rp_json = r.json() if "msg" in rp_json and "success" == rp_json["msg"]: return str(rp_json["r"]["code"]) return None def jy_ocr(image, mode="simple", text=None): """剑鱼验证码识别平台""" if mode.lower() == "arithmetic": return _arithmetic_captcha(image) elif mode.lower() == "det": return _get_click_verify_captcha(image) elif mode.lower() == "zhipu": return _zhipu_ocr_captcha(image, text) else: return _simple_captcha(image) swordfish_platform = jy_ocr def chaojiying_platform(file, pic_type, spidercode=None): """ 超级鹰识别平台 pic_type,详情查询地址: https://www.chaojiying.com/price.html @param str|bytes file: 验证码图片 @param int pic_type: 验证码图片类型 @param str spidercode: 爬虫代码 """ files = _pack_file(file) url = f"{setting.CAPTCHA_URL}/v1/images/discern?pic_type={pic_type}" if spidercode is not None: url = f"{setting.CAPTCHA_URL}/v1/images/discern?pic_type={pic_type}&jy_code={spidercode}" data = { 'grant_type': '', 'username': 'jianyu001', 'password': '123qwe!A', 'scope': '', 'client_id': '', 'client_secret': '' } response = requests.post(url, headers=_headers, data=data, files=files, timeout=10) json_resp = response.json() '''code 返回0时,打码平台正常返回数据''' pic_str = json_resp["r"]["pic_str"] pic_id = json_resp["r"]["pic_id"] if 0 == json_resp["code"]: return pic_str, pic_id return None, pic_id def chaojiying_report(pic_id): """ 超级鹰平台识别验证码错误时,提交识别错误的验证码pic_id @param str pic_id: 超级鹰验证码识别图片id @return: """ url = f"{setting.CAPTCHA_URL}/v1/images/report_err?pic_id={pic_id}" headers = { 'accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' } data = { 'grant_type': '', 'username': 'jianyu001', 'password': '123qwe!A', 'scope': '', 'client_id': '', 'client_secret': '' } response = requests.post(url, headers=headers, data=data, timeout=10) ''' 回调成功:{'msg': 'OK', 'code': 0} 此接口不能随便调用!程序逻辑里要这样判断: 如果 识别结果是错的 再调用 报错返分 接口。 如果没有这个判断或是无法判断,就不要调用! ''' return response.json() def get_code(image): return jy_ocr(image) or {} def get_code_det(image): return jy_ocr(image, mode="det") def arithmetic_captcha(image): return jy_ocr(image, mode="arithmetic")