Привет, Хабр. Это моя первая статья, и сегодня я хочу рассказать вам про свой первый модуль на python. Называется он dnevnikru. Я написал его для облегчения работы с сайтом дневника. Работает модуль по принципу парсера, а не получает данные через API.

Идея написать такой модуль пришла мне после идеи написать телеграм бота для просмотра оценок и домашних заданий из Дневника.ру, так как смотреть успеваемость в телефоне с браузера неудобно, а функционал приложения платный.

Почему не через API?

Это сделано потому что Администрация Дневника отказывает разработчикам в предоставлении доступа к API.

Конечно, функционал этого модуля не сравнится с функционалом, предоставляемым официальным API. Я добавил только самые необходимые функции, о которых я расскажу ниже.

Как этим пользоваться?

Сам модуль находится в github репозитории. Также, я залил модуль на PyPi. Для установки нужно прописать в терминале:

pip install dnevnikru

Мануал по использованию и описание методов есть на wiki странице

Доступные методы

На момент написания статьи, я реализовал 5 методов.

  • homework - Получение домашних заданий за определенный период

  • marks - Получение оценок за четверть (семестр)

  • searchpeople - Поиск людей по Вашей школе (Среди учителей, учеников, работников. Можно искать по имени, классу, ФИО)

  • birthdays - Дни рождения людей из Вашей школы

  • week - Возвращает результаты недели (расписание, посещаемость, пройденные темы и так далее)

Подробнее о методах:

homework

Принимает 4 необязательных параметра

datefrom - С какой даты отобразить Д/З (в формате dd.mm.yyyy). По умолчанию стоит текущий день.

dateto - До какой даты отобразить Д/З (в формате dd.mm.yyyy). По умолчанию +10 дней к datefrom

days - На сколько дней вперед отобразить (Используется когда ни datefrom, ни dateto не указаны, либо когда указан только datefrom)

studyYear - учебный год (Используется для просмотра домашних заданий прошлых лет)

Возвращает словарь с домашними заданиями.

Пример
from dnevnikru import Dnevnik
from pprint import pprint
dn = Dnevnik(login="login", password="password")
pprint(dn.homework(days=2))
{'homeworkCount': 9,
 'homework': (('Алгебра и НА', 'п.1', 'Сегодня 2 урок'),
              ('Алгебра и НА', 'п.2', 'Сегодня 2 урок'),
              ('Геометрия', 'п.52', 'Сегодня 4 урок'),
              ('Инф. и ИКТ', '§1.8.3, с.92-94', 'Сегодня 5 урок'),
              ('Инф. и ИКТ', '§1.8.3, с.94-95', 'Сегодня 5 урок'),
              ('Алгебра и НА',
               'п.2 № № 8, 11, 12,16,чет 19 (2)',
               '21 октября 2021 3 урок'),
              ('Геометрия',
               '№ 456 разобрать№ 455, 457, 462',
               '21 октября 2021 4 урок'),
              ('Рус. язык',
               'Пар.79-80.Словарный диктант.Приложение 2.(абажур-алюминий).',
               '21 октября 2021 5 урок'),
              ('Род.язык',
               'Итоговое по первому направлению!Сочинение!Принести черновик!',
               '21 октября 2021 6 урок'))}
marks

Принимает 2 необязательных параметра

index - Год обучения. По умолчанию вернется текущий год

period - Период. Если ничего не передать - вернется текущий период.

Возвращает кортеж списков с оценками, количеством пропусков, пропусков по болезни и вообще все данные, которые отображает таблица

Пример
from dnevnikru import Dnevnik
from pprint import pprint
dn = Dnevnik(login="login", password="password")
pprint(dn.marks())
(['1', 'Алгебра и НА', '555', '0', '6', '3', '2', ''],
 ['2', 'Англ. язык', '555', '0', '6', '2', '4,5', ''],
 ['3', 'Биология', '', '0', '0', '0', '', ''],
 ['4', 'Геометрия', '555', '0', '4', '3', '4', ''],
 ['5', 'Инф. и ИКТ', '555', '0', '10', '6', '', ''],
 ['6', 'ИПД', '555', '0', '2', '1', '', ''],
 ['7', 'История', '555', '0', '3', '2', '3', ''],
 ['8', 'Литература', '555', '0', '15', '2', '', ''],
 ['9', 'ОБЖ', '555', '0', '1', '1', '5', ''],
 ['10', 'Реш. физ. задач', '555', '0', '2', '1', '', ''],
 ['11', 'Реш.задач по матем', '555', '0', '2', '1', '', ''],
 ['12', 'Род.язык', '555', '0', '1', '1', '', ''],
 ['13', 'Рус. язык', '555', '0', '2', '1', '4', ''],
 ['14', 'Физика', '555', '0', '14', '6', '3,5', ''],
 ['15', 'Физкультура', '555', '0', '8', '3', '', ''],
 ['16', 'Химия', '555', '0', '4', '1', '', ''])

