Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
*.log
__pycache__/
__pycache__/
env
*.Identifier
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2021 Adil Mohammed K

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
55 changes: 35 additions & 20 deletions PageLogin.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,45 @@
# Necessary imports
from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.keys import Keys
from getpass import getpass
import no_graph_features as ngf
import graph_features as gf
from course_details import tabulate_course_details
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.chrome.options import Options

options = Options()
options.headless = True

# Specify Path to geckodriver for Firefox
driver = webdriver.Firefox(options=options, executable_path=r"./geckodriver-v0.26.0-linux64/geckodriver")
driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()))

# Navigating to the webpage
driver.get("https://www.iitm.ac.in/viewgrades/")



# Loop prompting correct login details
tried = False
while driver.current_url=="https://www.iitm.ac.in/viewgrades/index.html" or driver.current_url=="https://www.iitm.ac.in/viewgrades/":
while (
driver.current_url == "https://www.iitm.ac.in/viewgrades/index.html"
or driver.current_url == "https://www.iitm.ac.in/viewgrades/"
):

if tried == True:
# Check if it is not the first iteration
print("Incorrect Roll Number and/or Password")

# Locate form fields
rollno = driver.find_element_by_name("rollno")
pwd = driver.find_element_by_name("pwd")
rollno = driver.find_element("name", "rollno")
pwd = driver.find_element("name", "pwd")

roll = input("Enter your roll number:")
password = getpass("Enter your password:")

rollno.send_keys(roll)
pwd.send_keys(password)
driver.find_element_by_name("submit").click()
driver.find_element("name", "submit").click()

tried = True

Expand All @@ -44,28 +49,38 @@


# Intro greeting
name = driver.find_element_by_xpath("/html/body/center/table/tbody/tr/th[3]")
name = driver.find_element("xpath", "/html/body/center/table/tbody/tr/th[3]")
print("Hi,", name.text)

cg = driver.find_element_by_xpath("/html/body/center/center/table[1]/tbody/tr[last()]/td[last()]")
cg = driver.find_element(
"xpath", "/html/body/center/center/table[1]/tbody/tr[last()]/td[last()]"
)
print("Your", cg.text)

courses, sem = tabulate_course_details(driver)
courses, sem, gpas = tabulate_course_details(driver)
driver.close()


choice = ' '
while choice.lower() != 'x':
choice = input('''\nHow do you want you visualize your grades:
choice = " "
while choice.lower() != "x":
choice = input(
"""\nHow do you want you visualize your grades:
a) GPA for courses taken in a specific department

Other features will come soon.
b) Credits per stream in bar chart
c) GPA per semester in bar chart
d) Grade and credits in specific course

Enter x to exit
''')
if choice.lower() == 'a':
"""
)
if choice.lower() == "a":
dept, gpa = ngf.Dept_GPA(courses)
print("Your GPA of the courses done in", dept, "department is", gpa, "\n")
dummy = input('''Press Enter to continue''')


dummy = input("""Press Enter to continue""")
elif choice.lower() == "b":
gf.Credits_stream(courses)
elif choice.lower() == "c":
gf.gpa_graph(gpas)
elif choice.lower() == "d":
course_check = input("Type course number to check: ")
ngf.courseCheck(course_check, courses)
29 changes: 22 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,30 @@
# viewgrades-scraper
# IITM Grades Scraper

An interactive and alternate Command Line visualisation of an IITM student's grades by scraping data from https://www.iitm.ac.in/viewgrades/
Currently requires Firefox and works only on linux
Requires Chrome and can be run on Windows and Linux( also through WSL2)

## Setup

1. Clone the repository onto your system (or download the .zip file and unzip it)
<pre><code>git clone https://github.com/Adil-MohammedK/IITM-viewgrades-scraper.git</code></pre>
2. Navigate to the location where you have cloned/downloaded the code on terminal
3. To install the neccesary packages
`pip install -r requirements.txt`
4. To run the code
`python PageLogin.py`
3. Create virtual environment
<pre><code>python3 -m venv env</code></pre>
4. Activate virtual environment
<pre><code>source env/bin/activate</code></pre>
5. To install the neccesary packages
<pre><code>pip3 install -r requirements.txt</code></pre>
6. To run the code
<pre><code>python3 PageLogin.py</code></pre>

## Features currently available:

1. Displays your CGPA
2. Accepts a department and give the GPA of the courses offered by that department

3. Plot Credits per stream in bar chart
4. GPA per semester in bar chart
5. Find credits and grade for user input course

# Contribution

Some parts of this code is from [Murale127](https://github.com/murale127/viewgrades-scraper). I have changed the requirement from Firefox to Chrome and added few features from where he stopped.
35 changes: 24 additions & 11 deletions course_details.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
def tabulate_course_details(driver):
'''
"""
driver: Webdriver element

