cherry reborn!!!

This commit is contained in:
ElonLi 2021-09-04 10:50:46 +08:00
parent ae6fe3ee8f
commit b660dd033c
8 changed files with 133 additions and 80 deletions

2
.gitignore vendored
View File

@ -1,3 +1,3 @@
__pycache__
.vscode/settings.json
venv
venv

View File

@ -8,13 +8,6 @@ python3 -m venv venv
. venv/bin/activate
// 升级pip
pip install --upgrade pip
// 安装flask...
pip install Flask
pip install requests
pip install bs4
pip install gunicorn
pip install pymongo
pip install flask_cors
// 根据依赖文件安装环境
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
// 设置全局变量

View File

@ -2,7 +2,7 @@
import sys
sys.path.append('./lib')
# 引入处理函数
from allFunction import manageLogin, manageScheduleUpload, manageScheduleGet
from allFunction import manageLogin, manageScheduleUpload, manageScheduleGet, manageSubmitVerificationCode
# 引入flask
from flask import Flask, request, session, redirect
# 初始化app
@ -24,6 +24,11 @@ def login():
res = manageLogin(request)
return res
@app.route('/api/submitVC', methods=['POST'])
def submitVC():
res = manageSubmitVerificationCode(request)
return res
# 更新课表游戏排名信息
@app.route('/api/game/schedule/upload',methods=['POST'])
def schedule_upload():
@ -43,4 +48,4 @@ def miss(e):
# 本地运行启动
if __name__ == '__main__':
app.run(host="0.0.0.0", debug=True, port="80")
app.run(host="127.0.0.1", debug=True, port="7980")

View File

@ -1,11 +1,16 @@
# coding=utf-8
import sys
from requests.sessions import session
sys.path.append('./lib/public')
from crawler import Crawler
import json
from hashlib import md5
from urllib.parse import urlencode, unquote_plus
from db import addRank, getRank
from db import insertRank, findRank
# 主函数
crawlerCache = {}
# 处理登录操作 data:{cid,pwd,sign}
# 这里三个接口公用一个session所以合并成一个接口一个session走到底一次性返回所有数据
def manageLogin(request):
@ -14,16 +19,26 @@ def manageLogin(request):
# MD5校验
checked = checkData(data)
if checked:
# 创建会话
phone = ''
if data.get('phone'):
phone = data['phone']
c = Crawler(data['cid'], data['pwd'], phone)
c = Crawler()
c.defaultInit(data)
res = c.connection()
crawlerCache[data['cid']] = c
return res
else:
return '数据校验失败', 400
def manageSubmitVerificationCode(request):
data = json.loads(request.form['data'])
checked = checkData(data)
if checked:
c = crawlerCache[data['cid']]
res = c.submitVerificationCode(data)
if res[-1] == 200:
c.getGrade()
c.getSchedule()
return c.getData()
grade = c.getGrade()
ownSchedule = c.getOwnSchedule()
crawlerCache[data['cid']] = None
return json.dumps({'grade': grade, 'ownSchedule': ownSchedule}), 200
else:
return res
else:
@ -37,7 +52,7 @@ def manageScheduleUpload(request):
checked = checkData(data_cache)
data_cache.pop('sign')
if checked:
add_res = addRank( data_cache['nick'], data_cache['count'], data_cache['time'])
add_res = insertRank( data_cache['cid'], data_cache['nick'], data_cache['count'], data_cache['time'])
return add_res
else:
return '数据校验失败', 400
@ -51,7 +66,7 @@ def manageScheduleGet(request):
data_cache.pop('sign')
if checked:
# 获取排名表
get_res = getRank()
get_res = findRank()
return get_res
else:
return '数据校验失败', 400

View File

@ -78,7 +78,7 @@ def manageCrawler(cid, pwd, phone):
return get_res
grade = get_res[0]
return {
'user_info': init_res[0]
'user_info': init_res[0],
'grade': grade,
'schedule': schedule,
}, 200

View File

