Пишем отложенные сообщения для ВК на питоне

Данная проблема возникла у меня, когда мне нужно было уехать загород на несколько недель, при этом во время отъезда нужно было отправить сообщение в ВК, а доступа в интернет я не имел бы. Поискав информацию в интернете, я ничего не смог найти про отложенные сообщения в ВК, поэтому у меня остался только один вариант — придумать как реализовать свои отложенные сообщения для ВК.

Ну, в целом, задача была понятна и я её разбил на несколько этапов:

  • Как отслеживать время на компьютере

  • Каким образом переходить на странички нужных людей

  • Каким образом отправлять им сообщения

Самое просто было написать код для отслеживания времени на компьютере:

import time


dt = [int(i) for i in input("Введите дату отправки в формате mm:dd ").split(":")]
tm = [int(i) for i in input("Введите время отправки в формате hh:mm:ss: ").split(":")]
message = input("Введите сообщение: ")


while True:
    if (tm[0] == time.localtime().tm_hour and tm[1] == time.localtime().tm_min and tm[2] == time.localtime().tm_sec
            and dt[0] == time.localtime().tm_mon and dt[1] == time.localtime().tm_mday):
        print(message)
    print(time.localtime())
    time.sleep(1)

Для того, чтобы переходить на странички нужных людей, я не придумал ничего лучше, чем задавать ссылки на них :/

Изучив странички в ВК, их можно разделить на два типа:

  1. Которые находятся в списке друзей

  2. Которые не находятся в списке друзей

Основное различие в них — разные кнопки для открытия окна сообщения:

Не в списке друзей
Не в списке друзей
В списке друзей
В списке друзей

Я решил использовать библиотеку selenium

На самом деле, всё решение свелось к тому, что нужно было начать со страницы входа в аккаунт и последовательно сохранять XPath’ы кнопок и полей ввода

Чтобы получить XPath элемента, мы на него наводимся мышкой, нажимаем правой кнопкой и выбираем «исследовать элемент», потом правой кнопкой на выделенный код и копируем XPath

9e66d1ee94632aebf898dfd36972ac85.png24fa2b29dc8014c55d70933bd5e34823.png

Вход по QR-код невозможен в рамках нашей задачи, поэтому нажимаем «Войти другим способом»

e2b2a99abef913267e900cbe3c3a0376.png

Вводим номер телефона

8f6357958ea1ccc96ceb7a1885c438d9.png

Подтвердить другим способом

3598cb88ca07b7accf6ac35eaa914d55.png

Пароль

1b92ed0c3d91c9cfdc8882fc5678781c.png

Вводим пароль и нажимаем продолжить

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

ef0b38681ba49c36964a79eb6472e69d.png

Когда перешли на страницу нажимаем на кнопку сообщения

adfacc843483c73c8f2c7d5a4ef1df16.png

В поле ввода вписываем наше сообщение и нажимаем «send»

По пути мы скопировали все пути для кнопок и полей ввода и теперь осталось написать код:

import time
from selenium import webdriver
from selenium.webdriver.common.by import By


dt = [int(i) for i in input("Введите дату отправки в формате mm:dd ").split(":")]
tm = [int(i) for i in input("Введите время отправки в формате hh:mm:ss: ").split(":")]
receivers = input("Вставьте ссылки получателей через запятую без пробелов: ").split(",")
message = input("Введите сообщение: ")

while True:
    if (tm[0] == time.localtime().tm_hour and tm[1] == time.localtime().tm_min and tm[2] == time.localtime().tm_sec\
            and dt[0] == time.localtime().tm_mon and dt[1] == time.localtime().tm_mday):
        urls = ["https://vk.com/?to=c3RpbGxtb3J0YWw-",
               "/html/body/div[14]/div/div/div/div[3]/div/div/div[2]/div[1]/div/div/section/div/div/div/div/div/div[2]/div/button[1]/span/span",
               "/html/body/div[14]/div/div/div/div[3]/div/div/div[2]/div[1]/div/div/section/div/div/div/div/div/form/div[1]/div[3]/span/div/div[2]/input",
               "/html/body/div[14]/div/div/div/div[3]/div/div/div[2]/div[1]/div/div/section/div/div/div/div/div/form/button[1]/span",
               "/html/body/div[1]/div/div/div/div/div[1]/div[1]/div/div/div/div/form/div[3]/button/span/span",
               "/html/body/div[1]/div/div/div/div/div[2]/div/div[2]/div/div/div/div/div[2]/div[1]/div/div/div[4]/div[2]/div[1]/span",
               "/html/body/div[1]/div/div/div/div/div[1]/div[1]/div/div/div/div/form/div[1]/div[3]/div/div/input",
               "/html/body/div[1]/div/div/div/div/div[1]/div[1]/div/div/div/div/form/div[2]/button[1]/span",
               ]

        urls_send = ["//*[@id='mail_box_editable']",
                    "//*[@id='mail_box_send']/span/span"]

        friend = "//*[@id='profile_redesigned']/div/div/div/div[2]/div[2]/div[2]/div/div[2]/div/div/div/div[1]/a/span/span"
        not_friend = "#profile_redesigned > div > div > div > div.ProfileHeader.ProfileHeader--withSnowballs > div.ProfileHeader__in > div.ProfileHeader__wrapper > div > div.ProfileHeader__actions > div > div > div > div:nth-child(2) > a > span > span > svg"

        # entrance
        browser = webdriver.Chrome()
        browser.maximize_window()

        browser.get(urls[0])

        time.sleep(5)

        search = browser.find_element(By.XPATH, urls[1])
        search.click()

        time.sleep(5)

        search = browser.find_element(By.XPATH, urls[2])
        search.send_keys("login")

        time.sleep(5)

        search = browser.find_element(By.XPATH, urls[3])
        search.click()

        time.sleep(5)

        search = browser.find_element(By.XPATH, urls[4])
        search.click()

        time.sleep(5)

        search = browser.find_element(By.XPATH, urls[5])
        search.click()

        time.sleep(5)

        search = browser.find_element(By.XPATH, urls[6])
        search.send_keys("password")

        time.sleep(5)

        search = browser.find_element(By.XPATH, urls[7])
        search.click()

        time.sleep(5)

        # sending
        for receiver in receivers:
            browser.get(receiver)

            time.sleep(5)

            try:
                search = browser.find_element(By.CSS_SELECTOR, not_friend)
                search.click()
            except Exception:
                search = browser.find_element(By.XPATH, friend)
                search.click()

            time.sleep(5)

            search = browser.find_element(By.XPATH, urls_send[0])
            search.send_keys(message)

            time.sleep(5)

            search = browser.find_element(By.XPATH, urls_send[1])
            search.click()
    print(time.localtime())
    time.sleep(1)

Между каждым действием выставлена пауза в 5 секунд, чтобы страница успевала прогрузиться, иначе может возникнуть ошибка

Это, по сути, всё. Думаю, что это можно как-то оптимизировать, но для меня и так сошло

Во время отъезда проверил программу и она смогла отправить сообщение спустя 3 дня после запуска. Конечно же в конце дописал код, чтобы по завершению отправки сообщений компьютер сам выключился, просто решил его не вставлять сюда

© Habrahabr.ru