Enjoy this hell of a script I made, completely unreadable, and will most likely break sometime, but rn, it works perfectly
Linusx
Posted on September 8, 2024
import csv
import bs4
import twill.commands as twill
from twill import browser
from login_stuff import secrets
timetable_url = 'https://ergogym.eltern-portal.org/service/stundenplan'
def get_html():
twill.go(timetable_url)
twill.form_value(1,'username', secrets['username'])
twill.form_value(1,'password', secrets['password'])
twill.submit(1)
twill.go(timetable_url)
return browser.html
html = get_html()
soup = bs4.BeautifulSoup(html, 'html.parser')
def get_courses(html):
course_table = [table for table in soup.find_all('table') if 'Kurse' in table.text][0]
courses = [course.text.split(',')[0] for course in course_table.find_all('td') if ',' in course.text]
return courses
def parse_to_room_dict(field_string):
# Split the string into two parts: the identifiers and the numbers
identifiers_part, numbers_part = field_string.strip().split('\n')
# Split both parts into individual elements
identifiers = identifiers_part.split('/')
numbers = numbers_part.split('/')
# Create the dictionary by zipping the identifiers with the numbers
result_dict = dict(zip(identifiers, numbers))
return result_dict
def find_course_room(courses_dict, my_courses):
# Find the intersection between the keys of the dictionary and the list of courses
intersection = set(courses_dict.keys()) & set(my_courses)
if len(intersection) > 0:
course = intersection.pop() # Get the only course that's common
room = courses_dict[course] # Get the room for this course
if room == '':
return course
return f'{course[1:].lower()} - {room}' # Return the formatted string (course, room)
return None
def get_timetable(html, courses=get_courses(html)):
timetable = [table for table in soup.find_all('table') if 'Montag' in table.text][0]
# Create a deep copy of the timetable by converting to a string and re-parsing
timetable_copy = bs4.BeautifulSoup(str(timetable), 'html.parser')
for br in timetable_copy.find_all('br'):
br.insert_before('\n')
timetable_array = [[td.text for td in row.find_all('td')] for row in timetable_copy.find_all('tr')]
timetable_array[0] = ['','Montag','Dienstag','Mittwoch','Donnerstag','Freitag']
for row_id in range(1,len(timetable_array)):
timetable_array[row_id][0] = timetable_array[row_id][0].replace('\n',' ')
for row_idx, row in enumerate(timetable_array):
for col_idx, field in enumerate(row):
if row_idx > 0 and col_idx > 0:
field = timetable_array[row_idx][col_idx]
if '/' in field:
course_room = find_course_room(parse_to_room_dict(field), courses)
if course_room is not None:
timetable_array[row_idx][col_idx] = course_room
else:
timetable_array[row_idx][col_idx] = ''
else:
timetable_array[row_idx][col_idx] = ''
timetable_array = [row for row in timetable_array if any(field != '' for field in row[1:])]
return timetable_array
def save_to_file(timetable_array, courses):
timetable_array.append([])
timetable_array.append(['Kurse:',', '.join(courses)])
with open('timetable.csv', 'w', newline='') as csvfile:
writer = csv.writer(csvfile,delimiter=',')
writer.writerows(timetable_array)
from reportlab.lib.pagesizes import A4, landscape
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph
from reportlab.lib.units import cm
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase import pdfmetrics
def save_to_pdf(timetable_array, courses, width_cm=19, height_cm=11, output='timetable.pdf'):
pdfmetrics.registerFont(TTFont('Inter','InterVariable.ttf'))
pdfmetrics.registerFontFamily('Inter',normal='Inter')
# Convert cm to points
width = width_cm * cm
height = height_cm * cm
doc = SimpleDocTemplate(output, pagesize=landscape(A4))
col_width = width / len(timetable_array[0])
row_height = height / len(timetable_array)
num_cols = len(timetable_array[0])
col_width = width / num_cols
# Calculate new column widths
first_col_width = col_width * 1.3
remaining_col_width = (width - first_col_width) / (num_cols - 1)
# Define table with adjusted column widths and row heights
table = Table(timetable_array,
colWidths=[first_col_width] + [remaining_col_width] * (num_cols - 1),
rowHeights=[row_height] * len(timetable_array))
# Apply table style for borders and larger font size
table.setStyle(TableStyle([
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
('FONTNAME', (0, 0), (-1, -1), 'Inter'), # Use bold font
('FONTSIZE', (0, 0), (-1, -1), 14), # Increase font size
('GRID', (0, 0), (-1, -1), 1, colors.black) # Add gridlines
]))
table.hAlign = 'LEFT'
# Add the courses as a paragraph at the top
styles = getSampleStyleSheet()
course_text = f"Kurse: {', '.join(courses)}"
course_paragraph = Paragraph(course_text, ParagraphStyle(name='CourseParagraph', fontName='Inter', fontSize=12, spaceBefore=cm))
# Build the PDF
doc.build([table, course_paragraph])
if __name__ == '__main__':
courses = get_courses(html)
leopold_courses = ['1k3', '1E', '1M1', '1D1', '1ku1', '1pug4', '1ph2','1ew','1g3','1geo2','1b1','1smw3']
save_to_pdf(get_timetable(html,courses),courses)
save_to_pdf(get_timetable(html,leopold_courses),leopold_courses,output='timetable_leopold.pdf')
💖 💪 🙅 🚩
Linusx
Posted on September 8, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
githubcopilot AI Innovations at Microsoft Ignite 2024 What You Need to Know (Part 2)
November 29, 2024