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
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) |