Немного вводной
Я имею самый обычный рабочий график: 5/2, 8ч/день. В настоящий момент удаленно учусь в аспирантуре (коронавирус, все дела) и единственный день, когда я могу вдоволь почувствовать себя человеком-соседом и поделать что-то по дому, – это суббота. Как вы понимаете, здесь что-то пошло не так и вместо обещанных будничных пар, которые должны были проходить по вечерам после работы, нам утрамбовали всю субботу. Но дела ведь себя не переделают, поэтому решено было написать на python простого бота-кликера, который мог бы:
Заходить на пару по скормленной извне ссылки;
Стартовать запись экрана со звуком;
Ожидать окончания пары;
Выключать запись и выходить с пары.
Таким образом я и на паре присутствую, и домашними делами занимаюсь. А еще могу просмотреть лекции с удвоенным ускорением и в любое удобное для меня время. Придумано – сделано. Может быть мой опыт поможет кому-то решить аналогичную «проблему».
В ВУЗе мы используем Microsoft Teams и для того, чтобы попасть на лекцию требуется перейти по ссылке, которую за несколько часов до старта этой самой лекции, высылает староста. На мой взгляд, самым простым решением является бот-кликер, наблюдающий за экраном и тыкающий по кнопкам. А также было бы неплохо стартовать все это удаленно и желательно с телефона.
Кликер
Начал я с питонячей библиотеки pyautogui. Если кратенько, она умеет перехватывать управление клавомышью, тыкать кнопки, вводить тексты, делать снимки экрана, искать окна приложений и взаимодействовать с ними и многое-многое другое. Для своего кликера я выстроил следующую логику: я заранее сохраняю картинку нужной кнопки, pyautogui ожидает ее появления на экране, когда он находит кнопку, то тыкает по ней.
Функция ожидания:
def find_element(element):
"""Ожидание появления элемента на экране"""
sleep(1)
r = None
count = 100
while r is None:
count -= 1
r = pyautogui.locateOnScreen(dir_true_files + element, confidence=0.7)
print(count)
if count == 0:
print(element + ' не найден!')
break
else:
if r != None:
print(element + ' нашОлся!')
return r
else:
continue
Здесь pyautogui ищет на экране в пределах счетчика «100» совпадений в 70% с заранее сохраненной картинкой.
Далее функции для взаимодействия с приложением и создание скриншота экрана:
def press_key(key):
"""Нажатие одной клавиши"""
sleep(1)
pyautogui.press(key)
def write_text(text):
"""Ввод текста"""
sleep(1)
pyautogui.write(text, interval=0.2)
def create_screenshot(screens_directory, name):
"""Создание скриншота"""
sleep(1)
im1 = pyautogui.screenshot()
screenshot = im1.save(screens_directory + name)
return screenshot
Здесь можно расширить функционал бота, добавив возможность сравнивать время с временем системы, искать поле для ввода текста, делать его активным и вводить приветствие в зависимости от времени суток – с 09.00 до 12.00 «Доброе утро!», с 12.00 до 17.00 «Добрый день!», с 17.00 до 21.00 «Добрый вечер!». Можно сделать список, из которого раз в n минут бот будет забирать рандомное значение и передавать его функции, отправляющей текст – [‘Где экшон?’, ‘Лучше бы в армию пошел’, ‘Отличная мысль!’, ‘Я не расслышал, повторите’, ‘Хочу есть’] и т.д. Но нас на парах отмечали по факту присутствия и нахождению в онлайне – поэтому я не стал с этим заморачиваться.
Для записи экрана по работе я использую заранее настроенный OBS. Здесь его функциональности хватит с головой. Да, я знаю про ffmpeg, но подружиться с ним у меня так и не получилось. В итоге для старта записи я использую поиск окна по заголовку и выношу приложение «на передний план». Эти манипуляции нужны для того, чтобы, имея активное окно OBS, нажать через pyautogui хоткей для старта и окончания записи.
def active_window(title):
"""Найти окно по заголовку и сделать его активным"""
sleep(1)
app = Application().connect(title_re=title, backend='win32')
app.window(title_re=title).set_focus()
sleep(3)
Кнопки сохранены, шаги в MS Teams боту прописаны, все отлажено. Как запускаться?
Чат бот
До этого я много игрался с чат-ботами, поэтому мой выбор пал именно на них. Самым простым решением имхо здесь является Телеграмм с его @BotFather. Создаем бота, используя telebot. Я захотел отрезать от него все, что можно и нельзя, оставив ему один единственный функционал – получать ссылку и заходит на пару.
А как скармливать ему ссылку и открывать ее в MS Teams? Тут я вспомнил про давно задвинутый в дальний ящик чудесный selenium. Расчехлил и инициализировал хромдрайвер с нажатием на кнопку «Open Microsoft Teams»:
def site_desktop(url):
chrome_options = webdriver.ChromeOptions()
driver = webdriver.Chrome(executable_path=driver_chrome, options=chrome_options)
driver.set_window_size(1920, 1080)
driver.get(url)
find_and_click('/open_team.png')
sleep(3)
driver.close()
Можно заморочиться с распознаванием сообщений в другом чате, откуда к нам поступаю ссылки на лекции, привязаться ко времени (первая пара в 9.00, вторая в 10.40 и т.д.) и в нужное время автоматом забрать сообщение, начинающееся с ‘https://’, но я предпочитаю контролировать этот процесс и копипастить ссылки лично.
В итоге, когда я отправляю боту url, он делает следующее:
Открывает selenium chrome driver с присланной ссылкой;
Кликает по кнопке "Открыть Microsoft Teams";
Открывает MS Teams, проверяет статус микрофона - включен/выключен. Если включен, отключает;
Подключается к паре;
Делает активным окно OBS, нажимает хоткей для записи экрана, отправляет скриншот рабочего стола в Телеграмм;
Ждет 90 минут;
Отправляет сообщение в Телеграмм о том, что пара закончилась;
Вновь делает активным окно OBS, выключает запись, кликает на кнопку для выхода с пары;
Отправляет финальное сообщение о завершении цикла. Ждет новой ссылки.
bot = telebot.TeleBot(bot_token)
@bot.message_handler(content_types=['text'])
def get_text_messages(message):
if message.text:
try:
bot.send_message(message.chat.id, text='Стартую вход на пару')
txt = message.text
site_desktop(txt)
find_and_click('/disable_micro.png')
if find_element('/micro_status_on.png'):
find_and_click('/disable_micro.png')
find_and_click('/apply_study.png')
active_window('OBS')
press_key('f7')
sleep(3)
create_screenshot(dir_to_save_fail_screen, name_fail_screen)
bot.send_photo(message.chat.id, open(dir_to_save_fail_screen + name_fail_screen, 'rb'))
bot.send_message(message.chat.id, text='Зашел на пару, включил запись экрана')
# Длительность пары 90 мин == 5400
sleep(5400)
bot.send_message(message.chat.id, text='Пара подошла к концу, выключаю запись экрана, выхожу')
active_window('OBS')
press_key('f8')
sleep(3)
find_and_click('/exit.png')
bot.send_message(message.chat.id, text='Успешное завершение')
except Exception as e:
bot.send_message(message.chat.id, text='ОШИБКА + ' + str(e))
bot.polling()
Не очень хорошо, что 90 минут пары я обернул в простой time.sleep, но этого, как показала практика, более, чем достаточно. Также в OBS можно настроить запись видео только окна MS Teams в небольшом разрешении с фиксированной частотой кадров и пожатым звуком, дабы уменьшить итоговый размер видоса. И затем слать его себе в Телеграмм.
А вот так это выглядит для меня, который в этот момент вполне может ехать куда-нибудь за стройматериалами (ссылки замазюкал, время сократил):
З.Ы. Я ни в коем случае не призываю пропускать таким образом уроки/пары – ученье свет! Но, увы, отечественное образование частично состоит из архаичных лекций времен советского союза, выхлоп от которых… чуть больше, чем никакой. И такой робот позволит хотя бы частично разгрузиться и переключиться на что-то более полезное и продуктивное.
dopusteam
"Но, увы, отечественное образование частично состоит из архаичных лекций времен советского союза, выхлоп от которых… чуть больше, чем никакой"
Для того, чтоб это утверждать, нужно ходить на лекции)
А вообще, может вам лучше бросить учёбу?
BeardedBeaver
Запись экрана подразумевает последующий просмотр в удобное время на комфортной скорости с перематыванием на моменты, которые не понятны с первого раза или просто не расслышаны, а не «отметиться на паре, а самому уйти пить пиво».
Другой вопрос, что по моему опыту записи лекций к ним не возвращаешься приблизительно никогда
zagayevskiy
2x очень комфортная скорость, да уж.
saboteur_kiev
С небольшой практикой — в общем-то да. А учитывая возможность в определенный момент остановиться и перемотать назад — это идеально.
А есть люди, которым комфортно 3x+
300KpS
Да. После того, как я открыл для себя х2 на ютубе, я больше не могу смотреть всякие видосы, слушать подкасты, на скорости х1. По большей части там болтовня. Исключение — фильмы и музыка
zagayevskiy
Ну значит качество и сложность материала лекций такова, что слушать их не имеет смысла вовсе. Да и вообще, лекции нужно конспектировать, это очень помогает в понимании материала, и в его запоминании. Пытаюсь представить, что я на 2х слушаю наших преподов… нереально вообще.
Volnyii Автор
Я же указал, что сделал всё это с целью отсмотреть лекции позже и в ускоренном виде, а не забить на них)
vmkazakoff
Если вдруг ещё и выложить эти лекции куда-то, то вы случайно переплюнете наш минобр и создадите систему дистанционного обучения нормально.
А вообще шикарное решение и хорошая идея — пока не придумали способ ускорять онлайн трансляцию, кажется, что это лучший вариант, если на парах нет реальной практики. Главное не забыть пересмотреть. По опыту этот архив при первом же "мне лениво" внезапно разрастается до состояния что отсмотреть все долги занимает больше времени чем есть до следующих занятий.