Created
January 24, 2024 11:31
-
-
Save TheFlash2k/91361979c8873b2a8263c81427f051ee to your computer and use it in GitHub Desktop.
Extract result of students of AU based on their roll numbers (Individual, Multiple and Range-based)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import requests | |
from bs4 import BeautifulSoup | |
from urllib.parse import unquote | |
import argparse | |
import re | |
import json | |
from tabulate import tabulate | |
from pprint import pprint | |
def parse(content: str) -> dict: | |
details = {} | |
soup = BeautifulSoup(content, 'html.parser') | |
student_details = soup.find(attrs={'id':'AUContent_DataList1'}) | |
attrs = [i.strip() for i in re.findall(r'<b>(.*?)</b>', str(student_details))] | |
if not attrs: return {} | |
details["rollnumber"], details["name"], details["class"] = attrs | |
course_details = soup.find(attrs={'id':'AUContent_GridView1'}) | |
attrs = [ | |
i.replace('</td>', '|').replace('<td>', '').strip().split('|')[:-1] | |
for i in re.findall(r'Black;">(.*?)\n', str(course_details))] | |
details["courses"] = { | |
i[0]: { # Course Name | |
"grade": i[1], | |
"credit-hours": i[2] | |
} for i in attrs | |
} | |
details["gpa"] = re.findall('>(.*?)<',str(soup.find(attrs={'id': 'AUContent_lbl_gpa'})))[0] | |
return details | |
def get_result(rollno: int) -> dict: | |
response = requests.post( | |
'https://portals.au.edu.pk/auresult/', | |
headers={ | |
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8', | |
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', | |
}, data={ | |
'ctl00$AUContent$ScriptManager1': 'ctl00$AUContent$searchupdatepanel|ctl00$AUContent$btnShow', | |
'ctl00$AUContent$txt_regid': str(rollno).replace(' ', ''), | |
'__VIEWSTATE': 'AfMz+9qUKSr/TJeFzIg4vhcdxHIN3WrjhvZwFsT46ISeCqURNZ2Fza3GJWfuC9X9shEfMkXdkEupKF6SF595wS5FQlr+49P4zitPGnTVNFfRykB2+cXm+k89PczTYJASIXGvCKWKsw+HBlDZZwn+MsGVFClDzCAat267sBRuMaLlq6X0TcQ4BM4uPbie0i7PPkSHdMNoZ/s/fRn3T4AuxAApxY+8aoeEdLreQS3FOVDCwxx26sCMSZjXUU7K0B+vx5k048BJcD+FzWDpSZL0XAItfjSSs1lzHBPh/6D/p7czJ3g06uK1YwidYK9rLOTVT5JuHJ3ZagHWJCDFDQOXyQzAN2E1GerX8xgxIT7sGk/Jvh8NeiGN441YnN9XVSQh', | |
'ctl00$AUContent$btnShow': 'Search Result', | |
}) | |
return parse(content=response.text) | |
def run(rollno: str): | |
data = get_result(i) | |
if not data: | |
print(f"[!] Unable to extract result of {rollno}") | |
return | |
if args.output == "table": | |
table = [['Name:', data['name']], | |
['Roll Number:', data['rollnumber']], | |
['GPA:', data['gpa']], | |
['Class:', data['class']], | |
['', '', ''], # Empty row for separation | |
['Course', 'Credit Hours', 'Grade']] | |
for course, details in data['courses'].items(): | |
table.append([course, details['credit-hours'], details['grade']]) | |
tbl = tabulate(table, tablefmt='grid') | |
print(tbl) | |
else: | |
pprint(data) | |
if args.outfile: | |
try: | |
with open(args.outfile, "a") as f: | |
f.write(str(result).replace('"', '"') + '\n') # stupid json error | |
except: | |
print("[!] An error occurred while trying to access the file.") | |
if __name__ == "__main__": | |
parser = argparse.ArgumentParser(description="Extract results of AU student(s)") | |
parser.add_argument('-r', '--roll-number', help="Roll number(s) of the student you want to extract result of [Can be a comma seperated list]", type=lambda x: x.strip().split(','), dest="rollnos") | |
parser.add_argument('--range', help="Specify a range (inclusive) (Example: 190700-190764) to extract results of. Can also be (190700-190764-2) which will extract every 2nd roll number", dest="ranges") | |
parser.add_argument("-t", "--output-type", help="Specify the type of output you want.", choices=["json", "table"], default="table", dest='output') | |
parser.add_argument("-o", "--output-file", help="Specify the output file name (output stored in json format)", dest="outfile") | |
args = parser.parse_args() | |
if not args.rollnos and not args.ranges: | |
print("[!] Please specify either -r or --range") | |
exit(1) | |
if args.outfile: | |
print(f"[*] Storing output in {args.outfile}") | |
try: open(args.outfile, "w") | |
except: | |
print(f"[!] Unable to access {args.outfile}.") | |
args.outfile = None | |
if args.ranges: | |
try: ranges = [int(i) for i in args.ranges.split('-')] | |
except: ranges = [] | |
if len(ranges) < 2 or len(ranges) > 3: | |
print('[!] Invalid range specified!') | |
exit(1) | |
begin = ranges[0] | |
end = ranges[1] | |
if(len(ranges) == 3): diff = ranges[2] | |
else: diff = 1 | |
print(f"[*] Extracting result between {begin} and {end}") | |
for i in range(begin, end+1, diff): | |
run(i) | |
else: | |
print(f"[*] Extracting result(s) of {','.join(args.rollnos)}") | |
for i in args.rollnos: | |
run(i) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
argparse | |
tabulate | |
beautifulsoup4 | |
requests |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage:
You need to install the libraries:
python3 au-result.py -r roll_number # Example: python3 au-result.py -r 190792