Добридень, пані та панове, з вами знову OlegWock. За вікном чудовий вечір п'ятниці. Чому б не провести його з користю? Пропоную сьогодні написати невеличкого бота-автовідповідача.
Зміст
Одразу хочу сказати, що цей бот буде з себе представляти і які навички вам знадобляться. Бот буде виконувати деякі дії в відповідь на отримане повідомлення. Наприклад, в цьому уроці, ми навчимо його відправляти, у відповідь на команду ~bash~
, випадкову цитату з bash.im, а по команді ~cgra~
випадкову статтю з Codeguida. Для написання цього бота, окрім знань пітону та роботи з VK API, потрібні хоча б початкові знання з парсингу. Для парсингу я використовую requests + lxml, ви ж можете використовувати свої улюблені бібліотеки. Також, повинен сказати, що в мене є нездорова пристрасть до XPath'у, тому я інтенсивно використовую його можливості. Ну а зараз час починати.
Перед усім, потрібно написати відловлювання потрібних повідомлень. Отримувати повідомлення ми будемо за допомогою messages.get, використовуючи last_message_id
, завдяки чому ми не пропустимо ні одного повідомлення.
import vk
from time import sleep
from lxml import html
import requests as req
login = ''
password = ''
# Авторизація
vkapi = vk.EnterCaptchaAPI('4766382', login, password)
print('Успішно авторизувався')
messages = vkapi.messages.get(count=1)
last = messages['items'][0]['id']
while True:
try:
messages = vkapi.messages.get(last_message_id=last)
except Exception as e:
print(e)
sleep(4)
continue
if not messages['items']: # Якщо нема нових повідомлень
sleep(4)
continue
last = messages['items'][0]['id']
for message in messages['items']:
# Тимчасові заглушки
if "~bash~" in message['body']:
print("Wow. Such bash")
if "~cgra~" in message['body']:
print("Very nice")
sleep(4)
Тепер потрібно написати функції для отримання цитати з башу та статті з Codeguida. Давайте почнемо з башу. Як я вже казав, я великий прихильник XPath, тому не дивуйтеся, якщо його, на вашу думку, тут забагато.
def bash(id):
try:
r = req.get('https://web.archive.org/web/20230327094403/http://bash.im/random')
doc = html.document_fromstring(r.text)
bash = '\
'.join(doc.xpath('//*[@id="body"]/div[3]/div[@class="text"]/text()'))
vkapi.messages.send(user_id=id, message=bash)
except Exception as e:
print(e)
Тут магія зберігається в 4 стрічці. За допомогою XPath ми дістаємо текст з контейнера div, що містить в собі першу цитату на сторінці. Знайти XPath потрібного елемента можна в інструментах розробника вашого браузера, але потрібно примітити, що майже завжди потрібно "доробляти напилком" до потрібного вам dbukzle. doc.xpath
завжди повертає список, в даному випадку? це буде список із абзаців (шматків тексту, розділених <br>
), тому його потрібно зібрати, замінивши зникнувші <br>
на \
, ну й надіслати отриманий текст у відповідь. Поправимо цикл перевірки повідомлень, замінивши заглушку на вже готову функцію:
...
if "~bash~" in message['body']:
bash(message['user_id'])
...
Можете запустити й упевнитися, що все працює. Але є одне не. Якщо хтось в колективному чаті напише ~bash~
, то цитата відправиться до нього в особисті повідомлення, а не в чат. Треба пофіксити.
def bash(id, mode='u'):
try:
r = req.get('https://web.archive.org/web/20230327094403/http://bash.im/random')
doc = html.document_fromstring(r.text)
bash = '\
'.join(doc.xpath('//*[@id="body"]/div[3]/div[@class="text"]/text()'))
if mode == 'c':
vkapi.messages.send(chat_id=id, message=bash)
else:
vkapi.messages.send(user_id=id, message=bash)
except Exception as e:
print(e)
....
if "~bash~" in message['body']:
if 'chat_id' in message:
bash(message['chat_id'], 'c')
else:
bash(message['user_id'])
....
А тепер час писати парсер для кодегіди. Давайте візьмемо url цього посту, як ви бачите в кінці є ідентифікатор посту. Тобто, щоб отримати випадковий пост потрібно замість ідентифікатора підставити випадкове число від 1 до 287 (на даний момент).
def cgra(id, mode='u'):
try:
r = req.get('https://web.archive.org/web/20230327094403/http://codeguida.com/')
doc = html.document_fromstring(r.text)
last_article = doc.xpath('/html/body/div[3]/section/div[1]/div[1]/article[1]/div/a/@href')[0] # адреса останнього посту
last_id = int(last_article.split('/')[-2]) # ID останнього посту
random_id = randint(1, last_id)
r = req.get('https://web.archive.org/web/20230327094403/http://codeguida.com/post/{}/'.format(random_id))
doc = html.document_fromstring(r.text)
title = doc.xpath('/html/body/div[3]/div[2]/section/h1/text()')[0] # отримуємо заголовок
message = '{0}\
\
http://codeguida.com/post/{1}/'.format(title, random_id)
if mode == 'c':
vkapi.messages.send(chat_id=id, message=message)
else:
vkapi.messages.send(user_id=id, message=message)
except Exception as e:
print(e)
Не забудьте прибрати заглушку в циклі перевірки повідомлень. На цьому роботу можна вважати завершеною, все повинно працювати. Але давайте ще додамо допомогу до нашої програми.
def print_help(id, mode='u'):
try:
message = """=== Система \"Єнотик\" ===
Дотсупні команди:
&#_9989; ~bash~ -- випадкова цитата з bash.im
&#_9989; ~cgra~ -- випадкова стаття з Codeguida
&#_9989; ~help~ -- показує цю довідку
Автор: OlegWock, 2015, спеціально для Codeguida"""
if mode == 'c':
vkapi.messages.send(chat_id=id, message=message)
else:
vkapi.messages.send(user_id=id, message=message)
except Exception as e:
print(e)
...
if "~help~" in message['body']:
if 'chat_id' in message:
print_help(message['chat_id'], 'c')
else:
print_help(message['user_id'])
...
Як і зазвичай ви можете знайти повний код в цьому репозитарії. В коментарях можете висловлювати свої думки про додавання боту функціональності. Хто знає, можливо, саме ваша ідея мені сподобається і буде описана в наступних статтях.
Ще немає коментарів