Skip to content

Instantly share code, notes, and snippets.

@opabravo
Last active May 16, 2022 06:54
Show Gist options
  • Save opabravo/796f8bd4e73d02eef5d71f7718fef078 to your computer and use it in GitHub Desktop.
Save opabravo/796f8bd4e73d02eef5d71f7718fef078 to your computer and use it in GitHub Desktop.
tip 自動請假
from bs4 import BeautifulSoup
import requests
import re
from datetime import date as now_date
from getpass import getpass
# from icecream import ic
class Tip:
HEADERS = {"Cache-Control": "max-age=0", "Upgrade-Insecure-Requests": "1",
"Origin": "https://netinfo.takming.edu.tw/tip/",
"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/87.0.4280.88 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"Referer": "https://netinfo.takming.edu.tw/tip/stu_absrec.php", "Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-TW,zh;q=0.9,en-US;q=0.8,en;q=0.7", "Connection": "close"}
def __init__(self, user, passwd):
self.session = requests.session()
self.user = user
self.passwd = passwd
def login(self):
burp0_url = "https://netinfo.takming.edu.tw/tip/login_xx.php"
burp0_data = {"UserID": self.user, "Passwd": self.passwd, "image.x": "0", "image.y": "0"}
self.session.post(burp0_url, headers=self.HEADERS, data=burp0_data)
def session_vaild(self):
"""Check if cookie is valid to auth"""
if 'cookie_userid' in self.session.cookies:
return True
class Stg(Tip):
PREFIX = "timed=&d1=&d2=&TDate="
SUFFIX = "&StuDate="
ABSREC_URL = "https://netinfo.takming.edu.tw/tip/stu_absrec.php?mode=1"
def __init__(self, user, passwd):
super().__init__(user, passwd)
self.yyy_mm_accepted = ()
self.periods = {}
def periods_update(self, rows:list):
"""Update periods from a page, row by row"""
for row in rows:
data = re.findall(
r"<tr>\s+<td.*font.*>(.*?)</font>.*\s+<td.*font.*>(.*?)</font>.*\s+<td.*font.*>("
r".*?)</font>.*\s+<td.*font.*>(.*?)</font>.*\s+<td.*font.*>(.*?)</font>.*\s+<td.*font.*>("
r".*?)</font>.*\s+</tr>",
row)[0]
date = data[0]
dic = {data[2]: data[4]} # 節次 : 課程代號
if date[:5] not in self.yyy_mm_accepted:
return
if data[3] != "曠課":
continue
self.periods.setdefault(date, {}).update(dic)
def set_valid_yyy_mm(self):
"""Calculate and set two valid yyy_mm"""
today = str(now_date.today()).split("-")
this_year = f"{int(today[0]) - 1911}"
this_month = f"{today[1]}"
month_previous = str(int(this_month) - 1) if int(this_month) > 10 else f"0{int(this_month) - 1}"
yyy_mm_previous = f"{int(this_year) - 1}12" if this_month == "01" else this_year + month_previous
self.yyy_mm_accepted = yyy_mm_previous, this_year + this_month
def req(self, page_num=1) -> str:
"""Send request to stu_stg01 endpoint"""
r = self.session.get(f"{self.HEADERS['Origin']}stu_stg01.php?page_num={page_num}&RgNo={self.user}",
headers={
"Referer": f"{self.HEADERS['Origin']}list_fun.php?flag=1&item=07&funitem=&Type=2"})
r.encoding = r.apparent_encoding
return r.text
def fetch(self):
"""Fetch stg records from pages"""
self.set_valid_yyy_mm()
page_num = 1
while 1:
page_source = self.req(page_num)
rows = re.findall(r"<tr>\s+<td.*>\s+<td.*>\s+<td.*>\s+<td.*>\s+<td.*>\s+<td.*>\s+</tr>", page_source)
if len(rows) == 0: # 沒有紀錄
return periods
self.periods_update(rows)
if f'page_num={page_num + 1}&' not in page_source: # 到底
break
page_num += 1
def bulk_absrec(self, periods: dict):
"""
timed=&d1=&d2=&TDate=1100330&AbsType=2&T13=D920604&T14=D920604&T16=D932306&T17=D932306 # Example URI
{"3":"D920604", "4":"D920604"} # 節次 : 課程代號
"""
for date in periods:
parms = [f"&T1{k}={v}" for k, v in periods[date].items()]
data = f"{self.PREFIX}{date}&AbsType=2{''.join(parms)}{self.SUFFIX}"
self.session.post(self.ABSREC_URL, headers=self.HEADERS, data=data)
def bulk_cancel(self, month: str):
data = f"{self.SUFFIX}&AbsType=&StuDate={month}"
r = self.session.post(self.ABSREC_URL[:-6], headers=self.HEADERS, data=data)
soup = BeautifulSoup(r.text, "html.parser")
table = soup.find("table", attrs={"id": "AutoNumber4"})
for link in table.find_all("a"):
self.session.post(self.HEADERS["Origin"] + link.get("href"), headers=self.HEADERS)
print(f"Purged all absrec in month : {month}")
def main():
user = input("User : ")
passwd = getpass("Password : ")
tip = Stg(user, passwd)
tip.login()
print("Logging in...")
if not tip.session_vaild():
input("Bad creds!")
exit()
tip.fetch()
# ic(periods)
print(tip.periods)
# tip.bulk_cancel("10")
tip.bulk_absrec(tip.periods)
input("\nDone")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment