from getpass import getpass from robobrowser import RoboBrowser from re import compile url = 'https://galilei-cr-sito.registroelettronico.com/' url_main = url + 'news' url_login = url + 'login' url_marks = url + 'votes/?s=' subjects = {} br = RoboBrowser(history=False) def login(user, password): '''Authenticate the user''' br.open(url_login) # Fill in the login form form = br.get_form(id='loginform') form['username'].value = user form['password'].value = password br.submit_form(form) # Check if authenticated if 'errati' in br.response.text: return False return True def means(): '''Compute mean for each subject''' for i in subjects.keys(): yield _mean(list(get_marks(i))) def get_name(): '''Find the student's name from the registry''' br.open(url_main) # Get the content of 'h2' tag with ID 'student_name' name = br.select('h2#student_name')[0].text.split() return ' '.join([name[-1]] + name[:-1]) def get_subjects(): '''Create a reversed dictionary of type (subject, id)''' br.open(url_main) links = br.get_links(href=compile('votes/\?s=\d+')) return {i.text.capitalize(): i.attrs['href'][-7:] for i in links} def get_marks(subject): '''Returned the list of marks for a subject''' br.open(url_marks + str(subjects[subject])) res = br.find_all(text=compile(r'^(\d{1,2}(\+|-|\.\d{1,2})?) ')) return _parse(i[0:-1] for i in res) def _parse(marks): ''' Parse marks into floats: NC -> 0 A -> nothing n+ -> n + 0.25 n- -> n - 0.25 n -> n ''' for i in marks: try: yield float(i) except ValueError: if i == 'A': pass elif i == 'NC': yield 0 elif i[1] == '+': yield float(i[0]) + 0.25 elif i[1] == '-': yield float(i[0]) - 0.25 elif i[2] == '-': yield float(i[:-1]) - 0.25 def _mean(marks): '''Mean of a list of marks''' marks = list(marks) return sum(marks) / len(marks) def _show_means(): '''Show general mean and for each subject [Procedure]''' # Print id, subject, mean for every subject print('Media generale: %.2f' % _mean(means())) for id, (subject, voto) in enumerate(zip(subjects.keys(), means())): print('%d. %s: %.2f' % (id + 1, subject, voto)) def _show_marks(): '''Prompt for a subject and show the marks [Procedure]''' for i, subject in enumerate(subjects.keys()): print('%d. %s' % (i + 1, subject)) while True: print('') id = int(input('Materia: ')) if id in range(15): name = list(subjects.keys())[id - 1] print(name) print('Voti:', *get_marks(name)) print('Media: %.2f' % _mean(get_marks(name))) else: print('Inserire numero corretto!') def main(): # Authentication logged = False while not logged: user, password = input('Username: '), getpass('Password: ') logged = login(user, password) if not logged: print('Autenticazione fallita, riprovare.') print('Connesso come %s.\n' % get_name()) # So we don't need to recompute every time global subjects subjects = get_subjects() # Menu while True: mode = input('Scegli [v]oti o [m]edie: ') print('') if mode == 'v': _show_marks() elif mode == 'm': _show_means() input() if __name__ == '__main__': try: main() except KeyboardInterrupt: print('')