├── img.png ├── README.md ├── get_encrypt.js └── baidu_ocr.py /img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intAV/BaiduRotate_ocr/HEAD/img.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 百度旋转验证码识别 || 纯接口无界面操作 2 | ## 使用第三方模型识别:[121.4.108.95:8000](http://121.4.108.95:8000/index/?type=%E6%97%8B%E8%BD%AC(%E7%99%BE%E5%BA%A6%E8%B4%B4%E5%90%A7)) 3 | ## ![image](https://user-images.githubusercontent.com/38396198/219425370-3355a623-2946-4d9c-b207-4a1094694fe0.png) 4 | #### 识别成功率还是挺高的 5 | -------------------------------------------------------------------------------- /get_encrypt.js: -------------------------------------------------------------------------------- 1 | var CryptoJS = require('crypto-js'); 2 | 3 | function encrypt_(angle, as, backstr) { 4 | var tt = { 5 | "cl": [ 6 | { 7 | "x": 862, 8 | "y": 287, 9 | "t": 1657760616916 10 | } 11 | ], 12 | "mv": [ 13 | { 14 | "fx": 987, 15 | "fy": 149, 16 | "t": 1657760613905, 17 | "bf": 2 18 | }, 19 | { 20 | "fx": 979, 21 | "fy": 370, 22 | "t": 1657760615529, 23 | "bf": 2 24 | }, 25 | { 26 | "fx": 948, 27 | "fy": 339, 28 | "t": 1657760615688, 29 | "bf": 2 30 | }, 31 | { 32 | "fx": 911, 33 | "fy": 321, 34 | "t": 1657760615848, 35 | "bf": 2 36 | }, 37 | { 38 | "fx": 892, 39 | "fy": 309, 40 | "t": 1657760616008, 41 | "bf": 2 42 | }, 43 | { 44 | "fx": 880, 45 | "fy": 299, 46 | "t": 1657760616176, 47 | "bf": 2 48 | }, 49 | { 50 | "fx": 869, 51 | "fy": 290, 52 | "t": 1657760616440, 53 | "bf": 2 54 | }, 55 | { 56 | "fx": 864, 57 | "fy": 288, 58 | "t": 1657760616641, 59 | "bf": 2 60 | }, 61 | { 62 | "fx": 862, 63 | "fy": 287, 64 | "t": 1657760616866, 65 | "bf": 2 66 | }, 67 | { 68 | "fx": 864, 69 | "fy": 288, 70 | "t": 1657760617026, 71 | "bf": 1 72 | }, 73 | { 74 | "fx": 877, 75 | "fy": 293, 76 | "t": 1657760617186, 77 | "bf": 1 78 | }, 79 | { 80 | "fx": 882, 81 | "fy": 295, 82 | "t": 1657760617360, 83 | "bf": 1 84 | }, 85 | { 86 | "fx": 891, 87 | "fy": 298, 88 | "t": 1657760617537, 89 | "bf": 1 90 | }, 91 | { 92 | "fx": 900, 93 | "fy": 300, 94 | "t": 1657760617688, 95 | "bf": 1 96 | }, 97 | { 98 | "fx": 908, 99 | "fy": 301, 100 | "t": 1657760617864, 101 | "bf": 1 102 | }, 103 | { 104 | "fx": 910, 105 | "fy": 301, 106 | "t": 1657760618585, 107 | "bf": 1 108 | } 109 | ], 110 | "sc": [], 111 | "kb": [ 112 | { 113 | "key": "a", 114 | "t": 1657760606047 115 | } 116 | ], 117 | "sb": [], 118 | "sd": [], 119 | "sm": [], 120 | "cr": { 121 | "screenTop": 0, 122 | "screenLeft": 0, 123 | "clientWidth": 1920, 124 | "clientHeight": 979, 125 | "screenWidth": 1920, 126 | "screenHeight": 1080, 127 | "availWidth": 1920, 128 | "availHeight": 1050, 129 | "outerWidth": 1920, 130 | "outerHeight": 1050, 131 | "scrollWidth": 1920, 132 | "scrollHeight": 1920 133 | }, 134 | "simu": 0, 135 | "ac_c": (angle * 212 / 360 / 212).toFixed(2), 136 | "backstr": backstr 137 | }; 138 | var t = as + 'appsapi0' 139 | , n = CryptoJS.enc.Utf8.parse(t) 140 | , i = CryptoJS.enc.Utf8.parse(JSON.stringify(tt)) 141 | , r = CryptoJS.AES.encrypt(i, n, { 142 | mode: CryptoJS.mode.ECB, 143 | padding: CryptoJS.pad.Pkcs7 144 | }); 145 | return [r.toString(), tt['ac_c']]; 146 | } 147 | 148 | function add(x,y) { 149 | return x+y; 150 | } 151 | 152 | //console.log(encrypt_('175','77af72b4','3665-Px4DcLoit3uVe824uBkHUhYlQRP9J1snLUo3oUo4NCni3QAeNyHrm3CQYE1d0+bG4z2Vv/PQXdv1Qp9j+bImhNo+yvQeYZjOGBVq/fJYQARPO+z357jr0N2VdtJR6PLV/ZF/4vWSekHq0V0F9PvNX4E9FL+bBVTtveoWXlDB3zxsr30wdtMey7lw/HDDDKm05KTU72MoN+B2g6pXkXJLfwXeK557yhbIgeqaUUxYRgI46RjrwoF1Em3LISq+4Ke5TIyH89awQ6ups+DSlxyJZbU/WxmL6wSrpxmVpQ0rYrwgtgO8yAPCE2myWZ7uQnMkWTnNNBThHZHALC3YA4xWkA==')) 153 | -------------------------------------------------------------------------------- /baidu_ocr.py: -------------------------------------------------------------------------------- 1 | from urllib.parse import unquote 2 | import requests 3 | import execjs 4 | import time 5 | import json 6 | import re 7 | import urllib3 8 | import base64 9 | 10 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) 11 | 12 | 13 | class BaiduRotate: 14 | 15 | def __init__(self): 16 | self.session = requests.session() 17 | self.headers = { 18 | 'Accept': 'text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, ' 19 | '*/*; q=0.01', 20 | 'Accept-Language': 'zh-CN,zh;q=0.9', 21 | 'Connection': 'keep-alive', 22 | 'Sec-Fetch-Dest': 'empty', 23 | 'Sec-Fetch-Mode': 'cors', 24 | 'Sec-Fetch-Site': 'same-origin', 25 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) ' 26 | 'Chrome/103.0.0.0 Safari/537.36', 27 | 'X-Requested-With': 'XMLHttpRequest', 28 | 'Referer': 'https://wappass.baidu.com/static/captcha/tuxing.html?ak=2ef521ec36290baed33d66de9b16f625&backurl=http%3A%2F%2Ftieba.baidu.com%2Ff%3Fkw%3D%25E5%25A9%259A%25E5%25A7%25BB%26ie%3Dutf-8%26pn%3D3900×tamp=1676562481&signature=db40e5143d0645f18009524380a49b8e', 29 | 'sec-ch-ua': '".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"', 30 | 'sec-ch-ua-mobile': '?0', 31 | 'sec-ch-ua-platform': '"Windows"', 32 | } 33 | 34 | def get_image_request_data(self): 35 | """ 36 | :return: 获取需要获取图片的参数 37 | """ 38 | url = "https://wappass.baidu.com/viewlog" 39 | params = { 40 | "callback": "jQuery110205449684422426735_" + str(int(time.time() * 1000)), 41 | "ak": "2ef521ec36290baed33d66de9b16f625", 42 | "_": str(int(time.time() * 1000)) 43 | } 44 | response = self.session.get(url, headers=self.headers, params=params) 45 | res_data = re.findall(r'.*?(\{.*?})\)', response.text)[0] 46 | res_data = json.loads(res_data) 47 | item = { 48 | "tk": res_data['data']['tk'], 49 | "as": res_data['data']['as'], 50 | "ds": res_data['data']['ds'] 51 | } 52 | #print(item) 53 | return item 54 | 55 | #获取图片url地址 56 | def get_img(self, item): 57 | url = "https://wappass.baidu.com/viewlog/getstyle" 58 | params = { 59 | "callback": "jQuery110205449684422426735_" + str(time.time() * 1000), 60 | "ak": '2ef521ec36290baed33d66de9b16f625', 61 | "tk": item["tk"], 62 | "isios": "0", 63 | "type": "spin", 64 | "_": str(time.time() * 1000) 65 | } 66 | response = self.session.get(url, headers=self.headers, params=params) 67 | ret_data = re.findall(r'.*?(\{.*?})\)', response.text)[0] 68 | ret_data = json.loads(ret_data) 69 | item_img = { 70 | "img_url": unquote(ret_data['data']['ext']['img']), 71 | "backstr": ret_data['data']['backstr'], 72 | "tk": item["tk"], 73 | "as": item["as"] 74 | } 75 | response = self.session.get(item_img['img_url'], verify=False) 76 | with open('img.png', 'wb')as f: 77 | f.write(response.content) 78 | return item_img 79 | 80 | # 图片旋转度数--关键 81 | def fun_get_angle(self,img_url): 82 | # print(img_url) 83 | res = requests.get(url=img_url) 84 | headers = { 85 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36", 86 | "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", 87 | } 88 | data = { 89 | "img": base64.b64encode(res.content).decode("utf-8"), 90 | "project_name": "旋转(百度贴吧)", 91 | "show": "True", 92 | } 93 | try: 94 | text = requests.post(url="http://121.4.108.95:8000/%E6%B5%8B%E8%AF%95/", data=data, headers=headers, 95 | timeout=5) 96 | except: 97 | print("远程识别验证码失败! url:http://121.4.108.95:8000/") 98 | return 0 99 | detail = json.loads(text.text).get('detail') 100 | print("旋转度数:", detail) 101 | return detail 102 | 103 | 104 | def verify_data(self, item): 105 | url = "https://wappass.baidu.com/viewlog" 106 | print("angle:", item['angle']) 107 | print("as:", item['as']) 108 | with open('get_encrypt.js', 'r', encoding='utf-8') as f: 109 | js_text = f.read() 110 | #print(js_text) 111 | fs = execjs.compile(js_text).call('encrypt_', str(item['angle']), str(item['as']), str(item['backstr'])) 112 | #print("fs:", fs) 113 | params = { 114 | "callback": "jQuery110204100787474351779_" + str(time.time() * 1000), 115 | "ak": "2ef521ec36290baed33d66de9b16f625", 116 | "as": item['as'], 117 | "fs": fs[0], 118 | "tk": item['tk'], 119 | "cv": "submit", 120 | "_": str(time.time() * 1000) 121 | } 122 | response = self.session.get(url, headers=self.headers, params=params) 123 | print(response.headers.get("cookies")) 124 | ret_data = re.findall(r'.*?(\{.*?})\)', response.text)[0] 125 | ret_data = json.loads(ret_data) 126 | print("验证结果:", ret_data) 127 | return ret_data 128 | 129 | 130 | 131 | 132 | 133 | 134 | if __name__ == '__main__': 135 | item = BaiduRotate().get_image_request_data() 136 | item_img = BaiduRotate().get_img(item) 137 | angle = BaiduRotate().fun_get_angle(item_img.get('img_url')) 138 | item_img['angle'] = angle 139 | #print(item_img) 140 | ret_data = BaiduRotate().verify_data(item_img) 141 | #print(ret_data) 142 | if 1 == ret_data['data']['op']: 143 | print("验证通过...") 144 | else: 145 | print("验证未通过...") 146 | --------------------------------------------------------------------------------