Отметки находятся только во 2 элементе (Начиная с 0 элемента)

searchpeople

Принимает 3 необязательных параметра

group - Группа среди которой нужно искать людей. По умолчанию пустое значение, будет искать среди всех (all). Доступные группы - 'all', 'students', 'staff', 'director', 'management', 'teachers', 'administrators'

name - Поиск по имени. Можно вводить имя, фамилию, ФИО. Разные форматы.

grade - Поиск по классу. Опять же, можно использовать разные форматы. Например: "11Б", "8 Г", "9.1" - для тех, у кого в школе не буквы, а цифры.

Возвращает словарь с людьми

Пример
from dnevnikru import Dnevnik
from pprint import pprint
dairy = Dnevnik("login", "password")
birthdays = dairy.birthdays(day=9, month=5)
{'peopleCount': 8,
 'people': (('З***а Александра Сергеевна', 'Ученик'),
            ('К***в Александр Юрьевич', 'Родитель'),
            ('К***а Юлия Александровна', 'Ученик'),
            ('К***в Андрей Александрович', 'Родитель'),
            ('К***а Елена Александровна', 'Родитель'),
            ('С***я Ольга Александровна', 'Родитель'),
            ('С***а Александр Иванович', 'Ученик'),
            ('С***а Иван Александрович', 'Родитель'))}

Фамилии скрыл в целях конфиденциальности

birthdays

Принимает 3 необязательных параметра

day (int) - день (по умолчанию текущая дата)

month (int) - месяц

group - Группа среди которой нужно искать людей. По умолчанию пустое значение, будет искать среди всех (all). Доступные группы - 'all', 'students', 'staff', 'class'

Пример
from dnevnikru import Dnevnik
from pprint import pprint
dairy = Dnevnik("login", "password")
birthdays = dairy.birthdays(day=9, month=5)
{'birthdaysCount': 3,
 'birthdays': ('П***в Александр Павлович',
               'К***а Софья Михайловна',
               'П***в Ярослав Иванович')}
week

