From 4553725ee934a3a53081c4a5c839d3cf574a3b0c Mon Sep 17 00:00:00 2001 From: Shijh <838239178@qq.com> Date: Fri, 17 Jun 2022 20:52:10 +0800 Subject: [PATCH 1/2] 1.3.0 --- docker-compose.yml | 4 ---- ocr_module/util.py | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 ocr_module/util.py diff --git a/docker-compose.yml b/docker-compose.yml index 4926446..0871465 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,8 +16,4 @@ services: # success, fail, both - sendMode= - extUsers= -<<<<<<< HEAD - TZ=Asia/Shanghai -======= - - TZ=Asia/Shanghai ->>>>>>> 5b038aa82f3f89ea1b4a519c036d35da2d12881c diff --git a/ocr_module/util.py b/ocr_module/util.py new file mode 100644 index 0000000..782a7cd --- /dev/null +++ b/ocr_module/util.py @@ -0,0 +1,43 @@ +from datetime import datetime +import importlib +import logging +import base64 +import time + +from exception.exceptions import KnownException + +ocr_util = None + +def init_ocr(ocr_type: str, ak: str, sk: str): + global ocr_util + if ocr_type is None or ocr_type == '': + ocr_type = "baidu_image" + try: + ocr_util = importlib.import_module( + f"ocr_module.{ocr_type}.{ocr_type}_ocr") + except ModuleNotFoundError: + raise KnownException("ocr类型不存在,请更换类型") + + if ocr_util.is_need_keys(): + ocr_util.set_keys(ak, sk) + logging.info(f"使用 OCR {ocr_type}") + +def get_validate_code(sess) -> str: + max_try = 5 + has_try = 0 + while has_try < max_try: + resp = sess.get( + url=f"https://m.fjcyl.com/validateCode?0.{datetime.microsecond}&width=58&height=19&num=4") + try: + # noinspection PyUnresolvedReferences + res = ocr_util.get_result(base64.b64encode(resp.content)) + logging.info('获取验证码成功') + return res + except Exception as e: + logging.warning(f'获取验证码失败,原因:{e}') + logging.warning(f'正在重试, 次数:{has_try}') + has_try += 1 + time.sleep(1) + + if has_try == max_try: + raise KnownException("验证码解析失败,请尝试更换方式或发issue寻求帮助") \ No newline at end of file From 23192365af9c080e19aed03b85d63ca74a58abf1 Mon Sep 17 00:00:00 2001 From: Shijh <838239178@qq.com> Date: Fri, 17 Jun 2022 20:53:57 +0800 Subject: [PATCH 2/2] fix(login):fix login error, add validation code ocr --- README.md | 44 +++++++++++++++++++++++++++++++----------- config.json.bak | 5 +++++ main.py | 28 +++++++++++++++++++++------ ocr_module/__init__.py | 6 ++++++ 4 files changed, 66 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 034d795..915472b 100644 --- a/README.md +++ b/README.md @@ -4,25 +4,25 @@ [此处展示最近更新日志,完整日志搓这里](./doc/Log.md) -> 2022.03.26: 感谢 @miscdec 对开源库的贡献,现在添加了push_plus推送渠道,并修复了一些异常。 -> -> 2022.03.27: 代理池极不稳定 -> > 2022.03.30: 感谢 @Dark-Existed 贡献了Docker部署脚本,请使用环境变量配置相关参数 > > 2022.05.11: 不使用代理IP的场景可使用Python3.7版本 +> +> 2022.06.03:针对未知打卡失败的情况添加重试措施 +> +> 2022.06.17:⚠ **重要:验证码检测回归**,现在需要验证码识别技术,请使用`1.3.0`及以上版本。⚠ 🤺妈妈再也不用担心我团课没看被团支书赶着催了 ### 点个:star:再走吧,❤感谢大家的Star和Fork,有问题可以发issue -**仅供福建共青团团员学习交流使用** - -~~浙江团员可以点击这里[青春浙江](https://gist.github.com/838239178/ddad90e8c5e52f5fa8f0febea6109f24)~~ +**仅供福建共青团团员学习交流使用** 项目遵循GPL协议,请勿拿来盈利、诈骗和违法之事!否则后果需要自负。 ### 参与贡献! -:pen: 如果你有新的或更好消息推送方式 请参考 [消息推送贡献文档](./doc/send_module_rule.md) 做出你的贡献! +🖊️ 如果你有新的或更好OCR识别方式 请参考 [OCR贡献文档](https://github.com/838239178/tk-auto-study/blob/1.2.5/doc/OCR_Module_Rule.md) 做出你的贡献! + +🖊️ 如果你有新的或更好消息推送方式 请参考 [消息推送贡献文档](https://github.com/838239178/tk-auto-study/blob/1.2.5/doc/send_module_rule.md) 做出你的贡献! ## 使用方法 @@ -32,6 +32,16 @@ A7E74D2B6282AEB1C5EA3C28D25660A7 ``` +#### 申请Ocr识别接口的权限 + +[详细教程请点击这里](https://blog.pressed.top/2021/02/14/signUpBaiduOcr/) + +*请选择使用一种可以识别文字的api,建议使用BaiduAI的Ocr接口* + +- 首先要有一个百度账号,进入[这个网址](https://ai.baidu.com/),点击控制台并登录 +- 完成个人实名认证,申请文字识别的使用权 +- 点击管理应用,点击创建应用,按要求填一些信息,创建完成后记住**API KEY**和**SECRET KEY** + #### 部署在平台上定时执行 这里介绍如何在GitHubActions中运行,因代理IP的相关代码,需确保**Python3.9**及以上版本。 @@ -40,8 +50,10 @@ A7E74D2B6282AEB1C5EA3C28D25660A7 - 添加三个secrets,分别为:username, pwd, pub_key +- `1.3.0`开始,需要添加验证码识别的OCR的 api_key,secret_key,ocr_type + - 将[该文件](./.github/workflows/run.yml)中的`#`删除并修改cron为你想要触发的时间,默认是每周三14点运行一次,cron如何写请自行百度 - + ![image](https://user-images.githubusercontent.com/55338151/161259594-21812419-25e3-4b1f-b64f-e06b826351b8.png) - 进入 Actions 中手动触发一次(点击auto-study 右边 Run workflow),测试是否成功 @@ -77,7 +89,7 @@ crontab -e # 将下面这行复制到里面,cd的路径按照需要更改 00 08 * * 3 cd /root/tk-auto-study && python3 main.py >> crontab.log 2>&1 # 或者 -00 08 * * python3 /root/tk-auto-study/main.py >> crontab.log 2>&1 +00 08 * * 3 python3 /root/tk-auto-study/main.py >> crontab.log 2>&1 ``` 使用 `crontab -l` 查看是否修改成功 @@ -90,6 +102,16 @@ crontab -e docker-compose up -d ``` +## 可选识别类型 + +> `1.3.0` + +GithubAction(可选)添加新的secrets OCR_TYPE 来指定识别类型 + +其他方式在config.json中修改指定配置项即可 + +- baidu_image [默认方法,需要到百度AI中申请](https://blog.pressed.top/2021/02/14/signUpBaiduOcr/) + ## 可选消息推送 > 仅 `1.2.2` 版本及以上可用 @@ -137,5 +159,5 @@ GithubAction用户可通过添加secrets:send_type, send_key, send_mode 来使 ## 赏我一杯Coffee -![qq_pic_merged_1633171137809](https://cdn.jsdelivr.net/gh/838239178/PicgoBed/img/68747470733a2f2f63646e2e6a7364656c6976722e6e65742f67682f3833383233393137382f506963676f4265642f696d672f313633333137313136342e6a7067.jpg)![qq_pic_merged_1633171137809](https://cdn.jsdelivr.net/gh/838239178/PicgoBed/img/qq_pic_merged_1633171137809.jpg) +![qq_pic_merged_1633171137809](https://cdn.jsdelivr.net/gh/838239178/PicgoBed/img/qq_pic_merged_1633171137809.jpg) diff --git a/config.json.bak b/config.json.bak index 715e312..df9c8ba 100644 --- a/config.json.bak +++ b/config.json.bak @@ -9,6 +9,11 @@ "key": "填写server酱或其他的SendKey", "mode": "默认fail(fail/success/both)" }, + "ocr": { + "sk": "填写API KEY", + "ak": "填写SECRET KEY", + "type": "baidu_image" + }, "extUsers": [ { "username": "", diff --git a/main.py b/main.py index 57e7320..5c29f9e 100644 --- a/main.py +++ b/main.py @@ -9,6 +9,7 @@ import urllib3 from exception import KnownException, SendInitException +from ocr_module import util as ocrutil # 处理https警告 urllib3.disable_warnings() @@ -90,10 +91,11 @@ def post_study_record(): error_raise(f"学习失败,{errmsg}") -def post_login(username: str, pwd: str, pub_key): +def post_login(username: str, pwd: str, pub_key: str, code: str): post_dict = { 'userName': encryptor.encrypt(username, pub_key), - 'pwd': encryptor.encrypt(pwd, pub_key) + 'pwd': encryptor.encrypt(pwd, pub_key), + 'validateCode': encryptor.encrypt(code, pub_key) } resp = sess.post(url="https://m.fjcyl.com/mobileNologin", @@ -115,6 +117,10 @@ def get_profile_from_config(): pwd = config_json.get('pwd') pub_key = config_json.get('rsaKey').get('public') + api_key = config_json.get('ocr').get('ak') + secret_key = config_json.get('ocr').get('sk') + ocr_type = config_json.get('ocr').get('type') + send_config = config_json.get('send') accounts = config_json.get("extUsers") if send_config is not None: @@ -122,7 +128,7 @@ def get_profile_from_config(): send_key = send_config.get('key') send_mode = send_config.get('mode') return username, pwd, pub_key, \ - send_type, send_key, send_mode, accounts + send_type, send_key, send_mode, accounts, api_key, secret_key, ocr_type def get_profile_from_env(): @@ -134,6 +140,11 @@ def get_profile_from_env(): send_mode = os.environ['sendMode'] ext_users = os.environ['extUsers'] accounts = [] + + api_key = os.environ['ocrKey'] + secret_key = os.environ['ocrSecret'] + ocr_type = os.environ['ocrType'] + if ext_users is not None and ext_users.__len__() > 1: for userLine in ext_users.split('\n'): usr_split = userLine.split(" ") @@ -147,16 +158,17 @@ def get_profile_from_env(): account['pwd'] = usr_split[1] accounts.append(account) return username, pwd, pub_key, \ - send_type, send_key, send_mode, accounts + send_type, send_key, send_mode, accounts, api_key, secret_key, ocr_type def login(username, pwd, pub_key): has_try = 0 logging.info(f"正在登录尾号{username[-4:]}") + code = ocrutil.get_validate_code(sess) while has_try < MAX_TRY: # do login try: - post_login(username, pwd, pub_key) + post_login(username, pwd, pub_key, code) break except ConnectionError as e: logging.error(f'尾号{username[-4:]}登录失败,原因:{e}') @@ -237,9 +249,13 @@ def run(use_config: bool, use_proxy: bool = False): # get default config username, pwd, pub_key, \ send_type, send_key, send_mode, \ - accounts = get_profile_from_config() if use_config else get_profile_from_env() + accounts, \ + api_key, secret_key, ocr_type = get_profile_from_config( + ) if use_config else get_profile_from_env() # init sender init_sender(send_type, send_key, send_mode) + # init ocr + ocrutil.init_ocr(ocr_type, api_key, secret_key) # init proxy if use_proxy: init_proxy() diff --git a/ocr_module/__init__.py b/ocr_module/__init__.py index e69de29..440ad5e 100644 --- a/ocr_module/__init__.py +++ b/ocr_module/__init__.py @@ -0,0 +1,6 @@ +from . import util + + +__all__ = [ + "util" +]