用Python作一个Telegram的新闻Bot

在这篇文章中,咱们构建一个高可用的Telegram机器人,用来在成千上万的新闻源当中搜索内容。python

介绍

Telegram 如今是一个全球流行的实时消息应用,它的特色是安全性和高效性,除了能够互相发送消息之外,还能够在它上面建立bot用来自动执行一些任务。安全

在这个教程中,咱们将用Python和Telegram's bot API 建立一个基于Datanews的新闻bot。服务器

Telegram API 简单介绍

咱们将使用官方的python-telegram-botApi,这个库大大简化了开发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

  1. /start - Bot会根据这个命令响应出帮助页面
  2. /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]}!')

上面每个方法都须要两个参数:

  1. update 从Telegram服务器收到一个更新
  2. context包含一些有用的参数和信息,举个例子,它有一个用来储存用户相关信息的user_data字典

除此之外,每个参数都会给用户返回一条消息。

Datanews API 介绍

Datanews 是一个用来从成千上万个新闻源中取回和监控新闻的API,新闻聚合器和其余网站,天天收集并处理了数十万的新闻数据,固然,它也提供了灵活和简单可用的API用来检索这些新闻文章。

对于咱们这个小项目,咱们只须要API中的一小部分,特别是咱们想让bot能作什么:

  1. 根据用户输入的关键字返回新闻内容
  2. 根据特定的新闻源返回新闻内容

这些用例需求能够用一个入口处理- /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)

这些方法看起来都很是简单,它们都用了咱们前面讨论过的/headlinesAPI,惟一的区别是咱们传递给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中取出数据并排序返回给用户,

  1. 咱们确保用“包围查询”,以便Datanews返回全部包含完整查询的文章,而不单单是其中的一个单词。
  2. 咱们还要确保处理没法查询到文章的状况,若是这种状况下bot无反应是扯淡的。
  3. 咱们发送给用户的内容必须确保排序后的内容最后一条是最新的内容。

有了这些功能,咱们看一下主程序:

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

关注公众号得到更多最新的精彩内容。

相关文章
相关标签/搜索