#!/usr/bin/env python3 # TODO # Распарсить индексник # Сформировать POST # Сделать POST # Забрать результат (готовое расписание) from bs4 import BeautifulSoup import re import requests import sys useragent = "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/112.0" if __name__ == '__main__': print("Hello, fucker, what is ur name?") fucker_name = input() if fucker_name == "": fucker_name = "ты" print("Your group?") stud_group = input() if stud_group == '': print("Введи группу") sys.exit(1) init_url = "https://guap.ru/rasp/" init_headers = { 'User-Agent': useragent } init_html = requests.get(init_url, headers=init_headers) soup = BeautifulSoup(init_html.text.strip(), 'html.parser') # Реверс инжиринг __doPostBack # # # _doPostBack # @param eventTarget # @param eventArgument # E.g.: # # Показать расписание # Я не видел, чтобы eventArgument заполнялось, поэтому оставляем пустым # Т.е. просто заполняет 2 переменные # Реверс POST запроса # Передается вот это: # &__EVENTARGUMENT= # &__VIEWSTATE=%2FwEPDwUKLTkzNTgzNzI3Ng9kFgJmD2Q..... # &__VIEWSTATEGENERATOR=3EAAC6F7 # &_EVENTVALIDATION=%2FwEdAIgLxA5dNdvuvMP6V.... # &ctl00%24cphMain%24ctl05=2 - НОМЕР ГРУППЫ # &ctl00%24cphMain%24ctl06=-1 - ПРЕПОД # &ctl00%24cphMain%24ctl07=-1 - АУДИТОРИЯ (МЕСТО) # &ctl00%24cphMain%24ctl08=-1 - АУДИТОРИЯ (ЗАЛ) # Криптохуйню ищем cryptshits = ( {"name": "__EVENTTARGET", "value": ""}, {"name": "__EVENTARGUMENT", "value": ""}, {"name": "__VIEWSTATE", "value": ""}, {"name": "__VIEWSTATEGENERATOR", "value": ""}, {"name": "__EVENTVALIDATION", "value": ""}, ) for i in cryptshits: val = soup.find('input', {"id": i['name']}) i['value'] = val.get('value') # Теперь нам надо распарсить список групп и найти нужную rasp = soup.find('div', {"class": "rasp"}) rasp_div_form = rasp.find('div', {"class": "form"}) groups = list() group_keyword = "группа:" for i in rasp_div_form.find_all('span'): group_html_block = i.find(string=re.compile(group_keyword)) if group_html_block is None: break else: for group in group_html_block.parent.findAll('option'): if group.get('value') != "-1": groups.append({ "name": group.contents[0], "value": group.get('value') }) # Формируем POST data post_data = dict() # Заполняем дату криптохуйней for i in cryptshits: post_data[i['name']] = i['value'] # Ищем группу for group in groups: if group['name'] == stud_group: post_data['ctl00%24cphMain%24ctl05'] = group['value'] # Заполняем как есть, нам это не интересно post_data["&ctl00%24cphMain%24ctl06"] = -1 post_data["&ctl00%24cphMain%24ctl07"] = -1 post_data["&ctl00%24cphMain%24ctl08"] = -1 post_headers = {"Content-Type": "application/x-www-form-urlencoded", 'User-Agent': useragent} post_url = "https://guap.ru/rasp/?g={}".format(post_data['ctl00%24cphMain%24ctl05']) post_result = requests.post(post_url, data=post_data, headers=post_headers) # Парсим полученные данные soup_result = BeautifulSoup(post_result.text, 'html.parser') # В переменную записываем само расписание, без остальной страницы rasp_html = soup_result.find('div', {'class', 'result'}) rasp_summary = list() # Пример rasp_summary # ( # { # "date": "Понедельник", # "value": ( # { # "time": "1 пара (9:30–11:00)", # "type": "ПР", # "name": "– Прикладная физическая культура (элективный модуль)", # "profs": ( # "Алексеева С.В. - старший преподаватель" # ), # "groups": ( # 1011, # 1012 # ), # "place": "– Б.Морская 67, ауд. спортзал*", # "up_or_down": 'none' # } # ) # } # ) # Верхняя - нечетная неделя # Нижняя - четная неделя # Верстка сайта на высоте. Придется использовать next_siblings. Хвататься не за что. rasp_html_inside = rasp_html.find('div') # Это будет ужасно... cur_day = "" cur_lesson = "" day_iterator = 0 groups = list() for cur_sibl in rasp_html_inside.find_next_siblings(): tag_type = cur_sibl.name match tag_type: case 'h2': # Header, пропускаем print(cur_sibl.text) case 'h3': # День недели if cur_day == '' and cur_day != cur_sibl.text and day_iterator == 0: cur_day = cur_sibl.text elif cur_day != '' and cur_day != cur_sibl.text: day_iterator += 1 cur_day = cur_sibl.text case 'h4': # какая пара cur_lesson_time = cur_sibl.text case 'div': # Что за пара, препод, место, аудитория # Верхняя или нижняя? up_or_down = 'none' if cur_sibl.find('b', {'class': 'up'}): up_or_down = 'up' if cur_sibl.find('b', {'class': 'dn'}): up_or_down = 'down' # Тип пары (лекция) lesson_type = cur_sibl.find('b', {'class': ''}) # Что за пара lesson_name = lesson_type.next_sibling # Препод preps = list() preps_block = cur_sibl.find('span', {'class': 'preps'}) if preps_block is not None: for prep in preps_block.findAll('a'): preps.append(prep.text) # Группы groups = list() group_block = cur_sibl.find('span', {'class': 'groups'}) for group in group_block.findAll('a'): groups.append(group.text) # место, аудитория place = cur_sibl.find('em') # Итого, пишем в rasp_summary temp_list_para = { "time": cur_lesson_time, "type": lesson_type.text, "name": lesson_name, "profs": preps, "groups": groups, "place": place.text, "up_or_down": up_or_down } temp_dict = { "date": cur_day, "value": temp_list_para } rasp_summary.append(temp_dict) case _: print('wtf') from datetime import date import locale locale.setlocale(locale.LC_TIME, "ru_RU.UTF-8") today_weekday = date.today().strftime('%A') today_week = int(date.today().strftime('%U')) print("Сегодня {}, {} был на:".format(today_weekday, fucker_name)) for para in rasp_summary: if para['date'] == today_weekday: if para['value']['up_or_down'] == 'up' and today_week % 2 != 0: print(para['value']['type'], para['value']['name']) elif para['value']['up_or_down'] == 'down' and today_week % 2 == 0: print(para['value']['type'], para['value']['name']) elif para['value']['up_or_down'] == 'none': print(para['value']['type'], para['value']['name'])