cherry reborn!!!
This commit is contained in:
parent
ae6fe3ee8f
commit
b660dd033c
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,3 @@
|
|||||||
__pycache__
|
__pycache__
|
||||||
.vscode/settings.json
|
.vscode/settings.json
|
||||||
venv
|
venv
|
||||||
|
@ -8,13 +8,6 @@ python3 -m venv venv
|
|||||||
. venv/bin/activate
|
. venv/bin/activate
|
||||||
// 升级pip
|
// 升级pip
|
||||||
pip install --upgrade 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
|
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||||
// 设置全局变量
|
// 设置全局变量
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import sys
|
import sys
|
||||||
sys.path.append('./lib')
|
sys.path.append('./lib')
|
||||||
# 引入处理函数
|
# 引入处理函数
|
||||||
from allFunction import manageLogin, manageScheduleUpload, manageScheduleGet
|
from allFunction import manageLogin, manageScheduleUpload, manageScheduleGet, manageSubmitVerificationCode
|
||||||
# 引入flask
|
# 引入flask
|
||||||
from flask import Flask, request, session, redirect
|
from flask import Flask, request, session, redirect
|
||||||
# 初始化app
|
# 初始化app
|
||||||
@ -24,6 +24,11 @@ def login():
|
|||||||
res = manageLogin(request)
|
res = manageLogin(request)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
@app.route('/api/submitVC', methods=['POST'])
|
||||||
|
def submitVC():
|
||||||
|
res = manageSubmitVerificationCode(request)
|
||||||
|
return res
|
||||||
|
|
||||||
# 更新课表游戏排名信息
|
# 更新课表游戏排名信息
|
||||||
@app.route('/api/game/schedule/upload',methods=['POST'])
|
@app.route('/api/game/schedule/upload',methods=['POST'])
|
||||||
def schedule_upload():
|
def schedule_upload():
|
||||||
@ -43,4 +48,4 @@ def miss(e):
|
|||||||
|
|
||||||
# 本地运行启动
|
# 本地运行启动
|
||||||
if __name__ == '__main__':
|
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")
|
@ -1,11 +1,16 @@
|
|||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from requests.sessions import session
|
||||||
|
sys.path.append('./lib/public')
|
||||||
from crawler import Crawler
|
from crawler import Crawler
|
||||||
import json
|
import json
|
||||||
from hashlib import md5
|
from hashlib import md5
|
||||||
from urllib.parse import urlencode, unquote_plus
|
from urllib.parse import urlencode, unquote_plus
|
||||||
from db import addRank, getRank
|
from db import insertRank, findRank
|
||||||
# 主函数
|
# 主函数
|
||||||
|
|
||||||
|
crawlerCache = {}
|
||||||
# 处理登录操作 data:{cid,pwd,sign}
|
# 处理登录操作 data:{cid,pwd,sign}
|
||||||
# 这里三个接口公用一个session所以合并成一个接口,一个session走到底,一次性返回所有数据
|
# 这里三个接口公用一个session所以合并成一个接口,一个session走到底,一次性返回所有数据
|
||||||
def manageLogin(request):
|
def manageLogin(request):
|
||||||
@ -14,16 +19,26 @@ def manageLogin(request):
|
|||||||
# MD5校验
|
# MD5校验
|
||||||
checked = checkData(data)
|
checked = checkData(data)
|
||||||
if checked:
|
if checked:
|
||||||
# 创建会话
|
c = Crawler()
|
||||||
phone = ''
|
c.defaultInit(data)
|
||||||
if data.get('phone'):
|
|
||||||
phone = data['phone']
|
|
||||||
c = Crawler(data['cid'], data['pwd'], phone)
|
|
||||||
res = c.connection()
|
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:
|
if res[-1] == 200:
|
||||||
c.getGrade()
|
grade = c.getGrade()
|
||||||
c.getSchedule()
|
ownSchedule = c.getOwnSchedule()
|
||||||
return c.getData()
|
crawlerCache[data['cid']] = None
|
||||||
|
return json.dumps({'grade': grade, 'ownSchedule': ownSchedule}), 200
|
||||||
else:
|
else:
|
||||||
return res
|
return res
|
||||||
else:
|
else:
|
||||||
@ -37,7 +52,7 @@ def manageScheduleUpload(request):
|
|||||||
checked = checkData(data_cache)
|
checked = checkData(data_cache)
|
||||||
data_cache.pop('sign')
|
data_cache.pop('sign')
|
||||||
if checked:
|
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
|
return add_res
|
||||||
else:
|
else:
|
||||||
return '数据校验失败', 400
|
return '数据校验失败', 400
|
||||||
@ -51,7 +66,7 @@ def manageScheduleGet(request):
|
|||||||
data_cache.pop('sign')
|
data_cache.pop('sign')
|
||||||
if checked:
|
if checked:
|
||||||
# 获取排名表
|
# 获取排名表
|
||||||
get_res = getRank()
|
get_res = findRank()
|
||||||
return get_res
|
return get_res
|
||||||
else:
|
else:
|
||||||
return '数据校验失败', 400
|
return '数据校验失败', 400
|
||||||
|
@ -78,7 +78,7 @@ def manageCrawler(cid, pwd, phone):
|
|||||||
return get_res
|
return get_res
|
||||||
grade = get_res[0]
|
grade = get_res[0]
|
||||||
return {
|
return {
|
||||||
'user_info': init_res[0]
|
'user_info': init_res[0],
|
||||||
'grade': grade,
|
'grade': grade,
|
||||||
'schedule': schedule,
|
'schedule': schedule,
|
||||||
}, 200
|
}, 200
|
||||||
|
@ -1,21 +1,27 @@
|
|||||||
import json
|
import json
|
||||||
|
from json.encoder import JSONEncoder
|
||||||
import requests
|
import requests
|
||||||
from urllib.parse import quote
|
from urllib.parse import quote
|
||||||
import base64
|
import base64
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
import random
|
import random
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from werkzeug.utils import redirect
|
||||||
from utils import btoa, signCode
|
from utils import btoa, signCode
|
||||||
|
from ocr import getCaptcha
|
||||||
|
|
||||||
class Crawler(object):
|
class Crawler(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.__session = None
|
self.__session = requests.Session()
|
||||||
|
self.__response = None
|
||||||
self.__pwd = None
|
self.__pwd = None
|
||||||
self.__phone = None
|
self.__phone = None
|
||||||
self.cid = None
|
self.cid = None
|
||||||
self.sid = None
|
self.sid = None
|
||||||
self.uid = None
|
self.uid = None
|
||||||
self.real_name = None
|
self.real_name = None
|
||||||
|
self.baseUrl = None
|
||||||
|
|
||||||
# 获取用户基本信息
|
# 获取用户基本信息
|
||||||
def getUserInfo(self):
|
def getUserInfo(self):
|
||||||
@ -32,70 +38,82 @@ class Crawler(object):
|
|||||||
try:
|
try:
|
||||||
# 获取统一身份系统的网页
|
# 获取统一身份系统的网页
|
||||||
r = self.__session.get(
|
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')
|
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 = {
|
formdata = {
|
||||||
'username': self.cid,
|
'username': self.cid,
|
||||||
'password': self.__pwd,
|
'password': self.__pwd,
|
||||||
'execution': execution,
|
'execution': execution,
|
||||||
|
'captcha': getCaptcha(r.content),
|
||||||
'_eventId': 'submit',
|
'_eventId': 'submit',
|
||||||
'geolocation': ''
|
'geolocation': ''
|
||||||
}
|
}
|
||||||
r = self.__session.post(
|
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')
|
soup = BeautifulSoup(r.text, 'html.parser')
|
||||||
flag = soup.find(name='title')
|
loginSuccess = (soup.find(name='title').text != "统一身份认证系统")
|
||||||
if(flag.text == "手机号设置"):
|
self.__response = r
|
||||||
if self.__phone == '':
|
if not loginSuccess:
|
||||||
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:
|
|
||||||
return '账号或者密码错误', 511
|
return '账号或者密码错误', 511
|
||||||
r = self.__session.get(
|
return '登录成功', 200
|
||||||
url='https://mysso.cust.edu.cn/cas/login?service=https://jwgls1.cust.edu.cn/welcome', allow_redirects=False)
|
except Exception as e:
|
||||||
ticket = r.headers['Location'][42:]
|
print(e)
|
||||||
asp_net_sessionid_param = {
|
return '教务挂了', 515
|
||||||
'Ticket': ticket, 'Url': 'https://jwgls1.cust.edu.cn/welcome'}
|
|
||||||
asp_net_sessionid_param = base64.b64encode(
|
def submitVerificationCode(self, data):
|
||||||
quote(json.dumps(asp_net_sessionid_param)).encode('utf-8')).decode('utf-8')
|
try:
|
||||||
asp_net_sessionid_param = {'param': asp_net_sessionid_param}
|
r = self.__response
|
||||||
headers = {'Content-Type': 'application/json'}
|
soup = BeautifulSoup(r.text, 'html.parser')
|
||||||
r = self.__session.post(url='https://jwgls1.cust.edu.cn/api/LoginApi/LGSSOLocalLogin?sf_request_type=ajax',
|
execution = soup.find_all(name='input')[2]['value']
|
||||||
data=json.dumps(asp_net_sessionid_param), headers=headers)
|
formdata = {
|
||||||
data = json.loads(r.content.decode('utf-8'))
|
'yzm': data['vc'],
|
||||||
# 提示未建立教务信息
|
'msgType': '',
|
||||||
if data['state'] == 1:
|
'execution': execution,
|
||||||
return data['message'], 514
|
'_eventId': 'submit'
|
||||||
self.real_name = data['data']['StudentDto']['XM']
|
}
|
||||||
self.sid = data['data']['StudentDto']['XH']
|
r = self.__session.post(
|
||||||
self.uid = data['data']['StudentDto']['SMXSJBXXID']
|
url = "https://mysso.cust.edu.cn/cas/login?service=https://jwgl.cust.edu.cn/welcome", data = formdata, allow_redirects = True)
|
||||||
return self.getUserInfo(), 200
|
self.__response = r
|
||||||
|
return 'gotcha!', 200
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
return '教务挂了', 515
|
return '教务挂了', 515
|
||||||
|
|
||||||
# 获取成绩 -----------------------------------------------------------------------------
|
# 获取成绩 -----------------------------------------------------------------------------
|
||||||
def getGrade(self):
|
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'}
|
headers = {'Content-Type': 'application/json'}
|
||||||
r = self.__session.post(
|
r = self.__session.post(
|
||||||
url='https://jwgls1.cust.edu.cn/api/ClientStudent/QueryService/GradeQueryApi/GetDataByStudent?sf_request_type=ajax',
|
url=urlBase + '.cust.edu.cn/api/ClientStudent/QueryService/GradeQueryApi/GetDataByStudent',
|
||||||
data=json.dumps({"param": "JTdCJTIyU2hvd0dyYWRlVHlwZSUyMiUzQTElN0Q=", "__permission": {"MenuID": "4443798E-EB6E-4D88-BFBD-BB0A76FF6BD5",
|
data=json.dumps({
|
||||||
"Operation": 0}, "__log": {"MenuID": "4443798E-EB6E-4D88-BFBD-BB0A76FF6BD5", "Logtype": 6, "Context": "查询"}}),
|
"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
|
headers=headers
|
||||||
)
|
)
|
||||||
data = json.loads(r.content.decode('utf-8'))
|
data = json.loads(r.content.decode('utf-8'))
|
||||||
@ -320,9 +338,20 @@ class Crawler(object):
|
|||||||
def getOwnSchedule(self):
|
def getOwnSchedule(self):
|
||||||
headers = {'Content-Type': 'application/json'}
|
headers = {'Content-Type': 'application/json'}
|
||||||
r = self.__session.post(
|
r = self.__session.post(
|
||||||
url='https://jwgls1.cust.edu.cn/api/ClientStudent/Home/StudentHomeApi/QueryStudentScheduleData?sf_request_type=ajax',
|
url=self.baseUrl + '.cust.edu.cn/api/ClientStudent/Home/StudentHomeApi/QueryStudentScheduleData',
|
||||||
data=json.dumps({"param": "JTdCJTdE", "__permission": {"MenuID": "F71C97D5-D3E2-4FDA-9209-D7FA8626390E",
|
data=json.dumps({
|
||||||
"Operation": 0}, "__log": {"MenuID": "F71C97D5-D3E2-4FDA-9209-D7FA8626390E", "Logtype": 6, "Context": "查询"}}),
|
"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
|
headers=headers
|
||||||
)
|
)
|
||||||
data = json.loads(r.content.decode('utf-8'))
|
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 = {"KBLX":"2","CXLX":"0","XNXQ":"20202","CXID":self.uid,"CXZC":"0","JXBLX":""}
|
||||||
params = str(btoa(json.dumps(params)))[2:-1]
|
params = str(btoa(json.dumps(params)))[2:-1]
|
||||||
r = self.__session.post(
|
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",
|
data=json.dumps({"param": params, "__permission": {"MenuID": "F71C97D5-D3E2-4FDA-9209-D7FA8626390E",
|
||||||
"Operation": 0}, "__log": {"MenuID": "F71C97D5-D3E2-4FDA-9209-D7FA8626390E", "Logtype": 6, "Context": "查询"}}),
|
"Operation": 0}, "__log": {"MenuID": "F71C97D5-D3E2-4FDA-9209-D7FA8626390E", "Logtype": 6, "Context": "查询"}}),
|
||||||
headers=headers
|
headers=headers
|
||||||
@ -357,12 +386,11 @@ class Crawler(object):
|
|||||||
return 'OK', 200
|
return 'OK', 200
|
||||||
|
|
||||||
# 默认初始化
|
# 默认初始化
|
||||||
def defaultInit(self, cid, pwd, phone):
|
def defaultInit(self, data):
|
||||||
self.cid = cid
|
self.cid = data['cid']
|
||||||
self.__pwd = pwd
|
self.__pwd = data['pwd']
|
||||||
self.__phone = phone
|
self.__phone = data['phone']
|
||||||
self.__session = requests.Session()
|
self.__session = requests.Session()
|
||||||
return self.connection()
|
|
||||||
|
|
||||||
# 使用我的cookie初始化,用于快速刷新课表
|
# 使用我的cookie初始化,用于快速刷新课表
|
||||||
def cookieInit(self, cookies, uid, cid, sid, real_name):
|
def cookieInit(self, cookies, uid, cid, sid, real_name):
|
||||||
|
@ -154,7 +154,7 @@ def updateBg(cid, img_id):
|
|||||||
用户更新背景图片
|
用户更新背景图片
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
col('user').update('cid': cid, {'$set': {'setting.bg': img_id}})
|
col('user').update({'cid': cid}, {'$set': {'setting.bg': img_id}})
|
||||||
return 'OK', 200
|
return 'OK', 200
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
@ -305,7 +305,7 @@ def userInsertAllCrouse(crouses):
|
|||||||
print(e)
|
print(e)
|
||||||
return '用户所有课程数据库插入失败', 108
|
return '用户所有课程数据库插入失败', 108
|
||||||
|
|
||||||
def insertRank(nick, count, time):
|
def insertRank(cid, nick, count, time):
|
||||||
"""
|
"""
|
||||||
向排名表里增加或者覆写数据
|
向排名表里增加或者覆写数据
|
||||||
"""
|
"""
|
||||||
@ -345,7 +345,7 @@ def findUserCrouse(sid):
|
|||||||
return crouse_list, 200
|
return crouse_list, 200
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
reutrn '用户课程数据库查询失败', 304
|
return '用户课程数据库查询失败', 304
|
||||||
|
|
||||||
def groupInsertCrouse(crouse):
|
def groupInsertCrouse(crouse):
|
||||||
"""
|
"""
|
||||||
|
12
lib/public/ocr.py
Normal file
12
lib/public/ocr.py
Normal 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']
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user