Skip to content

Commit

Permalink
Merge pull request tianzhengs#8 from startkkkkkk/dev
Browse files Browse the repository at this point in the history
Multi-Account Support Fix
  • Loading branch information
tianzhengs authored Dec 16, 2021
2 parents d3ce3b6 + a38c7c8 commit 3f06681
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 106 deletions.
125 changes: 36 additions & 89 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,99 +1,46 @@
import json
import os
import re
import time
import traceback

import requests
from study import study

from utility import encrypt, cap_recognize

username = os.environ["USERNAME"]
password = os.environ["PASSWORD"]
def getAccounts():
result = []

if not (username and password):
raise Exception("请设置Secret: USERNAME和PASSWORD")
usernameRaw = os.getenv("USERNAME", "")
if len(usernameRaw.split('\n'))==1:
# Single User
passwd = os.environ["PASSWORD"]
if usernameRaw and passwd:
result.append((usernameRaw, passwd, os.getenv("ORGID", "172442")))
else:
# Multiple Users
account_lines = usernameRaw.split('\n')
for lnum, line in enumerate(account_lines):
if len(line.split(' ')) != 3:
raise Exception(f"第{lnum}行账号格式错误")
result.append(line.split(' '))

if not result:
raise Exception("没有被配置的账号!请设置Secret: USERNAME和PASSWORD")
return result

try:
org_id = str(int(os.environ["ORGID"])) # check type
except:
org_id = '172442'

