You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

208 lines
8.6 KiB
Python

import datetime
import json
import random
import requests
import time
import captcha_img
def get_timestamp():
return str(round(datetime.datetime.now().timestamp(), 3))
def parseMethodToken(test: str):
return test[test.find('methodToken=') + 12:test.find('&csComm')]
#https://mcwk.mycourse.cn/course/A22002/A22002.html?userCourseId57051d99-434f-4814-81e7-84deee2128bb\u0026tenantCode\u003d4137011066\u0026type\u003d1\u0026csComm\u003dtrue\u0026csCapt\u003dtrue
#https://mcwk.mycourse.cn/course/A22002/A22002.html?userCourseId=57051d99-434f-4814-81e7-84deee2128bb&tenantCode=4137011066&type=1&csComm=true&csCapt=true
#https://mcwk.mycourse.cn/course/A22002/A22002.html?userCourseId=57051d99-434f-4814-81e7-84deee2128bb&tenantCode=4137011066&type=1&csComm=true&csCapt=true&userProjectId=5fc7738e-f98c-4890-8ce8-d3b06d2649da&userId=eec6b514-93d6-4516-9e6a-e45cc3ce980c&courseId=dd85f614-d32f-11eb-9a88-d4ae52bad611&projectType=special&projectId=undefined&protocol=true&link=34415&weiban=weiban&userName=f61f3acc85f34ae5802675ac194a5c38
#https://weiban.mycourse.cn/#/course/detail?courseId=dd85f614-d32f-11eb-9a88-d4ae52bad611&userProjectId=5fc7738e-f98c-4890-8ce8-d3b06d2649da&courseName=%E5%8F%8D%E6%81%90%E4%B9%8B%E3%80%8A%E5%8F%8D%E6%81%90%E6%B3%95%E3%80%8B%E7%AF%87&userCourseId=57051d99-434f-4814-81e7-84deee2128bb&link=34415&projectType=special
def GetTimeStampMS():
return str(int(round(time.time() * 1000)))
class WeibanAPI:
tenantCode = ''
x_token = ' '
userId = ' '
userProjectId = ' '
headers = None
captcha_headers = None
def __init__(self, token, user_id, user_project_id, tenant_code):
self.x_token = token
self.tenantCode = tenant_code
self.userId = user_id
self.userProjectId = user_project_id
self.headers = {
'X-Token': self.x_token,
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.203'
}
self.captcha_headers = {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.203',
'Referer': 'https://mcwk.mycourse.cn/'
}
res = self._showProgress()
if len(res) == 0:
raise Exception('failed to get course info')
def showProgress(self):
res = self._showProgress()
j = json.loads(res)
return j["data"]["requiredNum"], j["data"]["requiredFinishedNum"]
def _showProgress(self):
url = 'https://weiban.mycourse.cn/pharos/project/showProgress.do?timestamp=' + get_timestamp()
data = {
'tenantCode': self.tenantCode,
'userId': self.userId,
'userProjectId': self.userProjectId
}
return self.process_url(url, data)
def _process_url(self, url, param, method):
if method == 'POST':
re = requests.post(url=url, data=param, headers=self.headers)
elif method == 'GET':
url += '?'
for key, item in param.items():
url = url + ('' if url.endswith('?') else '&') + str(key) + '=' + str(item)
re = requests.get(url=url, headers=self.headers)
else:
raise ValueError('WRONG METHOD')
return re.text
def process_url(self, url, param, method='POST'):
return self._process_url(url, param, method)
def _listCategory(self):
url = 'https://weiban.mycourse.cn/pharos/usercourse/listCategory.do?timestamp=' + get_timestamp()
data = {
'tenantCode': self.tenantCode,
'userId': self.userId,
'userProjectId': self.userProjectId,
'chooseType': 3
}
return self.process_url(url, data)
def listCategory(self):
ret = self._listCategory()
try:
j = json.loads(ret)
return j["data"]
except json.decoder.JSONDecodeError as e:
print(e.msg)
def _listCourse(self, category_code):
url = 'https://weiban.mycourse.cn/pharos/usercourse/listCourse.do?timestamp=' + get_timestamp()
data = {
'tenantCode': self.tenantCode,
'userId': self.userId,
'userProjectId': self.userProjectId,
'chooseType': 3,
'categoryCode': category_code
}
return self.process_url(url, data)
def listCourse(self, category_code):
ret = self._listCourse(category_code)
try:
j = json.loads(ret)
return j["data"]
except json.decoder.JSONDecodeError as e:
print(e.msg)
def _getCourseUrl(self, resource_id):
url = 'https://weiban.mycourse.cn/pharos/usercourse/getCourseUrl.do?timestamp=' + get_timestamp()
data = {
'tenantCode': self.tenantCode,
'userId': self.userId,
'userProjectId': self.userProjectId,
'courseId': resource_id
}
return self.process_url(url, data)
def getCourseUrl(self, resource_id):
ret = self._getCourseUrl(resource_id)
try:
j = json.loads(ret)
return j["data"]
except json.decoder.JSONDecodeError as e:
print(e.msg)
def methodToken(self, method_token, user_course_id):
url = 'https://weiban.mycourse.cn/pharos/usercourse/v1/{}.do'.format(method_token)
t = get_timestamp().replace('.', '')
param = {
'callback': 'jQuery341' + str(random.random()).replace('.', '') + '_' + t,
'userCourseId': user_course_id,
'tenantCode': self.tenantCode,
'_': int(t) + 1
}
return self.process_url(url, param, 'GET')
def CheckCaptcha(self, url, answer):
payload = {"coordinateXYs": answer}
return requests.post(url, data=payload, headers=self.captcha_headers).text
def DoCaptcha(self, user_course_id):
get_url = 'https://weiban.mycourse.cn/pharos/usercourse/getCaptcha.do'
check_url = 'https://weiban.mycourse.cn/pharos/usercourse/checkCaptcha.do'
#?userCourseId={}&userProjectId={}&userId={}&tenantCode={}
param = {
'userCourseId': user_course_id,
'userProjectId': self.userProjectId,
'userId': self.userId,
'tenantCode': self.tenantCode
}
try:
captcha_data = json.loads(self.process_url(get_url, param, 'GET'))
captcha_num = captcha_data["captcha"]["num"]
captcha_id = captcha_data["captcha"]["questionId"]
captcha_image = captcha_img.download_image(captcha_data["captcha"]["imageUrl"])
if(captcha_image is None):
print('【错误】无法下载验证码')
return None
answer_pos = captcha_img.captcha_main(captcha_image, captcha_num)
full_check_url = f'{check_url}?userCourseId={user_course_id}&userProjectId={self.userProjectId}&userId={self.userId}&tenantCode={self.tenantCode}&questionId={captcha_id}'
captcha_result = json.loads(self.CheckCaptcha(full_check_url, answer_pos))
if((captcha_result["code"] != "0") or (captcha_result["data"]["checkResult"] != 1)):
print('【错误】验证码未通过')
return None
return captcha_result["data"]["methodToken"]
except json.decoder.JSONDecodeError as e:
print(f'JSON Error: {e.msg}')
return None
def MakeCourseFinish(self, captcha_token, user_course_id):
url = 'https://weiban.mycourse.cn/pharos/usercourse/v2/{}.do'.format(captcha_token)
t = GetTimeStampMS()
param = {
'callback': 'jQuery341' + str(random.random()).replace('.', '') + '_' + t,
'userCourseId': user_course_id,
'tenantCode': self.tenantCode,
'_': int(t) + 1
}
return self.process_url(url, param, 'GET')
def study(self, resource_id):
res = self._study(resource_id)
try:
j = json.loads(res)
return j["code"]
except json.decoder.JSONDecodeError as e:
print(e.msg)
def _study(self, resource_id):
url = 'https://weiban.mycourse.cn/pharos/usercourse/study.do?timestamp=' + get_timestamp()
data = {
'tenantCode': self.tenantCode,
'userId': self.userId,
'userProjectId': self.userProjectId,
'courseId': resource_id
}
return self.process_url(url, data)