【问题标题】:Cannot understand Python telegram bot Job queue无法理解 Python 电报机器人作业队列
【发布时间】:2023-03-18 19:30:01
【问题描述】:

这可能是我的错,但我无法使“run_repeating”方法起作用。我查看了官方 Github 存储库中的示例,发现 timerbot.py。我试图在我的代码中遵循同样的想法,但我失败了。我的意思是,timerbot 可以工作,但我做错了什么,我不知道这在我的代码中不起作用。而且我知道,timerbot 使用“run_once”而不是“run_repeating”,但文档指出pretty similar syntax for both

顺便说一句,我的机器人应该是使用 Selenium 的亚马逊产品的价格跟踪器(那部分没问题)。机器人获取 url,然后跟踪产品,直到价格变得更便宜并通过消息通知用户。

这基本上是代码(重要的部分):

from telegram import Update
from telegram.ext import Updater, CommandHandler, CallbackContext, MessageHandler, Filters, ConversationHandler
from selenium import webdriver, common
import time, re

#Variables
token = open('note_token_telegram', 'r').read()
driver_path = open('note_driver','r').read()
bin_path = open('note_bin','r').read()
  
#Track
def track(update: Update, context: CallbackContext) -> None:
    data = context.user_data
    url = context.args[0]
    chat_id = update.message.chat_id 
    if re.match(r'(https:\/\/www\.amazon\.).*', url):
        print('track running')
        #Scrape 
        driver_options = webdriver.FirefoxOptions()
        driver_options.add_argument('--headless')
        driver_options.binary_location = bin_path.strip()
        driver = webdriver.Firefox(executable_path=driver_path.strip(), options=driver_options)
        driver.get(url)
        try:
            try:
                price = driver.find_element_by_css_selector('#priceblock_ourprice')
            except common.exceptions.NoSuchElementException:
                try:
                    price = driver.find_element_by_css_selector('#priceblock_saleprice')
                except:
                    price = driver.find_element_by_css_selector('#priceblock_dealprice')
            name =  driver.find_element_by_css_selector('#productTitle')
        except:
            update.message.reply_text('Are you sure this is an Amazon product page? '+url)
            driver.close()
        data[name.text] = {'url': url, 'price' : price.text}
        print(data.items())
        driver.close()
        print(chat_id)
        context.job_queue.run_repeating(notification, 30, context=chat_id, name=str(chat_id))
        update.message.reply_text("Good! We are now tracking one more Product!")
def notification(update, context):
#The Script
    job = context.job
    print('notification running')
    print(type(job.context))
    print(job.context)
    print(context.user_data.items())
    #Scrape 
    driver_options = webdriver.FirefoxOptions()
    driver_options.add_argument('--headless')
    driver_options.binary_location = bin_path.strip()
    driver = webdriver.Firefox(executable_path=driver_path.strip(), options=driver_options)
    for i in context.user_data.items():
        driver.get(i[1]['url'])
        try:
            try:
                new_price = driver.find_element_by_css_selector('#priceblock_ourprice')
            except common.exceptions.NoSuchElementException:
                try:
                    new_price = driver.find_element_by_css_selector('#priceblock_saleprice')
                except:
                    new_price = driver.find_element_by_css_selector('#priceblock_dealprice')
        except:
            context.bot.send_message(job.context, text='Are you sure this is an Amazon product page?'+i['url'])
                        
            #Notification
                        
            if '-' in new_price.text and float(new_price.text[1:4]) < float(i[1]['price']):
                context.bot.send_message(job.context, text=f"It's on your budget! \n{i[0]} \n {price.text} \n {i[1]['url']}")
                driver.close()
            elif float(new_price.text[1:9]) < float(i[1]['price']):
                context.bot.send_message(job.context, text=f"It's on your budget! \n{i[0]} \n {price.text} \n {i[1]['url']}")
                driver.close()
            else:
                driver.close()

#Main Function
def main():
    updater = Updater(token.strip())
    #Commands Instantiation
    updater.dispatcher.add_handler(CommandHandler('track', track))
    updater.dispatcher.add_handler(MessageHandler(Filters.text & ~Filters.command, help))
   

    #Main loop methods
    updater.start_polling()
    updater.idle()
    
if __name__ == '__main__':
    main()

这是我收到的错误消息:

raise ValueError('The following arguments have not been supplied: %s' %
ValueError: The following arguments have not been supplied: context

它表示值错误,但我已将上下文和所有内容粘贴到通知功能的正确位置,不是吗?我只是遵循 timerbot.py 的相同原则(至少我尝试过......)。

【问题讨论】:

    标签: python telegram telegram-bot


    【解决方案1】:

    您的通知函数有一个额外的输入参数:

    def notification(update, context):
    

    应该是:

    def notification(context):
    

    要记住的另一件事是,您目前无法删除作业,因此您要检查的任何产品都将无限继续,直到您重新启动您的机器人。您可以在run_repeating() 中添加一个“last”参数,或者添加一个可以让您删除作业的命令(如果这是您想要的处理方式,您应该给它们提供更多唯一的名称)。

    更新:

    要将数据传递给重复作业,请尝试以下操作:

    def track(update: Update, context: CallbackContext) -> None:
        data = context.user_data
        ...
        data["url"] = url
        data["price"] = price.text
        data["chat_id"] = update.message.chat_id
        ...
        context.job_queue.run_repeating(notification, 3, context=context.user_data, name=str(chat_id))
    
    
    def notification(context):
        job = context.job
        chat_id = job.context["chat_id"]
        url = job.context["url"]
        price = job.context["price"]
        ...
    

    就删除作业的命名而言,产品名称听起来不错,甚至是保证唯一的产品 ID(我认为...)。

    【讨论】:

    • 谢谢!有用!是的,我需要一个解决方案来删除这些工作。我正计划使用产品名称......如果我可以设置 ID(如 SQL 中),那将是完美的。你有什么建议吗?
    • 现在它引发了其他错误:文件“bot.py”,第 103 行,通知打印(context.user_data.items()) AttributeError:“NoneType”对象没有属性“项目”这意味着, context.user_data 没有像字典一样被读取,因为它应该是。我在其中运行 type 命令并显示“NoneType”。
    • 我想我有办法了
    • 谢谢你!你救了我的工作!关于删除问题,我将作业命名为消息 ID 而不是聊天 ID,这更加独特,因此用户可以添加更多作业(这意味着同时跟踪更多产品)。我仍然需要努力,但我认为我的方向很好。谢谢!
    • 请记住,每条新消息都会更改消息 ID,因此可能很难跟踪它们
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-20
    • 1970-01-01
    • 2020-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-18
    相关资源
    最近更新 更多