url = ''
ua = os.getenv('UA',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36 Edg/80.0.361.111')
try_time = 0
while try_time < 4:
try:
bjySession = requests.session()
bjySession.timeout = 5 # set session timeout
bjySession.headers.update({"User-Agent": ua, })
touch = bjySession.get(url="https://m.bjyouth.net/site/login")
cap_url = "https://m.bjyouth.net" + re.findall(
r'src="/site/captcha.+" alt=', touch.text)[0][5:-6]
cap_text = cap_recognize(bjySession.get(url=cap_url).content)
print(f'验证码识别: {cap_text}')
_csrf_mobile = bjySession.cookies.get_dict()['_csrf_mobile']
login_password = encrypt(password)
login_username = encrypt(username)
login_r = bjySession.post('https://m.bjyouth.net/site/login',
data={
'_csrf_mobile': _csrf_mobile,
'Login[username]': login_username,
'Login[password]': login_password,
'Login[verifyCode]': cap_text
})
print(f'Login:[{login_r.status_code}]{login_r.text}')
if login_r.text == '8':
print('Login:识别的验证码错误')
continue
if 'fail' in login_r.text:
try_time += 9
raise Exception('Login:账号密码错误')
r = json.loads(bjySession.get("https://m.bjyouth.net/dxx/index").text)
if 'newCourse' not in r:
print(r)
url = r['newCourse']['url']
title = r['newCourse']['title']
course_id = r['newCourse']['id']
break
except:
time.sleep(3)
try_time += 1
print(traceback.format_exc())

if not url:
print('Fail in login, terminating...')
exit(1)

r2 = bjySession.get('https://m.bjyouth.net/dxx/my-integral?type=2&page=1&limit=15')
have_learned = json.loads(r2.text)
if f"学习课程:《{title}》" in list(map(lambda x: x['text'], have_learned['data'])):
print(f'{title} 在运行前已完成')
exit(0)

pattern = re.compile(r'https://h5.cyol.com/special/daxuexi/(\w+)/m.html\?t=1&z=201')
result = pattern.search(url)
if not result:
print(f'Url pattern not matched: {url}')
exit(1)

end_img_url = f'https://h5.cyol.com/special/daxuexi/{result.group(1)}/images/end.jpg'
study_url = f"https://m.bjyouth.net/dxx/check?id={course_id}&org_id={org_id}"

r = bjySession.get(study_url)
if r.text:
print(
f'Unexpected response: {r.text}'
)
exit(1)

r = bjySession.get('https://m.bjyouth.net/dxx/my-integral?type=2&page=1&limit=15')
have_learned = json.loads(r.text)
if f"学习课程:《{title}》" in list(map(lambda x: x['text'], have_learned['data'])):
print(f'{title} 成功完成学习')
exit(0)
else:
print(f'完成{title}, 但未在检查中确认 {f"学习课程:《{title}》"}' not in {
list(map(lambda x: x['text'], have_learned['data']))})
exit(1)
accounts = getAccounts()
print(f'账号数量:{len(accounts)}')
successful = 0
failed = 0
count = 0
for username, password, org_id in accounts:
count+= 1
print(f'--User {count}--')
if study(username, password, org_id, ua):
successful += 1
else:
failed += 1

print(f'成功:{successful},失败:{failed}')
if failed != 0:
raise Exception(f'有{failed}个失败!')
36 changes: 19 additions & 17 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,34 @@
# 北京青年大学习
基于Github Action运行,简洁版本

基于GitHub Action运行,简洁版本

在运行时获取最新一集,如未学习进行学习,已学习则结束

建议配置运行频率一周2次(默认为3天一次),没有成功会出错,默认配置下Github会向邮箱推送,所以没有推送功能
建议配置运行频率一周2次(默认为3天一次),没有成功会出错,默认配置下GitHub会向邮箱推送,所以没有推送功能

更新:优化了验证码识别和验证码失败的反馈
更新:多账号支持


# How to use
1. Fork (+ Star)
2. 填写以下SECRET (名称均为大写):

​ (账号密码为登录青春北京的信息,可以在[这里](https://m.bjyouth.net/site/login)测试登录信息)

| Name | Description |
| -------- | -------- |
| USERNAME | 账号(必须) |
| PASSWORD | 密码(必须) |
| ORGID | 组织ID(可选,默认为172442,北京海淀区团委) |
1. Fork (+ Star)
2. 填写以下SECRET (名称均为大写)

[如何添加SECRET](https://docs.github.com/cn/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository)
(账号密码为登录青春北京的信息,可以在[这里](https://m.bjyouth.net/site/login)测试登录信息,[如何添加SECRET](https://docs.github.com/cn/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository))

3. 在Actions界面**手动启用(默认被禁用)** Workflows,**DaXueXi** 自动跟随本分支更新(以希望在有变化时不用再手动fetch upstream),如有安全顾虑**或需要修改**等可选择没有自动更新的 **DaXueXi (No update)**
4. (可以手动运行一次试验),可以在Run python中看到打印的结果信息
​ 方法1:单用户

# 其他
| Name | Description |
| -------- | :----------------------------------------: |
| USERNAME | 账号(必须) |
| PASSWORD | 密码(必须) |
| ORGID | 组织ID(可选,默认为172442,北京海淀区团委) |

​ 方法2:支持多用户

感谢[ouyen/qndxx-beijing](https://github.com/ouyen/qndxx-beijing)
| Name | Description |
| ------- | ---------------------------------------------------------- |
| ACCOUNT | 账号(必须): 每一行为 ***账号 密码 组织ID*** 中间由空格隔开 |

3. 在Actions界面**手动启用(默认被禁用)** Workflows,**DaXueXi** 自动跟随本分支更新(以希望在有变化时不用再手动fetch upstream),如有安全顾虑**或需要修改**等可选择没有自动更新的 **DaXueXi (No update)**
4. (可以手动运行一次试验),可以在Run python中看到打印的结果信息
82 changes: 82 additions & 0 deletions study.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import json
import re
import time
import traceback

import requests

from utility import encrypt, cap_recognize


def study(username, password, org_id, ua):
# return 1:success;0:fail
url = ''
try_time = 0
while try_time < 4:
try:
bjySession = requests.session()
bjySession.timeout = 5 # set session timeout
bjySession.headers.update({"User-Agent": ua, })
touch = bjySession.get(url="https://m.bjyouth.net/site/login")
cap_url = "https://m.bjyouth.net" + re.findall(
r'src="(/site/captcha.+)" alt=', touch.text)[0]
cap_text = cap_recognize(bjySession.get(url=cap_url).content)
# print(f'验证码识别: {cap_text}')
login_r = bjySession.post('https://m.bjyouth.net/site/login',
data={
'_csrf_mobile': bjySession.cookies.get_dict()['_csrf_mobile'],
'Login[password]': encrypt(password),
'Login[username]': encrypt(username),
'Login[verifyCode]': cap_text
})
print(f'Login:[{login_r.status_code}]{login_r.text}')
if login_r.text == '8':
print('Login:识别的验证码错误')
continue
if 'fail' in login_r.text:
try_time += 9
raise Exception('Login:账号密码错误')
r = json.loads(bjySession.get("https://m.bjyouth.net/dxx/index").text)
if 'newCourse' not in r:
print(r)
url = r['newCourse']['url']
title = r['newCourse']['title']
course_id = r['newCourse']['id']
break
except:
time.sleep(3)
try_time += 1
print(traceback.format_exc())

if not url:
print('登陆失败,退出')
return 0

r2 = bjySession.get('https://m.bjyouth.net/dxx/my-integral?type=2&page=1&limit=15')
have_learned = json.loads(r2.text)
if f"学习课程:《{title}》" in list(map(lambda x: x['text'], have_learned['data'])):
print(f'{title} 在运行前已完成,退出')
return 1

pattern = re.compile(r'https://h5.cyol.com/special/daxuexi/(\w+)/m.html\?t=1&z=201')
result = pattern.search(url)
if not result:
print(f'Url pattern not matched: {url}')
return 0

end_img_url = f'https://h5.cyol.com/special/daxuexi/{result.group(1)}/images/end.jpg'
study_url = f"https://m.bjyouth.net/dxx/check?id={course_id}&org_id={org_id}"

r = bjySession.get(study_url)
if r.text:
print(f'Unexpected response: {r.text}')
return 0

r = bjySession.get('https://m.bjyouth.net/dxx/my-integral?type=2&page=1&limit=15')
have_learned = json.loads(r.text)
if f"学习课程:《{title}》" in list(map(lambda x: x['text'], have_learned['data'])):
print(f'{title} 成功完成学习')
return 1
else:
print(f'完成{title}, 但未在检查中确认')
return 0

0 comments on commit 3f06681

Please sign in to comment.