Skip to content
This repository was archived by the owner on Apr 1, 2021. It is now read-only.

Commit 1322dae

Browse files
authored
Merge pull request #100 from NKUST-ITC/develop
Update master
2 parents 23ff918 + d2b5837 commit 1322dae

4 files changed

Lines changed: 89 additions & 45 deletions

File tree

src/cache/bus_cache.py

Lines changed: 74 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import datetime
21
import json
32
import pickle
3+
from datetime import datetime, timedelta
44
from multiprocessing.pool import ThreadPool
55

6-
76
import redis
87
import requests
98

@@ -13,6 +12,7 @@
1312
red_string = redis.StrictRedis.from_url(
1413
url=config.REDIS_URL, db=4, charset="utf-8", decode_responses=True)
1514
red_bin = redis.StrictRedis.from_url(url=config.REDIS_URL, db=3)
15+
pool = ThreadPool()
1616

1717

1818
def login(username, password):
@@ -75,54 +75,50 @@ def bus_query(username, year, month, day):
7575

7676
if not red_bin.exists('bus_cookie_%s' % username):
7777
return error_code.CACHE_BUS_COOKIE_ERROR
78-
79-
redis_name = "bus_timetable_{username}_{year}_{month}_{day}".format(
80-
username=username,
78+
redis_name = "bus_timetable_{year}_{month}_{day}".format(
8179
year=year,
8280
month=month,
8381
day=day)
8482

85-
if red_string.exists(redis_name):
86-
return red_string.get(redis_name)
87-
8883
session = requests.session()
8984
session.cookies = pickle.loads(red_bin.get('bus_cookie_%s' % username))
90-
pool = ThreadPool(processes=1)
91-
async_result = pool.apply_async(bus_reservations_record, (username,))
92-
93-
result = bus_crawler.query(
94-
session=session, year=year, month=month, day=day)
95-
96-
if isinstance(result, list):
85+
user_book_data = pool.apply_async(bus_reservations_record, (username,))
9786

98-
if not isinstance(async_result.get(), str):
87+
if red_string.exists(redis_name):
88+
main_timetable = json.loads(red_string.get(redis_name))
89+
else:
90+
main_timetable = get_and_update_timetable_cache(
91+
session, year, month, day)
92+
93+
if isinstance(main_timetable, list):
94+
user_book_data = user_book_data.get()
95+
if not isinstance(user_book_data, str):
9996
return error_code.BUS_ERROR
100-
# mix cancelKey in timetable
101-
user_reservation = json.loads(async_result.get())
102-
for bus_data in result:
97+
# mix cancelKey and add 'isReserve' in timetable
98+
user_reservation = json.loads(user_book_data)
99+
for bus_data in main_timetable:
103100
bus_data['cancelKey'] = ''
104-
if bus_data['isReserve']:
105-
for reservation_data in user_reservation['data']:
106-
if reservation_data['dateTime'] == bus_data['departureTime']:
107-
bus_data['cancelKey'] = reservation_data['cancelKey']
101+
bus_data['isReserve'] = False
102+
for reservation_data in user_reservation['data']:
103+
if reservation_data['dateTime'] == bus_data['departureTime'] and \
104+
reservation_data['start'] == bus_data['startStation']:
105+
bus_data['isReserve'] = True
106+
bus_data['cancelKey'] = reservation_data['cancelKey']
108107

109108
return_data = {
110-
"date": datetime.datetime.utcnow().isoformat(timespec='seconds')+"Z",
111-
"data": result
109+
"date": datetime.utcnow().isoformat(timespec='seconds')+"Z",
110+
"data": main_timetable
112111
}
113-
json_dumps_data = json.dumps(return_data, ensure_ascii=False)
114-
red_string.set(
115-
name=redis_name,
116-
value=json_dumps_data,
117-
ex=config.CACHE_BUS_TIMETABLE_EXPIRE_TIME)
118-
return json_dumps_data
119112

120-
elif result == error_code.BUS_USER_WRONG_CAMPUS_OR_NOT_FOUND_USER:
113+
return json.dumps(return_data, ensure_ascii=False)
114+
115+
elif main_timetable == error_code.BUS_USER_WRONG_CAMPUS_OR_NOT_FOUND_USER:
121116
# clear user cache cookie
122117
red_bin.delete('bus_cookie_%s' % username)
118+
red_bin.delete(redis_name)
123119
return error_code.CACHE_BUS_USER_ERROR
124120
# return error code
125-
return result
121+
return error_code.BUS_ERROR
126122

127123

128124
def bus_reservations_record(username):
@@ -193,8 +189,24 @@ def bus_reserve_book(username, kid, action):
193189
if isinstance(result, dict):
194190
if result['success']:
195191
# clear all bus cache, because data changed.
196-
for key in red_string.scan_iter('bus_*_{username}*'.format(username=username)):
192+
for key in red_string.scan_iter('bus_reservations_{username}*'.format(username=username)):
197193
red_string.delete(key)
194+
# remake redis user cache
195+
pool.apply_async(func=bus_reservations_record, args=(username,))
196+
# delete old main timetable
197+
if result.get("busTime"):
198+
book_time = datetime.fromtimestamp(
199+
int(result.get("busTime"))/1000)
200+
for key in red_string.scan_iter(
201+
'bus_timetable_{year}_{month}_{day}'.format(
202+
year=book_time.year,
203+
month=book_time.month,
204+
day=book_time.day)):
205+
red_string.delete(key)
206+
# update new main timetable
207+
pool.apply_async(func=get_and_update_timetable_cache, args=(
208+
session, book_time.year, book_time.month, book_time.day,))
209+
198210
return result
199211
else:
200212
return result
@@ -245,3 +257,31 @@ def bus_violation(username):
245257

246258
# return error code
247259
return result
260+
261+
262+
def get_and_update_timetable_cache(session: requests.session, year: int, month: int, day: int):
263+
"Just update redis bus timetable"
264+
redis_name = "bus_timetable_{year}_{month}_{day}".format(
265+
year=year,
266+
month=month,
267+
day=day)
268+
269+
main_timetable = bus_crawler.query(
270+
session=session, year=year, month=month, day=day)
271+
272+
if isinstance(main_timetable, list):
273+
red_string.set(
274+
name=redis_name,
275+
value=json.dumps(main_timetable, ensure_ascii=False),
276+
ex=config.CACHE_BUS_TIMETABLE_EXPIRE_TIME)
277+
if isinstance(main_timetable, list) and len(main_timetable) > 0:
278+
expire_seconds = ((datetime.strptime(
279+
main_timetable[0]['departureTime'], "%Y-%m-%dT%H:%M:%SZ")
280+
+ timedelta(days=1))-datetime.now()).total_seconds()
281+
282+
if expire_seconds > 0:
283+
red_string.set(
284+
name=redis_name,
285+
value=json.dumps(main_timetable, ensure_ascii=False),
286+
ex=round(expire_seconds))
287+
return main_timetable

src/cache/parse.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,16 +132,13 @@ def scores(html):
132132

133133
detail = {
134134
"conduct": float(total[0][5::]) if not None else 0.0,
135-
"classRank": total[2][8::]
135+
"classRank": total[2][8::],
136+
"departmentRank": total[3][8::]
136137
}
137138
try:
138139
detail["average"] = float(total[1][4::]) if not None else 0.0
139140
except ValueError:
140141
detail["average"] = 0.0
141-
try:
142-
detail["classPercentage"] = float(total[3][7:-1]) if not None else 0.0
143-
except ValueError:
144-
detail["classPercentage"] = 0.0
145142
res = {
146143
"scores": scores_list,
147144
"detail": detail

src/crawler/bus_crawler.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import datetime
22
import json
3-
import pytz
3+
import re
44

55
import execjs
6+
import pytz
67
import requests
78

89
from utils import config, error_code
@@ -85,7 +86,7 @@ def login(session, username, password):
8586

8687
return error_code.BUS_ERROR
8788

88-
89+
8990
def query(session, year, month, day):
9091
"""query bus timetable.
9192
@@ -221,6 +222,14 @@ def book(session, kid, action=True):
221222
try:
222223
resource = session.post(
223224
url=URL, data=data, timeout=BUS_TIMEOUT).json()
225+
if action is True and resource.get("data"):
226+
if resource.get("data").get("startTime"):
227+
resource['busTime'] = re.search(
228+
r"Date\((\d{0,14})\)", resource['data']['startTime']).group(1)
229+
if action is False and resource.get("data"):
230+
if resource.get("data").get("runTime"):
231+
resource['busTime'] = re.search(
232+
r"Date\((\d{0,14})\)", resource['data']['runTime']).group(1)
224233

225234
except requests.exceptions.Timeout:
226235
return error_code.BUS_TIMEOUT_ERROR
@@ -229,7 +238,7 @@ def book(session, kid, action=True):
229238

230239
return resource
231240

232-
241+
233242
def get_violation_records(session):
234243
"""get user violation records list.
235244
@@ -270,5 +279,3 @@ def get_violation_records(session):
270279

271280
data.append(temp)
272281
return data
273-
274-

src/utils/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
CACHE_SEMESTERS_EXPIRE_TIME = 3600
4444
CACHE_GRADUTION_EXPIRE_TIME = 3600
4545
CACHE_LEAVE_LIST_EXPIRE_TIME = 3600
46-
CACHE_BUS_USER_RESERVATIONS = 60
46+
CACHE_BUS_USER_RESERVATIONS = 600
4747
CACHE_WEBAP_QUERY_DEFAULT_EXPIRE_TIME = 600
4848
CACHE_BUS_VIOLATION_RECORD_EXPIRE_TIME = 600
4949
CACHE_SEMESTERS_EXPIRE_TIME = 3600

0 commit comments

Comments
 (0)