@ -1,21 +1,27 @@
import json
from json.encoder import JSONEncoder
import requests
from urllib.parse import quote
import base64
from bs4 import BeautifulSoup
import random
import sys
from werkzeug.utils import redirect
from utils import btoa, signCode
from ocr import getCaptcha
class Crawler(object):
def __init__(self):
self.__session = None
self.__session = requests.Session()
self.__response = None
self.__pwd = None
self.__phone = None
self.cid = None
self.sid = None
self.uid = None
self.real_name = None
self.baseUrl = None
# 获取用户基本信息
def getUserInfo(self):
@ -32,70 +38,82 @@ class Crawler(object):
try:
# 获取统一身份系统的网页
r = self.__session.get(
url='https://mysso.cust.edu.cn/cas/login?service=https://jwgls1.cust.edu.cn/welcome')
url='https://mysso.cust.edu.cn/cas/login?service=https://jwgl.cust.edu.cn/welcome')
soup = BeautifulSoup(r.text, 'html.parser')
execution = soup.find_all(name='input')[6]['value']
execution = soup.find_all(name='input')[3]['value']
r = self.__session.get('https://mysso.cust.edu.cn/cas/captcha')
formdata = {
'username': self.cid,
'password': self.__pwd,
'execution': execution,
'captcha': getCaptcha(r.content),
'_eventId': 'submit',
'geolocation': ''
}
r = self.__session.post(
url='https://mysso.cust.edu.cn/cas/login?service=https://jwgls1.cust.edu.cn/welcome', data=formdata)
url='https://mysso.cust.edu.cn/cas/login?service=https://jwgl.cust.edu.cn/welcome', data = formdata)
soup = BeautifulSoup(r.text, 'html.parser')
flag = soup.find(name='title')
if(flag.text == "手机号设置"):
if self.__phone == '':
return '请填写手机号', 513
execution = soup.find_all(name='input')[1]['value']
formdata = {
'phone': self.__phone,
'execution': execution,
'_eventId': 'submit',
'submit': '提交'
}
r = self.__session.post(
url="https://mysso.cust.edu.cn/cas/login?service=https://jwgls1.cust.edu.cn/welcome", data=formdata)
r = self.__session.get(
url='https://portal.cust.edu.cn/custp/index')
soup = BeautifulSoup(r.text, 'html.parser')
try:
if soup.findAll(name='a')[4]['href'] != 'logout':
raise('账号或密码错误')
except:
loginSuccess = (soup.find(name='title').text != "统一身份认证系统")
self.__response = r
if not loginSuccess:
return '账号或者密码错误', 511
r = self.__session.get(
url='https://mysso.cust.edu.cn/cas/login?service=https://jwgls1.cust.edu.cn/welcome', allow_redirects=False)
ticket = r.headers['Location'][42:]
asp_net_sessionid_param = {
'Ticket': ticket, 'Url': 'https://jwgls1.cust.edu.cn/welcome'}
asp_net_sessionid_param = base64.b64encode(
quote(json.dumps(asp_net_sessionid_param)).encode('utf-8')).decode('utf-8')
asp_net_sessionid_param = {'param': asp_net_sessionid_param}
headers = {'Content-Type': 'application/json'}
r = self.__session.post(url='https://jwgls1.cust.edu.cn/api/LoginApi/LGSSOLocalLogin?sf_request_type=ajax',
data=json.dumps(asp_net_sessionid_param), headers=headers)
data = json.loads(r.content.decode('utf-8'))
# 提示未建立教务信息
if data['state'] == 1:
return data['message'], 514
self.real_name = data['data']['StudentDto']['XM']
self.sid = data['data']['StudentDto']['XH']
self.uid = data['data']['StudentDto']['SMXSJBXXID']
return self.getUserInfo(), 200
return '登录成功', 200
except Exception as e:
print(e)
return '教务挂了', 515
def submitVerificationCode(self, data):
try:
r = self.__response
soup = BeautifulSoup(r.text, 'html.parser')
execution = soup.find_all(name='input')[2]['value']
formdata = {
'yzm': data['vc'],
'msgType': '',
'execution': execution,
'_eventId': 'submit'
}
r = self.__session.post(
url = "https://mysso.cust.edu.cn/cas/login?service=https://jwgl.cust.edu.cn/welcome", data = formdata, allow_redirects = True)
self.__response = r
return 'gotcha!', 200
except Exception as e:
print(e)
return '教务挂了', 515
# 获取成绩 -----------------------------------------------------------------------------
def getGrade(self):
r = self.__response
urlBase = r.url.split('.')[0]
ticket = r.url.split('?')[-1]
param = base64.b64encode(quote(json.dumps({
"Ticket":ticket.split('=')[-1],
"Url":"https://jwgl.cust.edu.cn/welcome"
})).encode('utf-8'))
self.baseUrl = urlBase
r = self.__session.post(
url = urlBase + '.cust.edu.cn/api/LoginApi/LGSSOLocalLogin',
data = {
"param": param,
"__log": {},
"__permission": {}
})
headers = {'Content-Type': 'application/json'}
r = self.__session.post(
url='https://jwgls1.cust.edu.cn/api/ClientStudent/QueryService/GradeQueryApi/GetDataByStudent?sf_request_type=ajax',
data=json.dumps({"param": "JTdCJTIyU2hvd0dyYWRlVHlwZSUyMiUzQTElN0Q=", "__permission": {"MenuID": "4443798E-EB6E-4D88-BFBD-BB0A76FF6BD5",
"Operation": 0}, "__log": {"MenuID": "4443798E-EB6E-4D88-BFBD-BB0A76FF6BD5", "Logtype": 6, "Context": "查询"}}),
url=urlBase + '.cust.edu.cn/api/ClientStudent/QueryService/GradeQueryApi/GetDataByStudent',
data=json.dumps({
"param": "JTdCJTIyU2hvd0dyYWRlVHlwZSUyMiUzQTAlN0Q=",
"__permission": {
"MenuID": "4443798E-EB6E-4D88-BFBD-BB0A76FF6BD5",
"Operate": "select",
"Operation": 0
},
"__log": {
"MenuID": "4443798E-EB6E-4D88-BFBD-BB0A76FF6BD5",
"Logtype": 6,
"Context": "查询"
}
}),
headers=headers
)
data = json.loads(r.content.decode('utf-8'))
@ -320,9 +338,20 @@ class Crawler(object):
def getOwnSchedule(self):
headers = {'Content-Type': 'application/json'}
r = self.__session.post(
url='https://jwgls1.cust.edu.cn/api/ClientStudent/Home/StudentHomeApi/QueryStudentScheduleData?sf_request_type=ajax',
data=json.dumps({"param": "JTdCJTdE", "__permission": {"MenuID": "F71C97D5-D3E2-4FDA-9209-D7FA8626390E",
"Operation": 0}, "__log": {"MenuID": "F71C97D5-D3E2-4FDA-9209-D7FA8626390E", "Logtype": 6, "Context": "查询"}}),
url=self.baseUrl + '.cust.edu.cn/api/ClientStudent/Home/StudentHomeApi/QueryStudentScheduleData',
data=json.dumps({
"param": "JTdCJTdE",
"__permission": {
"MenuID": "00000000-0000-0000-0000-000000000000",
"Operate": "select",
"Operation": "0"
},
"__log": {
"MenuID": "00000000-0000-0000-0000-000000000000",
"Logtype": 6,
"Context": "查询"
}
}),
headers=headers
)
data = json.loads(r.content.decode('utf-8'))
@ -336,7 +365,7 @@ class Crawler(object):
params = {"KBLX":"2","CXLX":"0","XNXQ":"20202","CXID":self.uid,"CXZC":"0","JXBLX":""}
params = str(btoa(json.dumps(params)))[2:-1]
r = self.__session.post(
url='https://jwgls1.cust.edu.cn/api/ClientStudent/QueryService/OccupyQueryApi/QueryScheduleData?sf_request_type=ajax',
url=self.baseUrl + '.cust.edu.cn/api/ClientStudent/QueryService/OccupyQueryApi/QueryScheduleData?sf_request_type=ajax',
data=json.dumps({"param": params, "__permission": {"MenuID": "F71C97D5-D3E2-4FDA-9209-D7FA8626390E",
"Operation": 0}, "__log": {"MenuID": "F71C97D5-D3E2-4FDA-9209-D7FA8626390E", "Logtype": 6, "Context": "查询"}}),
headers=headers
@ -357,12 +386,11 @@ class Crawler(object):
return 'OK', 200
# 默认初始化
def defaultInit(self, cid, pwd, phone):
self.cid = cid
self.__pwd = pwd
self.__phone = phone
def defaultInit(self, data):
self.cid = data['cid']
self.__pwd = data['pwd']
self.__phone = data['phone']
self.__session = requests.Session()
return self.connection()
# 使用我的cookie初始化用于快速刷新课表
def cookieInit(self, cookies, uid, cid, sid, real_name):

View File

@ -154,7 +154,7 @@ def updateBg(cid, img_id):
用户更新背景图片
"""
try:
col('user').update('cid': cid, {'$set': {'setting.bg': img_id}})
col('user').update({'cid': cid}, {'$set': {'setting.bg': img_id}})
return 'OK', 200
except Exception as e:
print(e)
@ -305,7 +305,7 @@ def userInsertAllCrouse(crouses):
print(e)
return '用户所有课程数据库插入失败', 108
def insertRank(nick, count, time):
def insertRank(cid, nick, count, time):
"""
向排名表里增加或者覆写数据
"""
@ -345,7 +345,7 @@ def findUserCrouse(sid):
return crouse_list, 200
except Exception as e:
print(e)
reutrn '用户课程数据库查询失败', 304
return '用户课程数据库查询失败', 304
def groupInsertCrouse(crouse):
"""

12
lib/public/ocr.py Normal file
View File

@ -0,0 +1,12 @@
from aip import AipOcr
APP_ID = '24797034'
API_KEY = 'ykebbHq8GaK2cD1sIPy7PEPu'
SECRET_KEY = '4rU7QPC1oGFbZgIbsDvMGcqPky4kv7kV'
import base64
from urllib.parse import quote
import json
client = AipOcr(APP_ID, API_KEY, SECRET_KEY)
def getCaptcha(image):
return client.numbers(image)['words_result'][0]['words']