在這篇文章中,咱們構建一個高可用的Telegram機器人,用來在成千上萬的新聞源當中搜索內容。python
介紹
Telegram 如今是一個全球流行的實時消息應用,它的特色是安全性和高效性,除了能夠互相發送消息之外,還能夠在它上面建立bot用來自動執行一些任務。安全
在這個教程中,咱們將用Python和Telegram's bot API 建立一個基於Datanews的新聞bot。服務器
Telegram API 簡單介紹
咱們將使用官方的python-telegram-bot
Api,這個庫大大簡化了開發Bot的工做,並且經過一些官方給出的例子,很容易學習和掌握它,下面是一個例子:markdown
from telegram.ext import Updater, CommandHandler USAGE = '/greet <name> - Greet me!' def start(update, context): update.message.reply_text(USAGE) def greet_command(update, context): update.message.reply_text(f'Hello {context.args[0]}!') def main(): updater = Updater("TOKEN", use_context=True) dp = updater.dispatcher # on different commands - answer in Telegram dp.add_handler(CommandHandler("start", start)) dp.add_handler(CommandHandler("greet", greet_command)) # Start the Bot updater.start_polling() updater.idle() if __name__ == '__main__': main()
這個小代碼片斷建立了一個bot用來識別兩個命令:dom
/start
- Bot會根據這個命令響應出幫助頁面/greet
- 這個命令會接受一個參數,例如Datanews
,而後返回Hello Datanews!
來看看每一行代碼的含義:函數
main
方法學習
def main(): updater = Updater("TOKEN", use_context=True) dp = updater.dispatcher dp.add_handler(CommandHandler("start", start)) dp.add_handler(CommandHandler("greet", greet_command)) updater.start_polling() updater.idle()
這個方法配置了一些Bot工做必要的參數,特別是Update
類的實例,須要注意的是,你須要一個Telegram的token
才能使用Telegram Bot 的API,你能夠查看這個建立Bot的官方指南點這裏。fetch
回到代碼,Updater
的目的是爲了將更新傳遞給Dispatcher
,當後者收到一個更新,它將處理用戶指定的一些回調請求,每個回調都由一個程序管理。網站
當收到的消息知足某些條件時,雖然這些條件取決於程序,也能夠由開發者本身定義,就咱們而言咱們有兩個任務處理實例。ui
dp.add_handler(CommandHandler("start", start)) dp.add_handler(CommandHandler("greet", greet_command))
上面的每一條處理一個命令,用來支持咱們Bot的/start
和/greet
而後咱們調用start_polling
命令。
updater.start_polling()
這個命令會讓咱們的bot週期性的處理更新,這個參數會在內部建立兩個進程,一個用來從Telegram服務器輪詢更新,另外一個將由調度程序處理這些更新。
下面這一行確保咱們的bot能夠正確的處理各類中斷信號
updater.idle
如今咱們討論兩個處理bot命令的回調函數:
def start(update, context): update.message.reply_text(USAGE) def greet_command(update, context): update.message.reply_text(f'Hello {context.args[0]}!')
上面每個方法都須要兩個參數:
update
從Telegram服務器收到一個更新context
包含一些有用的參數和信息,舉個例子,它有一個用來儲存用戶相關信息的user_data
字典
除此之外,每個參數都會給用戶返回一條消息。
Datanews API 介紹
Datanews 是一個用來從成千上萬個新聞源中取回和監控新聞的API,新聞聚合器和其餘網站,天天收集並處理了數十萬的新聞數據,固然,它也提供了靈活和簡單可用的API用來檢索這些新聞文章。
對於咱們這個小項目,咱們只須要API中的一小部分,特別是咱們想讓bot能作什麼:
- 根據用戶輸入的關鍵字返回新聞內容
- 根據特定的新聞源返回新聞內容
這些用例需求能夠用一個入口處理- /headlines
, 你能夠在後面連接中瞭解到更多相關的APIofficial documentation.
程序實施
首先,咱們要定義一個處理/start
命令的回調函數
def get_usage(): return '''This bot allows you to query news articles from Datanews API. Available commands: /help, /start - show this help message. /search <query> - retrieve news articles containing <query>. Example: "/search covid" /publisher <domain> - retrieve newest articles by publisher. Example: "/publisher techcrunch.com"''' def help_command(update, context): update.message.reply_markdown(get_usage())
就像你看到的,這個實現方式與咱們上面演示的很類似,咱們簡單的返回了一個help信息給用戶,你能夠注意到咱們的bot支持四個命令,下面咱們討論其餘兩個:
def search_command(update, context): def fetcher(query): return datanews.headlines(query, size=10, sortBy='date', page=0, language='en') _fetch_data(update, context, fetcher) def publisher_command(update, context): def fetcher(query): return datanews.headlines(source=query, size=10, sortBy='date', page=0, language='en') _fetch_data(update, context, fetcher)
這些方法看起來都很是簡單,它們都用了咱們前面討論過的/headlines
API,惟一的區別是咱們傳遞給Datanews API的參數:search_command檢索與特定查詢匹配的文章,而Publisher_command提取全部由特定來源發佈的文章,這兩個方法中咱們都只活去10條最近的文章。
def _fetch_data(update, context, fetcher): if not context.args: help_command(update, context) return query = '"' + ' '.join(context.args) + '"' result = fetcher(query) if not result['hits']: update.message.reply_text('No news is good news') return last_message = update.message for article in reversed(result['hits']): text = article['title'] + ': ' + article['url'] last_message = last_message.reply_text(text)
這個方法簡單的檢查了用戶輸入的特定的參數,從Datanews API中取出數據並排序返回給用戶,
- 咱們確保用「包圍查詢」,以便Datanews返回全部包含完整查詢的文章,而不單單是其中的一個單詞。
- 咱們還要確保處理沒法查詢到文章的狀況,若是這種狀況下bot無反應是扯淡的。
- 咱們發送給用戶的內容必須確保排序後的內容最後一條是最新的內容。
有了這些功能,咱們看一下主程序:
def main(): updater = Updater(token='TOKEN') updater.dispatcher.add_handler(CommandHandler('start', help_command)) updater.dispatcher.add_handler(CommandHandler('help', help_command)) updater.dispatcher.add_handler(CommandHandler('search', search_command)) updater.dispatcher.add_handler(CommandHandler('publisher', publisher_command)) updater.dispatcher.add_handler( MessageHandler( Filters.text & Filters.regex(pattern=re.compile('help', re.IGNORECASE)), help_command ) ) updater.start_polling() updater.idle()
這個程序看起來和前面的例子很是類似,只有一個主要區別是下面:
updater.dispatcher.add_handler( MessageHandler( Filters.text & Filters.regex(pattern=re.compile('help', re.IGNORECASE)), help_command ) )
MessageHandler
用來得到用戶的輸入,你能夠認爲它是CommandHandler
的相似功能,它能夠處理任何知足指定過濾器的消息,在咱們的六種,咱們想在用戶輸入信息中包含help的時候將幫助信息返回給用戶。
所以,咱們有了一個徹底程序化的新聞機器人。
此文章翻譯自https://datanews.io/blog/building-telegram-news-bot-2020
關注公衆號得到更多最新的精彩內容。