-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
skola-online-znamky.py
155 lines (123 loc) · 5.04 KB
/
skola-online-znamky.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
# Author: Jakub Andrysek
# Website: https://kubaandrysek.cz
# Date: 2023-03-06
# Description EN: Script for downloading marks from SkolaOnLine application
# Description CZ: Skript pro stahování známek z aplikace SkolaOnLine
# Version: 1.0.0
# License: MIT
import re
import requests
from bs4 import BeautifulSoup
from prettytable import PrettyTable
import maskpass
session = requests.Session()
def log_in_sol(user: str, password: str) -> bool:
url: str = 'https://aplikace.skolaonline.cz/SOL/Prihlaseni.aspx'
data = {
"__EVENTTARGET": "dnn$ctr994$SOLLogin$btnODeslat",
"__EVENTARGUMENT": "",
"__VIEWSTATE": "",
"__VIEWSTATEGENERATOR": "",
"__VIEWSTATEENCRYPTED": "",
"__PREVIOUSPAGE": "",
"__EVENTVALIDATION": "",
"dnn$dnnSearch$txtSearch": "",
"JmenoUzivatele": user, # username
"HesloUzivatele": password, # password
"ScrollTop": "",
"__dnnVariable": "",
"__RequestVerificationToken": ""
}
postLogin = session.post(url, data=data)
if postLogin.status_code != 200:
print('Nepodařilo se přihlásit')
return False
else:
print('Pokus o přihlášení proběhl úspěšně')
return True
def scrape_sol_url(params=None) -> str:
base = "https://aplikace.skolaonline.cz"
if params is not None:
base += params
r = session.get(base)
if r.status_code == 200:
return r.text
print('Nepodařilo se stáhnout data')
return ""
def find_marks_in_html(html: str) -> list:
soup = BeautifulSoup(html, 'lxml') # load html to BeautifulSoup object
# xpath //*[@id="ctl00_bodyFooter_boxHodnVypisStud_ctl00_Content"]
table = soup.find('div', id='ctl00_bodyFooter_boxHodnVypisStud_ctl00_Content')
# extract from table all rows
table = table.find('table')
# get all rows
rows = table.find_all('tr')
# get all columns
columns = [row.find_all('td') for row in rows]
# get all marks
marks = []
for row in columns:
marks.append(extract_mark_from_html(row))
return marks
# [<td>Út 10.1.</td>,<td title="Matematika">Matematika</td>,<td><a onclick="window.open('../Hodnoceni/KHO010_HodnVypisDetail.aspx?UdalostID=C37655175&OsobaID=C3023618', 'detail', 'width=430, height=400, resizable, scrollbars')" title="1"><span class="znamka_dobra"><strong>1</strong></span></a></td>]
def extract_mark_from_html(mark_html: str) -> dict:
mark = {
'Datum': mark_html[0].text,
'Předmět': mark_html[1].text,
'Známka': mark_html[2].text,
}
mark.update(extract_mark_details(mark_html))
return mark
# get window.open link and parse it
def extract_mark_details(mark_html: str):
try:
link = mark_html[2].find('a').attrs['onclick']
# "window.open('../Hodnoceni/KHO010_HodnVypisDetail.aspx?UdalostID=C37917700&OsobaID=C3361427', 'detail', 'width=430, height=400, resizable, scrollbars')" to "../Hodnoceni/KHO010_HodnVypisDetail.aspx?UdalostID=C37917700&OsobaID=C3361427"
detail_url = '/SOL/App/' + re.search(r"'...(.*?)'", link)[1]
detail_html = scrape_sol_url(detail_url)
soup = BeautifulSoup(detail_html, 'html.parser')
# //*[@id="tabVysledky"]
table = soup.find('table', id='tabVysledky')
mark_details = {}
for row in table.find_all('tr'):
try:
label = row.find('span', class_='FieldLabel SpaceAfterFieldLabel').text
try:
data = row.find('span', id=re.compile(r'LData.*')).text
except AttributeError:
data = None
mark_details[label.replace(":", "")] = data
except AttributeError:
pass
return mark_details
except AttributeError:
return {}
def scrape_sol_to_file():
html_content = scrape_sol_url("/SOL/App/Spolecne/KZZ010_RychlyPrehled.aspx")
# save to file
with open('htmlContent.html', 'w') as f:
f.write(html_content)
# get mark from file
def load_mark_from_file() -> str:
with open('htmlContent.html', 'r') as f:
return f.read()
def print_pretty_table(marks: list):
table = PrettyTable()
table.field_names = ['Datum', 'Předmět', 'Známka', 'Druh hodnocení', 'Učitel', 'Komentář', 'Slovní hodnocení']
for mark in marks:
table.add_row(
[mark['Datum'], mark['Předmět'], mark['Známka'], mark['Druh hodnocení'], mark['Učitel'], mark['Komentář'],
mark['Slovní hodnocení']])
print(table)
if __name__ == '__main__':
username = input("Zadejte uživatelské jméno: ")
password = maskpass.askpass(prompt="Zadejte heslo: ", mask="*")
log_in_sol(username, password)
scrape_sol_to_file()
html_content = load_mark_from_file()
try :
if html_content is not None:
marks = find_marks_in_html(html_content)
print_pretty_table(marks)
except AttributeError:
print('Nepodařilo se načíst známky ze souboru (pravděpodobně jsi zadal špatné přihlašovací údaje)')