forked from pipixia244/South_Seven-AutoReport
-
Notifications
You must be signed in to change notification settings - Fork 0
/
report.py
executable file
·366 lines (331 loc) · 15.4 KB
/
report.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
#!/bin/python3
# encoding=utf8
from selenium import webdriver
from PIL import Image
import time
import urllib.parse
import requests
import json
import time
import datetime
import pytz
import re
import sys
import argparse
import urllib.parse
import io
import os
from bs4 import BeautifulSoup
import PIL
import pytesseract
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
CAS_RETURN_URL = "https://weixine.ustc.edu.cn/2020/caslogin"
UPLOAD_PAGE_URL = "https://weixine.ustc.edu.cn/2020/upload/xcm"
UPLOAD_IMAGE_URL = "https://weixine.ustc.edu.cn/2020img/api/upload_for_student"
UPLOAD_INFO = [
(1, "14-day Big Data Trace Card")
]
DEFAULT_PIC = ['https://raw.githubusercontent.com/pipixia244/South_Seven-AutoReport/master/14day.jpg',
'https://raw.githubusercontent.com/pipixia244/South_Seven-AutoReport/master/ankang.jpg']
class Report(object):
def __init__(self, stuid, password, data_path, emer_person, relation, emer_phone, dorm_building, dorm, _14days_pic, ankang_pic, phone, addr):
self.stuid = stuid
self.password = password
self.data_path = data_path
self.emer_person = emer_person
self.relation = relation
self.emer_phone = emer_phone
self.dorm_building = dorm_building
self.dorm = dorm
self.pic = [_14days_pic, ankang_pic]
self.phone = phone
if addr == '':
self.addr = urllib.parse.quote("安徽省合肥市")
else:
self.addr = addr
def screenshot(self):
phone = self.phone
addr = self.addr
addr_urlencode = urllib.parse.quote(addr)
url = f"https://card.srpr.moe/cn-trip-card/#{phone}&{addr_urlencode}"
# 创建chrome参数对象
opt = webdriver.ChromeOptions()
opt.headless = True #设置无界面模式,windows开启会出现跨域cookie报错需要关闭,linux可以正常开启,自动适配对应参数
opt.add_argument('--no-sandbox')
opt.add_argument('--disable-gpu')
opt.add_argument('--hide-scrollbars')
opt.add_experimental_option('mobileEmulation', {'deviceName': 'Samsung Galaxy S8+'})
driver = webdriver.Chrome(options=opt)#此处填写chromedriver的路径
driver.get(url)
width = driver.execute_script("return document.documentElement.scrollWidth")
height = driver.execute_script("return document.documentElement.scrollHeight")
driver.set_window_size(width,height)
driver.get_screenshot_as_file('webpage.png')
print("整个网页尺寸:height={},width={}".format(height,width))
im=Image.open('webpage.png')
print("截图尺寸:height={},width={}".format(im.size[1],im.size[0]))
return im
def report(self):
phone = self.phone
addr = self.addr
# 统一验证登录
loginsuccess = False
retrycount = 5
while (not loginsuccess) and retrycount:
session = self.login()
cookies = session.cookies
getform = session.get("https://weixine.ustc.edu.cn/2020")
retrycount = retrycount - 1
if getform.url != "https://weixine.ustc.edu.cn/2020/home":
print("Login Failed! Retrying...")
else:
print("Login Successful!")
loginsuccess = True
if not loginsuccess:
return False
# 获取基本数据信息
data = getform.text
data = data.encode('ascii','ignore').decode('utf-8','ignore')
soup = BeautifulSoup(data, 'html.parser')
token = soup.find("input", {"name": "_token"})['value']
with open(self.data_path, "r+") as f:
data = f.read()
data = json.loads(data)
data["jinji_lxr"]=self.emer_person
data["jinji_guanxi"]=self.relation
data["jiji_mobile"]=self.emer_phone
data["dorm_building"]=self.dorm_building
data["dorm"]=self.dorm
data["_token"]=token
#print(data)
# 自动健康打卡
headers = {
'authority': 'weixine.ustc.edu.cn',
'origin': 'https://weixine.ustc.edu.cn',
'upgrade-insecure-requests': '1',
'content-type': 'application/x-www-form-urlencoded',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.100 Safari/537.36',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'referer': 'https://weixine.ustc.edu.cn/2020/home',
'accept-language': 'zh-CN,zh;q=0.9',
'cookie': "PHPSESSID=" + cookies.get("PHPSESSID") + ";XSRF-TOKEN=" + cookies.get("XSRF-TOKEN") + ";laravel_session="+cookies.get("laravel_session"),
}
url = "https://weixine.ustc.edu.cn/2020/daliy_report"
resp=session.post(url, data=data, headers=headers)
#print(resp)
res = session.get("https://weixine.ustc.edu.cn/2020/apply/daliy/i?t=3")
if(res.status_code < 400 and (res.url == "https://weixine.ustc.edu.cn/2020/upload/xcm" or res.url == "https://weixine.ustc.edu.cn/2020/apply/daliy/i?t=3")):
print("report success!")
elif(res.status_code < 400 and res.url != "https://weixine.ustc.edu.cn/2020/upload/xcm"):
print(res.url)
print("report failed")
return False
else:
print("unknown error, code: "+str(res.status_code))
# 自动上传健康码
is_new_upload = 0
is_user_upload = 0
can_upload_file = 0
if self.phone != '' and self.addr != '':
can_upload_file = 1
is_user_upload = 1
try:
#print(self.phone, self.addr)
self.screenshot()
except Exception as e:
print(e)
print('error!')
can_upload_file = 0
if(self.pic[0] != '' and self.pic[1] != ''):
can_upload_file = 0
is_user_upload = 1
ret = session.get("https://weixine.ustc.edu.cn/2020/apply/daliy/i?t=3")
if (True): #ret.url == "https://weixine.ustc.edu.cn/2020/upload/xcm" or is_user_upload == 1):
is_new_upload = 1
can_upload_code = 1
r = session.get(UPLOAD_PAGE_URL)
pos = r.text.find("每周可上报时间为周一凌晨0:00至周日中午12:00,其余时间将关闭相关功能。")
#print("position: "+str(pos))
if(pos != -1):
print("当前处于不可上报时间,请换其他时间上传健康码。")
can_upload_code = 0
for idx, description in UPLOAD_INFO:
if(can_upload_code == 0):
print(f"ignore {description}.")
continue
if(self.pic[idx - 1] == ''):
self.pic[idx - 1] = DEFAULT_PIC[idx - 1]
#print(self.pic[idx - 1])
if can_upload_file:
with open("webpage.png", 'rb') as f:
pngfile = f.read()
else:
ret = session.get(self.pic[idx - 1])
if can_upload_file:
blob = pngfile
else:
blob = ret.content
#print(len(blob))
#print(ret.status_code)
if blob == None or ret.status_code != 200:
print(f"ignore {description}.")
continue
#print(r.text)
r = session.get(UPLOAD_PAGE_URL)
#print(r.text)
x = re.search(r"""<input.*?name="_token".*?>""", r.text).group(0)
re.search(r'value="(\w*)"', x).group(1)
search_payload_1 = r"_token: '(\w*)'"
search_payload_2 = r"'gid': '(\d*)'"
search_payload_3 = r"'sign': '(\S*)'"
_token = re.search(search_payload_1, r.text).group(1);
gid = re.search(search_payload_2, r.text).group(1);
sign = re.search(search_payload_3, r.text).group(1);
# search_payload = r'''formData:{
# _token: '(\w{40})',
# 'gid': '(\d{10})',
# 'sign': '(\S{36})',
# 't' : 1
# }'''
# _token = re.search(search_payload, r.text).group(1);
# gid = re.search(search_payload, r.text).group(2);
# sign = re.search(search_payload, r.text).group(3);
# print(_token)
# print(gid)
# print(sign)
url = UPLOAD_IMAGE_URL
payload = {
"_token": _token,
"gid": f"{gid}",
"sign": f"{sign}",
"t": f"{idx}",
"id": f"WU_FILE_{idx}",
"name": f"{description}.png",
"type": "image/png",
"lastModifiedDate": datetime.datetime.now()
.strftime("%a %b %d %Y %H:%M:%S GMT+0800 (China Standard Time)"),
"size": f"{len(blob)}",
}
payload_files = {"file": (payload["name"], blob)}
headers_upload = session.headers
headers_upload['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.100 Safari/537.36'
r = session.post(url, data=payload, files=payload_files, headers=headers_upload)
#print(r)
#print(r.text):
r.raise_for_status()
if can_upload_file:
info = "file"
else:
info = "picture"
#print(r.text)
print(f"Uploaded {description} {info}: {r.json()['status']}")
# 自动出校报备
ret = session.get("https://weixine.ustc.edu.cn/2020/apply/daliy/i?t=3")
#print(ret.status_code)
if (ret.url == "https://weixine.ustc.edu.cn/2020/upload/xcm"):
print("Upload Code Img Error.")
return False
print("开始例行报备.")
data = ret.text
data = data.encode('ascii','ignore').decode('utf-8','ignore')
soup = BeautifulSoup(data, 'html.parser')
token2 = soup.find("input", {"name": "_token"})['value']
start_date = soup.find("input", {"id": "start_date"})['value']
end_date = soup.find("input", {"id": "end_date"})['value']
print("{}---{}".format(start_date, end_date))
REPORT_URL = "https://weixine.ustc.edu.cn/2020/apply/daliy/ipost"
RETURN_COLLEGE = {'东校区', '西校区', '中校区', '南校区', '北校区'}
REPORT_DATA = {
'_token': token2,
'start_date': start_date,
'end_date': end_date,
'return_college[]': RETURN_COLLEGE,
'reason': "上课/自习",
't': 3,
}
ret = session.post(url=REPORT_URL, data=REPORT_DATA)
# #删除占用码(可选功能, 默认关闭, 若想开启请取消注释)
# if (is_new_upload == 1 and is_user_upload == 0):
# print("delete.")
# header = session.headers
# header['referer'] = "https://weixine.ustc.edu.cn/2020/upload/xcm"
# header['X-CSRF-TOKEN'] = token2
# ret1 = session.post("https://weixine.ustc.edu.cn/2020/upload/1/delete", headers=header)
# ret2 = session.post("https://weixine.ustc.edu.cn/2020/upload/2/delete", headers=header)
# if(ret1.status_code < 400 and ret2.status_code < 400):
# print("delete success.")
# else:
# print(f"delete error, error code: {ret1} and {ret2}.")
if ret.status_code == 200:
print("success! code: "+str(ret.status_code))
return True
else:
print("error occured, code: "+str(ret.status_code))
return False
def login(self):
retries = Retry(total=5,
backoff_factor=0.5,
status_forcelist=[500, 502, 503, 504])
s = requests.Session()
s.mount("https://", HTTPAdapter(max_retries=retries))
s.headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 Edg/92.0.902.67"
url = "https://passport.ustc.edu.cn/login?service=http%3A%2F%2Fweixine.ustc.edu.cn%2F2020%2Fcaslogin"
r = s.get(url, params={"service": CAS_RETURN_URL})
x = re.search(r"""<input.*?name="CAS_LT".*?>""", r.text).group(0)
cas_lt = re.search(r'value="(LT-\w*)"', x).group(1)
CAS_CAPTCHA_URL = "https://passport.ustc.edu.cn/validatecode.jsp?type=login"
r = s.get(CAS_CAPTCHA_URL)
img = PIL.Image.open(io.BytesIO(r.content))
pix = img.load()
for i in range(img.size[0]):
for j in range(img.size[1]):
r, g, b = pix[i, j]
if g >= 40 and r < 80:
pix[i, j] = (0, 0, 0)
else:
pix[i, j] = (255, 255, 255)
lt_code = pytesseract.image_to_string(img).strip()
data = {
'model': 'uplogin.jsp',
'service': 'https://weixine.ustc.edu.cn/2020/caslogin',
'username': self.stuid,
'password': str(self.password),
'warn': '',
'showCode': '1',
'button': '',
'CAS_LT': cas_lt,
'LT': lt_code
}
print("lt-code is {}, login...".format(lt_code))
s.post(url, data=data)
return s
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='URC nCov auto report script.')
parser.add_argument('data_path', help='path to your own data used for post method', type=str)
parser.add_argument('stuid', help='your student number', type=str)
parser.add_argument('password', help='your CAS password', type=str)
parser.add_argument('emer_person', help='emergency person', type=str)
parser.add_argument('relation', help='relationship between you and he/she', type=str)
parser.add_argument('emer_phone', help='phone number', type=str)
parser.add_argument('dorm_building', help='dorm building num', type=str)
parser.add_argument('dorm', help='dorm number', type=str)
parser.add_argument('_14days_pic', help='14 days Big Data Trace Card', type=str)
parser.add_argument('ankang_pic', help='An Kang Health Code', type=str)
parser.add_argument('phone', help='phone', type=str)
parser.add_argument('addr', help='addr', type=str)
args = parser.parse_args()
autorepoter = Report(stuid=args.stuid, password=args.password, data_path=args.data_path, emer_person=args.emer_person,
relation=args.relation, emer_phone=args.emer_phone, dorm_building=args.dorm_building, dorm=args.dorm,
_14days_pic=args._14days_pic, ankang_pic=args.ankang_pic, phone=args.phone, addr=args.addr)
count = 5
while count != 0:
ret = autorepoter.report()
if ret != False:
break
print("Report Failed, retry...")
count = count - 1
if count != 0:
exit(0)
else:
exit(-1)