Позволяет получить результаты недели (информация берется от сюда http://dnevnik.ru/currentprogress/choose?userComeFromSelector=True)

Принимает 2 необязательных параметра:

info - тип результатов (Доступные типы - "themes", "attendance", "marks", "schedule", "homeworks") (По умолчанию schedule, т.е. расписание)

weeks - Сдвиг по неделям (По умолчанию 0, т.е. текущая неделя. Для прошедших недель используется отрицательное число)

Пример
from dnevnikru import Dnevnik
from pprint import pprint
dairy = Dnevnik("login", "password")
schedule = dairy.week()
{'student': 'Владимир Путин, МБОУ СОШ № 1, 7-А, 2021 / 2022, с 18.10 по '
            '24.10',
 'schedule': {'понедельник': ('Реш. физ. задач',
                              'Англ. язык',
                              'Реш.задач по матем',
                              'Химия',
                              'Физика'),
              'вторник': ('Физика',
                          'Физика',
                          'Литература',
                          'Литература',
                          'История',
                          'Физкультура'),
              'среда': ('История',
                        'Алгебра и НА',
                        'Физкультура',
                        'Геометрия',
                        'Инф. и ИКТ',
                        'Инф. и ИКТ'),
              'четверг': ('Физика',
                          'Физика',
                          'Алгебра и НА',
                          'Геометрия',
                          'Рус. язык',
                          'Род.язык'),
              'пятница': ('Англ. язык',
                          'ИПД',
                          'Алгебра и НА',
                          'Алгебра и НА',
                          'Литература',
                          'Физкультура'),
              'суббота': ('Физика',
                          'Англ. язык',
                          'ОБЖ',
                          'Инф. и ИКТ',
                          'Инф. и ИКТ'),
              'воскресенье': ()}}

Итог

Для меня эта библиотека стала первым опытом написания «открытых» проектов, поэтому, если Вы обнаружили какие-то баги/некачественный код/ и прочее, что можно исправить - сообщайте. Я буду только рад улучшить свой проект. Всем удачи.

UPD: Библиотека периодически обновляется, поэтому актуальная информация доступна на wiki странице библиотеки

Комментарии (18)


  1. protobuf
    01.10.2021 04:19
    -1

    Возможно лучше воспользоваться assert'ом?

    if len(datefrom) != 10 or len(dateto) != 10:
        raise DnevnikError("Неверно указаны dateto или datefrom", "Parameters error")
    if str(studyyear) not in datefrom:
        raise DnevnikError("StudyYear должен соответствовать datefrom", "Parameters error")


    Невероятно

    choose = '%D0%9F%D0%BE%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D1%8C'


    :wow:

    subject = [i[2],
      i[0].replace('\n\r\n                        ', '').replace(
          '\r\n                    \n', ''),
      i[3].replace('\n\n', '').replace('\xa0', ' ').replace('\r\n        \t\t\t ', '').replace(
         '\r\n                \r\n\t\t\t\t    \n', '')]


    И ещё 100500 пунктов...

    В общем, реализация - :crap:, а идея хорошая


    1. paracosm17 Автор
      01.10.2021 05:33
      +2

      Спасибо за фидбэк! Буду исправлять


      1. shibanovan
        01.10.2021 07:41
        +1

        Не обращайте внимания, человек выше просто самоутвержиться за ваш счет решил.

        Спасибо за то что выложили в открытый доступ - тоже хотел парсить, но у них там структура конечно адская для парсинга, я открыл - посмотрел и закрыл)


        1. protobuf
          01.10.2021 10:04
          +5

          Вчера думал, что автор троллирует всех, но потом узнал, что это 12ти летний парень, который код скорее всего пишет впервые. Порицаю себя за вчерашний коментарий. Автор большой молодец! Желаю чтобы автор не переставал развиваться и всё у него прокнуло с библиотекой


      1. ivankuzin
        03.10.2021 08:35

        Отличное работа, сам занимался подобным в начале карьеры разработчика.

        А для того, чтобы писать красивый код, с эффективным использованием функционала языка, советую прочитать пару книг по разработке, я бы выбрал "A byte of Python". По моему мнению - лучшая для новичка.


    1. amalchuk
      01.10.2021 07:42

      Насчёт assert'ов возражу, при отключённом режиме отладки (например, при запуске с ключом -O2) assert'ы не будут делать ничего от слова совсем.


  1. StepanSkryabin
    01.10.2021 04:19

    О круто, сам уже пару месяцев парсер делаю для этого поделия (dnevnik.ru). Какие планы на развитие проекта?


    1. paracosm17 Автор
      01.10.2021 07:48

      Пока что буду фиксить некачественный код по советам Хабровчан из комментариев. Потом буду придумывать новые методы и расширять функционал. Вот мне там ниже рассказали о /currentprogress/choose?userComeFromSelector=True

      Попробую с помощью этого какой-нибудь новый метод написать. Например, для просмотра результатов недели


      1. StepanSkryabin
        01.10.2021 12:54

        я надеюсь пулл-реквесты на гитхабе приветствуются? а то я хотел бы поучаствовать в разработке (насколько моих знаний хватит).


        1. paracosm17 Автор
          01.10.2021 13:20

          Конечно приветствуются! Я только за


  1. Trig3G
    01.10.2021 07:05

    Реализация конечно никуда не годится.

    И самое главное там же есть доступ просто к гос. услуге по информации успеваемости /currentprogress/choose?userComeFromSelector=True открывается в плоскую страницу, также имеет все оценки и информацию о ДЗ. Парсить её куда проще.


    1. paracosm17 Автор
      01.10.2021 07:06

      Не знал об этой услуге. Спасибо, что рассказали. Попробую добавить метод для просмотра результатов недели


  1. SkillZQ
    01.10.2021 10:40

    Не могу утверждать, но скорее всего приложение дневник ру общается с сервером по нормальному апи. Если нужно - могу посмотреть и скинуть запросы


    1. MerQ
      01.10.2021 14:49

      Приложение в бесплатном виде не показывает ни оценок (не точно, давно не проверял), ни домашнее задание (это точно). Так что его нормальное апи тут не поможет.


      1. SkillZQ
        01.10.2021 21:55

        Если в платном виде показывает - значит апи для этого есть. Ну, а скачать всегда можно на 4pda


  1. StepanSkryabin
    01.10.2021 13:00

    И претензия к тексту статьи - неплохо бы код оформить "как код", т. е. с подсветкой синтаксиса, и вообще мне кажется не очень удобным расположение описания методов в спойлерах.


    1. paracosm17 Автор
      01.10.2021 13:29

      Не могли бы Вы, пожалуйста, подсказать как с подсветкой оформить?


      1. paracosm17 Автор
        01.10.2021 14:07

        А, всё, разобрался