247 lines
9.0 KiB
Python
247 lines
9.0 KiB
Python
#!/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
|
||
#
|
||
# <script type="text/javascript">
|
||
# //<![CDATA[
|
||
# var theForm = document.forms['Form1'];
|
||
# if (!theForm) {
|
||
# theForm = document.Form1;
|
||
# }
|
||
# function __doPostBack(eventTarget, eventArgument) {
|
||
# if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
|
||
# theForm.__EVENTTARGET.value = eventTarget;
|
||
# theForm.__EVENTARGUMENT.value = eventArgument;
|
||
# theForm.submit();
|
||
# }
|
||
# }
|
||
# //]]>
|
||
# </script>
|
||
|
||
# _doPostBack
|
||
# @param eventTarget
|
||
# @param eventArgument
|
||
# E.g.:
|
||
# <a href="javascript:__doPostBack('ctl00$cphMain$ctl09','')">
|
||
# Показать расписание
|
||
# Я не видел, чтобы 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'])
|