Skip to content

Для авторов новых плагинов

Artem edited this page Sep 4, 2022 · 5 revisions

Про эту инструкцию

Инструкция написана чтобы на старте ответить на основные вопросы.
Т.к. пока желающих писать собственные плагины не сказать что очень много мне в большинстве случаев на вопросы по написанию плагинов проще ответить лично, чем заниматься написанием серьезной инструкции. По тем же причинам я пока не обдумывал серьезно как быть если плагинов и авторов будет слишком много и нужно будет это как-то аккуратно разрешать от конфликтов. Появиться такая проблема - будем думать.
Пока конфликты решаю вручную, изменения и новые плагины принимаются в виде pull request от авторов в ветку dev
Если же Вы хотите сделать плагин, но категорически не хотите разбираться с гитом (что на мой взгляд зря) - то это менее желательный вариант, но присылайте тогда в личку добавлю самостоятельно.

Структура плагинов

Плагины - это программа на питоне - файл, расположенный в папке mbplugin/plugin, содержащий функцию:

def get_balance(login, password, storename=None, **kwargs):
    result = {'Balance': 124.45}
    return result

Простые плагины

Пример простого плагина и возвращаемые параметры можно посмотреть в файле mbplugin/plugin/test1.py
Если Вы хотите получить какие-то данные с веб страницы и вариант просто воспользоваться библиотеками типа request, примеры такого использования можно найти например в плагинах megafon или avtodor-tr

Плагины для получения данных через браузер, использующие Playwright

Если Вы хотите получить какие-то данные с веб страницы и вариант просто воспользоваться библиотеками типа request Вам по каким-то причинам не подходят, то можно воспользоваться playwright. В принципе никто не мешает пользоваться им напрямую, но я реализовал основную часть рутины в классе BrowserController, для упрощения использования на типичных сайтах, что позволяет в большинстве случаев написать плагин буквально за 10 строчек кода. Пример такого плагина смотрите в mbplugin/plugin/test1.py
Собственно все плагины являются примерами и вполне можно в коде посмотеть как что реализовано и утянуть идеи в свой плагин. Только советую не начинать изучение с плагинов МТС и Теле2 они получились довольно навороченными в силу ряда особенностей и на старте понять как что там сделано будет трудно.

Логон

Т.к. в основном все страницы в окне логона довольно похожи, то для того чтобы понять куда писать логин и пароль хватит универсальных тэгов.
Они описаны в структуре default_logon_selectors в файле mbplugin/plugin/browsercontroller.py
Все уточнения проводим открыв окно логона в браузере и запустив отладчик.
Если какие-либо из них не подходят (самые распространенные причины - поле логина не находится по type=text или кнопка submit как то замысловато обнаруживается) - то создаем словарь user_selectors с теми значениями, которые должны перекрыть значения по умолчанию.
Для логона используем do_logon передавая в user_selectors изменения значений по умолчанию
self.do_logon(url=login_url, user_selectors=user_selectors)

Сбор данных

В большинстве случаев интересующая информация приходит в json сразу после нажатия submit, так что в простом случае просто пытаемся после логона получить из приходящих json данные с помощью вызова метода

self.wait_params(params=[{
            'name': 'Balance', 'url_tag': ['object/meters'], 'jsformula': "data.data.sensors[0].meters.length",
        }])

В self.wait_params можно указать несколько параметров в одном вызове. Подробное описание смотрите так же в файле mbplugin/plugin/browsercontroller.py
В данном примере мы получаем значение параметра Balance со страницы url или POST запрос которой содержит 'object/meters' для получения берем содержимое json ответа как переменную data и выполняем data.data.sensors[0].meters.length.
Для отладки удобно в консоли браузера присваивать переменной data полученный json и дальше прямо в отладчике пытаться написать выражение, дающее требуемый результат. Если же обработку полученного json необходимо провести на python то вместо jsformula пишем код на python в параметре pformula
В случае если данные необходимо просто получить со страницы указываем пустой url_tag и просто пишем выражение для анализа данных со страницы, отладить его можно точно также в отладчике.

Прочие действия с браузером

Несмотря на то, что можно к экземпляру playwright page можно обратиться через self.page для наиболее часто используемых действий сделаны специальные обертки исключающие необходимость обработки ошибок: self.page_click - (обертка для page.click) кликнуть на элемент
self.page_content - (обертка для page.content) полное содержимое страницы в html
self.page_evaluate - (обертка для page.page_evaluate) выполнение js кода в браузере
self.page_fill - (обертка для page.fill) заполнить в поле
self.page_goto - (обертка для page.goto) переход по url
self.page_press - (обертка для page.press) симуляция нажатия на клавиатуру
self.page_reload - (обертка для page.reload) перезагрузить страницу
self.page_screenshot - (обертка для page.screenshot) сохранение скриншота со страницы в папку с логами (очень помогает при отладке, не не увлекайтесь - скриншоты занимают место)
self.page_type - (обертка для page.type) ввести текст в поле
self.page_wait_for - (обертка сразу для комбинации методов page.wait_for_load_state, page.wait_for_url, page.wait_for_selector) ожидание события на странице, при использовании wait_for_load_state и wait_for_selector учитывайте что оно не всегда дает ожидаемый результат, поэтому я добавил вариант expression - ожидание что js выражение вернет true
self.sleep - (обертка для page.wait_for_timeout) правильный sleep (внимание! хоть playwrith и синхронное приложение, под капотом у него асинхронные вызовы, так что использовать time.sleep крайне не рекомендуется, используйте вместо него self.sleep)

Также при желании можно использовать все остальные возможности playwright обращаясь напрямую через self.page, но тогда не забудьте про обработку ошибок.

В любом случае можно посмотреть плагины других провайдеров и скорее всего найдутся похожие на Ваш случаи.

Диагностика.

В ходе разработки естественно возникают ошибки, для того чтобы понять что идет не так я запускаю проверку командой
mbp check-plugin p_pluginname login password И затем смотрю в файле mbplugin/log/mbplugin.log ошибки. (еще удобнее через tail -f)
Также в таком варианте запуска можно воспользоваться и breakpoint(), главое не забудьте их убрать перед реальным использованием.

Иконка для плагина

Для полноты картины иконку, которая будет видна в MobileBalance, можно сделать с помощью утилиты mbplugin/plugin/get_icon.py указав ей либо url либо скачанный файл favicon.ico или его аналог. иконка - это переменная icon в теле модуля.