Кросспостинг в Интернете - автоматическое, полуавтоматическое или ручное размещение или отправка одного и того же сообщения, статьи, ссылки или темы, на адреса электронной почты, форумах, блогах, либо на иной формы сайтах или в публичных переписках.
Будем публиковать анонсы на материалы сайта в социальных сетях и мессенджерах с указанием ссылки. Самыми популярными являются Twitter, Вконтакте и Facebook, а также мессенджеры Телеграм и Rocket.Chat. Возможно позже добавим одноклассников.
Все работы будем проводить на сервере под управлением OS linux debian 10.
Подобных скриптов в интернете много и всегда можно найти нужный и настроить для себя. Я напишу свой велосипед, для себя.
Почти свой.
Начало
Для публикации анонсов нужно их от куда-то брать? Почти на каждом сайте есть лента RSS с последними новостями. Обычно это файл rss.xml или index.xml.
В самом простейшем варианте наша новость в нем выглядит так:
<item>
<title>Кросспостинг на python</title>
<link>http://drhellp.loc.ru/krossposting-na-python/</link>
<pubDate>Fri, 10 Sep 2021 11:41:04 +0300</pubDate>
<description><h3 id="кросспостинг">Кросспостинг</h3> <p>Кросспостинг - что, как и зачем это нужно.</p></description>
</item>
Это обычный файл формата xml.
Также необходимо будет хранить пароли и токены доступа к социальным сетям, а также другие настройки в отдельном файле settings.ini.
Теперь определим, что будет делать наш скрипт и в каком порядке:
- Проверяем доступ в интернет
- Считываем настройки из settings.ini
- Читаем rss.xml файл блога с последними новостями
- Парсим rss.xml
- Находим последнюю новость и публикуем в социальные сети
- Записываем в settings.ini время публикации
Создадим директорию для нашего скрипта и перейдем в нее:
mkdir cross-bot
cd cross-bot
Создаем главный файл скрипта:
nano main.py
Проверка доступа в интернет
Проверять будем обычной командой ping до публичных серверов Google. Существует много способов проверить наличие интернет соединение мне этого достаточно. Скрипт завершит работу если ping не пройдет.
Прописываем следующие строки в скрипт:
#!/usr/bin/python3
# -*- coding: utf-8 -*
import sys
import subprocess
# Проверяем, есть ли доступ в интернет
print ("Проверка соединения...")
response = subprocess.call(["/usr/bin/ping", "-c", "3", "8.8.8.8"], stdout=subprocess.DEVNULL)
if response != 0:
print ("Нет доступа в интернет. Бот завершает работу.")
sys.exit(1)
print ("OK Google!")
Чтение параметров
Для хранения настроек скрипта используем файл settings.ini. Для работы с ini файлами нужно подключить библиотеку configparser.
import configparser
Создадим файл настроек settings.ini.
nano settings.ini
Добавим в него параметры:
[RSS]
feed = http://drhellp.loc.ru/rss.xml
datetime = 2021-09-10 10:12:23+00:00
Читаем:
# Имя ini файла
ini = '/home/drhellp/cross-bot/settings.ini'
config = configparser.ConfigParser()
config.read(ini)
FEED = config.get('RSS', 'feed')
DATETIME = config.get('RSS', 'DATETIME')
Чтение RSS
Для работы с rss установим библиотеку feedparser.
sudo apt-get install python3-pip
sudo pip3 install feedparser
Проверяем чтение rss. В цикле проходим все элементы.
import feedparser
# Получаем RSS ленту
rss = feedparser.parse(FEED)
for post in reversed(rss.entries):
print('---------------------------------')
# Получаем заголовок поста
title = post.title
print(title)
# Получаем ссылку на пост
link = post.links[0].href
print(link)
# Скачиваем текст
text = post.description
text = remove_html_tags(text)
print(text)
Для вывода новостей без html тегов добавим в начало скрипта функцию remove_html_tags. Также импортируем библиотеку для работы с регулярными выражениями.
import re
def remove_html_tags(text):
clean = re.compile('<.*?>')
return re.sub(clean, '', text)
Получаем вывод новостей.
---------------------------------
Кросспостинг на python
http://drhellp.loc.ru/krossposting-na-python/
Кросспостинг
Кросспостинг - что, как и зачем это нужно.
Публикация в Twitter
Для публикации анонсов в Twitter нужно получить ключи и токены.
- consumer_key
- consumer_secret
- access_token
- access_token_secret
Как их получить хорошо описано здесь https://mihalica.ru/twitter-api-key-token/ Если эта статья не поможет перейдите на страницу https://apps.twitter.com/app/new и при необходимости войдите в систему. Создайте приложение и оформите заявку для работы с API.
После получения ключей и токенов доступа продолжим. Добавим в систему библиотеку для работы с Twitter.
sudo apt-get install python3-tweepy
В settings.ini добавим секцию с ключами и токенами.
[Twitter]
consumer_key = XXXXXXXXXX
consumer_secret = XXXXXXXXXX
access_token = XXXXXXXXXX
access_token_secret = XXXXXXXXXX
Считываем параметры
import tweepy
# Параметры twitter
CONSUMER_KEY = config.get('Twitter', 'consumer_key')
CONSUMER_SECRET = config.get('Twitter', 'consumer_secret')
ACCESS_TOKEN = config.get('Twitter', 'access_token')
ACCESS_TOKEN_SECRET = config.get('Twitter', 'access_token_secret')
Прежде чем пытаться отправить сообщения в Twitter немного доработаем скрипт. Чтобы не публиковать все сообщения при каждом запуске скрипта, будем проверять время публикации в rss и время в файле settings.ini. Если в rss время больше чем в файле, тогда новость публикуем и обновляем время в файле, иначе ничего не делаем.
import datetime
for post in reversed(rss.entries):
# Время публикации
data = post.published
time = datetime.datetime.strptime(data, '%a, %d %b %Y %H:%M:%S %z')
time_old = config.get('RSS', 'DATETIME')
time_old = datetime.datetime.strptime(time_old, '%Y-%m-%d %H:%M:%S%z')
# Пропускаем уже опубликованные посты
if time <= time_old:
continue
else:
# Записываем время и дату нового поста в файл
config.set('RSS', 'DATETIME', str(time))
with open(ini, "w") as config_file:
config.write(config_file)
print('---------------------------------')
# Получаем заголовок поста
title = post.title
print(title)
# Получаем ссылку на пост
link = post.links[0].href
print(link)
# Скачиваем текст
text = post.description
text = remove_html_tags(text)
print(text)
Теперь при запуске напечатаются только те новости у которых время создания больше даты в файле settings.ini. При повторном запуске новости выводиться не будут. Для эксперимента можно исправить значение datetime в файле settings.ini.
# Авторизуемся в твитере и отправляем сообщение
auth = tweepy.OAuthHandler(
CONSUMER_KEY,
CONSUMER_SECRET
)
auth.set_access_token(
ACCESS_TOKEN,
ACCESS_TOKEN_SECRET
)
api = tweepy.API(auth)
# Формируем сообщение twitter
tweet = title + '\n' + link
status = api.update_status(status=tweet)
Публикация в Вконтакте
Для публикации анонсов Вконтакте тоже необходимо получить токен доступа.
Создадим Standalone приложение cross-bot на странице https://vk.com/apps?act=manage
Для подтверждения на номер подключенного к аккаунту телефона придет код.
Добавим описание и сохраняем изменения. Переходим в настройки.
Здесь нам нужен ID приложения.
Сформируем ссылку такого вида:
https://oauth.vk.com/authorize?client_id={ID-CLIENT}&display=page&redirect_uri=https://oauth.vk.com/blank.html&scope=wall,offline&response_type=token&…
{ID-CLIENT} - ID нашего приложения. Открываем ссылку в браузере.
Разрешаем доступ нашему приложению.
Получаем следующее предупреждение:
Пожалуйста, не копируйте данные из адресной строки для сторонних сайтов. Таким образом Вы можете потерять доступ к Вашему аккаунту.
Из адресной строки копируем часть после access_token= и до &expires_in, это и есть нужный нам токен доступа.
Для проверки напишем маленький скрипт.
#!/usr/bin/python3
# -*- coding: utf-8 -*
import requests
token = 'access_token'
version = 5.81
data = {
'access_token': token,
'from_group': 1,
'message': 'Тест',
'attachments': 'Ссылка на любую страничку',
'signed': 0,
'close_comments': 1,
'v':version
}
r = requests.post('https://api.vk.com/method/wall.post', data).json()
print(r)
Добавляю в settings.ini данные.
[VK]
access_token = XXXXXXXXXXXXXXXXXXXX
version = 5.81
В скрипте считываю данные и добавляю функцию.
import requests
# Параметры Вконтакт
VK_TOKEN = config.get('VK', 'access_token')
VK_VERSION = config.get('VK', 'version')
# Публикуем анонс во Вконтакт
def public_vk(title, link):
# Формируем массив данных
data = {
'access_token': VK_TOKEN,
'from_group': 1,
'message': title,
'attachments': link,
'signed': 0,
'close_comments': 1,
'v': VK_VERSION
}
# Отправляем запрос
requests.post('https://api.vk.com/method/wall.post', data).json()
return
public_vk(title, link)
Публикация в Телеграм
Для публикаций в Телеграм создадим бота. Хорошее руководство находится на этой странице http://nikovit.ru/blog/telegram-bot-peresylki-soobshcheniy-rss/
Лучше для наших целей воспользоваться клиентом на компьютере. Добавляем в контакты @BotFather. Отправляем ему команду:
/newbot
Придумываем имя, логин должно заканчиваться обязательно на bot.
После регистрации бота получаем следующее:
Done! Congratulations on your new bot. You will find it at t.me/ИМЯ_ВАШЕГО_БОТА. You can now add a description, about section and profile picture for your bot, see /help for a list of commands. By the way, when you've finished creating your cool bot, ping our Bot Support if you want a better username for it. Just make sure the bot is fully operational before you do this.
Use this token to access the HTTP API:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Keep your token secure and store it safely, it can be used by anyone to control your bot.
For a description of the Bot API, see this page: https://core.telegram.org/bots/api
Бот зарегистрирован, токен бота получен, никому не сообщайте его, зная токен можно полностью управлять ботом. Добавляем бота поиском по имени которое указывали ранее в наш канал, выдаем ему право публиковать сообщения.
Установим недостающие библиотеки.
sudo pip3 install pyTelegramBotAPI
Добавляем в файл настроек новую секцию.
[Telegram]
bot_token = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
channel = @ВАШ_КАНАЛ
Если канал частный то нужен его ID.
- Вы должны преобразовать канал в публичный и назначить @channelName
- Отправить сообщение на этот канал через Bot API
https://api.telegram.org/bot[ТОКЕН_ВАШЕГО_БОТА]/sendMessage?chat_id=@channelName&text=test
- В ответ вы получите информацию с chat_id вашего канала.
{"ok": true, "result": {"chat": { "id": -1001005582487, "title": "Test Private Channel", "type": "channel"}, "date": 1448245538, "message_id": 7,"text":"test"}}
- Теперь вы можете преобразовать канал обратно в частный (удалив ссылку на канал) и отправить сообщение прямо на этот chat_id “-1001005582487”
https://api.telegram.org/bot[ТОКЕН_ВАШЕГО_БОТА]/sendMessage?chat_id=-1001005582487&text=test
Дописываем в скрипт:
import telebot
# Публикуем анонс в Telegram
def public_telegram(title, text, link):
# Инициализируем телеграм бота
bot = telebot.TeleBot(BOT_TOKEN)
# Формируем сообщение в канал
message = '<a href="' + link + '">' + title + '</a>' + "\n" + text
# Отправляем сообщение в Telegram
bot.send_message(CHANNEL, message, parse_mode='HTML', disable_web_page_preview=False)
return
# Параметры бота Telegram
BOT_TOKEN = config.get('Telegram', 'bot_token')
CHANNEL = config.get('Telegram', 'channel')
public_telegram(title, text, link)False)
Публикация в Facebook
Устанавливаю библиотеку для работы с API Facebook.
sudo pip3 install facebook-sdk
В Facebook публиковать сообщения можно или в группу или на специально созданную страницу. В чем отличия группы и страницы, тема для другой статьи. Буду публиковать анонсы на страницу, создаю её.
Придумываю название, описание и категорию для страницы. Добавить обложку и изображение, это по желанию. Также по желанию можно подключить Страницу Facebook к WhatsApp.
Выбираю меню Ещё, пункт Информация
В самом низу - ID страницы.
Теперь создаем приложение Facebook, которое будет использоваться для доступа к Graph API Facebook. Перехожу на страницу https://developers.facebook.com/apps/ и создаю приложение cross-bot.
Выбираем тип Другое.
Придумаем название приложения.
Потребуется дополнительно ввести наш пароль от аккаунта. В верхнем меню выбираем Инструменты и Graph API Explorer. Выбираем наше приложение.
Выбираем Получить маркер доступа пользователя
cross-bot запрашивает доступ к следующим данным: имя и фото профиля.
Продолжаем со своим аккаунтом. Получим Разрешения public_profile. Добавим разрешение pages_manage_posts и сгенерируем токен.
Продолжаем со своим аккаунтом.
Какие Страницы вы хотите использовать с приложением cross-bot?
На следующем этапе вы определите, что приложение cross-bot может делать с выбранными Страницами.
Bыбираем недавно созданную страницу.
Что разрешено делать приложению cross-bot?
Показать список Страниц, которыми вы управляете
ДА
Читать контент, опубликованный на этой Странице
ДА
Создание контента на вашей Странице и управление им
ДА
В результате получим дополнительно следующие разрешения:
- pages_show_list
- pages_read_engagement
- pages_manage_posts
- public_profile
Возле маркера доступа нажимаем на значек i
Полученный токен действителен несколько часов. Увеличим время его действия. Жмем кнопку Открыть в Инструменте маркеров доступа и на открывшейся странице, в самом низу нажимаем Продлить маркер доступа
Для вашей безопасности вам необходимо еще раз ввести свой пароль, чтобы продолжить. В результате получим продленный токен.
Добавляем в settings.ini новую секцию.
[Facebook]
access_token = XXXXXXXXXXXXXXXXXXXXXXX
page_id = 109592441534081
Считываем параметры
import facebook
# Параметры Facebook
FB_TOKEN = config.get('Facebook', 'access_token')
FB_PAGE_ID = config.get('Facebook', 'page_id')
В скрипт добавляем новую функцию
# Публикуем анонс в Facebook
def public_fb(link):
# ID страницы для которой нужно получить токен
page_id = FB_PAGE_ID
# Используем для запроса токен пользователя
graph = facebook.GraphAPI(FB_TOKEN)
# Отправляем запрос
resp = graph.get_object('me/accounts')
page_access_token = None
# Поиск токена для страницы
for page in resp['data']:
if page['id'] == page_id:
page_access_token = page['access_token']
# Запрос с токеном страницы
graph = facebook.GraphAPI(page_access_token)
# Публикуем анонс
graph.put_object('me', 'feed', link=link)
return
public_fb(link)
Публикация в Rocket.Chat
Создайте пользователя или воспользуйтесь существующим. Убедитесь, что пользователь может отправлять сообщения в нужном канале. Предоставьте пользователю роль с разрешением на создание личных токенов доступа. Получите токен доступа.
Добавим параметры в файл настроек.
[RocketChat]
url = https://chat.loc.ru/hooks/XXXXXXXXX
username = USER
icon_emoji = :information_source:
color = #00008b
Считываем параметры и вызываем функцию.
# Параметры RocketChat
URL = config.get('RocketChat', 'url')
USERNAME = config.get('RocketChat', 'username')
ICON_EMOJI = config.get('RocketChat', 'icon_emoji')
COLOR = config.get('RocketChat', 'color')
# Публикуем анонс в RocketChat
def public_rc(title, text, link):
# Отправляем пост в корпоративный чат
payload = {"username":USERNAME,"emoji":ICON_EMOJI,"attachments":[{"color":COLOR,"title":title,"title_link":link,"text":text}]}
r = requests.post(URL, json=payload)
return
public_rc(title, text, link)
Публикация в Одноклассниках
Для публикаций в Одноклассниках потребуется создать тематическую группу и приложение. Во первых нужно получить права разработчика, переходим на страницу. Подробная инструкция, как создать приложение. Создаем приложение со следующими правами.
Приложение добавлено. На вашу эл. почту gmail@gmail.com был выслан код, который будет необходимо указывать при изменении настроек приложения.
В почтовом ящике обнаружите письмо.
Ваше приложение cross_bot успешно зарегистрировано на Одноклассниках.
Application ID: XXXXXXXXXXX
Публичный ключ приложения: XXXXXXXXXXX
Секретный ключ приложения: XXXXXXXXXXX
Ссылка на приложение: https://ok.ru/game/XXXXXXXXXXX
--
С уважением,
Служба поддержки OK.ru
Переходим по ссылке и выбираем Изменить настройки приложения. Внизу страницы нажимаем кнопку Добавить платформу.
Выбираем OAuth авторизацию. В Список разрешённых redirect_uri добавим пару строк и сохраним.
okauth://okApplication ID
okApplication ID://authorize
Внизу страницы, в разделе Access token нажимаем кнопку Получить новый.
Получаем необходимые токены доступа.
Вечный session_key: XXXXXXXXXXX
Session_secret_key: XXXXXXXXXXX
Сохраняем параметры приложения.
Внимание, после добавления дополнительных прав доступа в приложении, access_token работать перестанет, его необходимо будет получить заново.
Добавляем в файл настроек новую секцию.
[OK]
; Вечный access_token
ok_access_token = XXXXXXXXXXX
; Секретный ключ приложения
ok_private_key = XXXXXXXXXXX
; Публичный ключ приложения
ok_public_key = XXXXXXXXXXX
; Session_secret_key
ok_session_key = XXXXXXXXXXX
; ID группы
ok_gid = XXXXXXXXXXX
ID группы можно посмотреть в настройках группы или в строке браузера.
https://ok.ru/group/XXXXXXXXXXX
Для создания хэша нам понадобится библиотека шифрования. В скрипте считываем параметры и вызываем функцию.
import requests
import hashlib
# Параметры в Одноклассниках
OK_ACCESS_TOKEN = config.get('OK', 'ok_access_token')
OK_PRIVATE_KEY = config.get('OK', 'ok_private_key')
OK_PUBLIC_KEY = config.get('OK', 'ok_public_key')
OK_SESSION_KEY = config.get('OK', 'ok_session_key')
OK_GID = config.get('OK', 'ok_gid')
# Публикуем анонс в Одноклассники
def public_ok(link):
# Формируем массив параметров
params = {
"application_key": OK_PUBLIC_KEY,
"attachment": '{"media": [{"type": "link", "url": "' + link + '"}]}',
"format": "json",
"gid": OK_GID,
"method": "mediatopic.post",
"type": "GROUP_THEME"
}
# Формируем строку параметров из массива
string_params = ''
for key in params:
string_params = string_params + key + '=' + params[key]
# Высчитываем хеш для строки параметров
string_params = string_params + OK_SESSION_KEY
hash_string = hashlib.md5(string_params.encode())
# Добавляем наш токен
params["access_token"] = OK_ACCESS_TOKEN
# Добавляем полученный хеш
params["sig"] = hash_string.hexdigest()
# Отправляем пост
r = requests.post('https://api.ok.ru/fb.do', data=params)
return
Заключение
Полностью скрипт можно скачать в репозитории. Не забудьте добавить скрипт в задания CRON.