returns: Course and Semester details in a tabular format
'''
courses = driver.find_element_by_xpath("/html/body/center/center/table[1]/tbody").text
course_list = courses.split('\n')
"""
courses = driver.find_element(
"xpath", "/html/body/center/center/table[1]/tbody"
).text
course_list = courses.split("\n")

#print(course_list)
# print(course_list)

course_list = [i.split() for i in course_list]

Expand All @@ -18,26 +20,37 @@ def tabulate_course_details(driver):
course_grade = []
credits = []
sem = []
gpas = []

for i in course_list:
if i[0].isnumeric():
course_code.append(i[1])
course_name.append(' '.join(i[2:-4]))
course_name.append(" ".join(i[2:-4]))
course_category.append(i[-4])
course_credits.append(i[-3])
course_grade.append(i[-2])
count += 1 # Number of courses taken in a particular sem
count += 1 # Number of courses taken in a particular sem
elif i[0] == "Earned":
if i[1][-2:].isnumeric():
credits.append((int(i[1][-2:]), count))
if i[2][0:3] == "GPA":
gpas.append(float(i[2][4:]))
else:
credits.append((int(i[1][-1]), count))

if i[2][0:3] == "GPA":
gpas.append(float(i[2][4:]))

else:
count = 0
sem.append(' '.join(i[:]))
sem.append(" ".join(i[:]))

course_summary = (course_code, course_name, course_category, course_credits, course_grade)
course_summary = (
course_code,
course_name,
course_category,
course_credits,
course_grade,
)
sem_summary = (sem, credits)

return course_summary, sem_summary
return course_summary, sem_summary, gpas
Binary file removed geckodriver-v0.26.0-linux64/geckodriver
Binary file not shown.
59 changes: 59 additions & 0 deletions graph_features.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import numpy as np
import pandas as pd
from pandas import Series, DataFrame
import matplotlib.pyplot as plt


def addlabels(x, y):
for i in range(len(x)):
plt.text(i, y[i], y[i], ha="center")


def Credits_stream(courses):
# plt.savefig("mygraph.png")
count_eng = 0
count_pro = 0
count_sci = 0
count_hum = 0
credit_eng = 0
credit_pro = 0
credit_sci = 0
credit_hum = 0
for i in range(len(courses[0])):
# print (courses[2][i])
if courses[2][i] == "Engineering":
count_eng = count_eng + 1
credit_eng = credit_eng + int(courses[3][i])
elif courses[2][i] == "Professional":
count_pro = count_pro + 1
credit_pro = credit_pro + int(courses[3][i])
elif courses[2][i] == "Science":
count_sci = count_sci + 1
credit_sci = credit_sci + int(courses[3][i])
elif courses[2][i] == "Humanities":
count_hum = count_hum + 1
credit_hum = credit_hum + int(courses[3][i])
data = [credit_eng, credit_pro, credit_sci, credit_hum]
labels = ["Engineering", "Professional", "Science", "Humanities"]
addlabels(labels, data)
plt.xticks(range(len(data)), labels)
plt.xlabel("Category")
plt.ylabel("Credits")
plt.title("title")
plt.bar(range(len(data)), data)
plt.show()


def gpa_graph(gpas):
labels = []
for i in range(len(gpas)):
# print(gpas[i])
labels.append("Sem " + str(i))
data = gpas
addlabels(labels, data)
plt.xticks(range(len(data)), labels)
plt.xlabel("Semester")
plt.ylabel("GPAs")
plt.title("title")
plt.bar(range(len(data)), data)
plt.show()
35 changes: 29 additions & 6 deletions no_graph_features.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
grade2point = {"S":10, "A":9, "B":8, "C":7, "D":6, "E":4, "U":0, "I":0, "W":0}
grade2point = {
"S": 10,
"A": 9,
"B": 8,
"C": 7,
"D": 6,
"E": 4,
"U": 0,
"I": 0,
"W": 0,
}


def Dept_GPA(courses):
'''
"""
course: summary of the courses obtained from the webpage

returns: GPA of the required department
'''
"""
while True:
dept = input("Enter the department code: ")
total_credits = 0
total_credits = 0
total_points = 0
for i in range(len(courses[0])):
if courses[0][i][:2] == dept:
Expand All @@ -17,6 +28,18 @@ def Dept_GPA(courses):
total_credits += float(courses[3][i])
except:
pass
gpa = round(total_points/total_credits, 2)
gpa = round(total_points / total_credits, 2)

return dept, gpa


return dept, gpa
def courseCheck(name, courses):
flag = False
for i in range(len(courses[0])):
if courses[0][i] == name:
print("Course name is " + courses[1][i])
print("Your grade in " + name + " is: " + courses[4][i])
print("Your credits in " + name + " is: " + courses[3][i])
flag = True
if flag == False:
print("No such course found")
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[tool.black]
line-length = 85
target-version = ['py39']
6 changes: 5 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
selenium
selenium
numpy
pandas
matplotlib
webdriver-manager