You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

pyTelegramBotAPI机器人执行爬虫脚本时请求失败问题排查

问题分析与解决方案

问题背景

使用pyTelegramBotAPI开发Telegram机器人,通过/run命令触发服务器上的Python爬虫脚本(基于requests库)。直接运行爬虫脚本时300次请求全部成功,但通过机器人触发时仅170次成功,问题出在telebot相关逻辑。

可能的原因

  • 单线程阻塞限制:bot.polling()默认以单线程模式运行,爬虫的网络请求会阻塞bot的消息处理线程。当爬虫耗时较长或并发触发/run命令时,部分请求会因线程阻塞、Telegram API超时或上下文重置而失败。
  • 隐性超时限制:Telegram对bot的响应有隐性时间限制,若爬虫任务耗时过久,bot的会话上下文可能被中断,间接导致爬虫请求失败。
  • 资源竞争:单线程环境下,多个爬虫任务排队执行时,后续请求可能因等待时间过长被目标网站拒绝或超时。

修复方案

1. 多线程分离爬虫任务

将爬虫任务放到独立线程中执行,避免阻塞bot的消息轮询线程:

import telebot
import threading
from functions.scrape import scrape

API_KEY = 'MY_KEY'
bot = telebot.TeleBot(API_KEY)

@bot.message_handler(commands=['start', 'help'])
def help(message):
    bot.send_message(message.chat.id, """
        ℹ️ **Command Menu** ℹ️
       /help - Displays the command menu
       /run - scrape information
""")

# 独立线程执行爬虫并回复用户
def execute_scrape(chat_id):
    values = scrape()
    bot.send_message(chat_id, f"scraped values: {values}")

@bot.message_handler(commands=['run'])
def run(pm):
    # 立即回复用户告知任务启动
    bot.send_message(pm.chat.id, "爬虫任务已启动,请稍候...")
    # 启动新线程执行爬虫
    threading.Thread(target=execute_scrape, args=(pm.chat.id,), daemon=True).start()

bot.polling(timeout=60, long_polling_timeout=60)

2. 为爬虫添加重试机制

在scrape函数中为requests请求添加重试逻辑,应对偶发的请求失败:

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

def scrape():
    # 创建带重试机制的session
    session = requests.Session()
    retry_strategy = Retry(
        total=3,  # 总重试次数
        backoff_factor=1,  # 重试间隔时间(秒)
        status_forcelist=[429, 500, 502, 503, 504]  # 需要重试的状态码
    )
    adapter = HTTPAdapter(max_retries=retry_strategy)
    session.mount("http://", adapter)
    session.mount("https://", adapter)
    
    # 后续使用session.get/post替代requests.get/post
    # ... 你的爬虫逻辑 ...

3. 优化polling参数

调整bot.polling()的超时参数,避免bot频繁重启导致中间请求中断:

bot.polling(timeout=60, long_polling_timeout=60, none_stop=True)

替代解决方案

1. 改用Webhook模式

Polling模式适合低流量场景,高流量或耗时任务建议切换到Webhook模式,从根本上避免单线程阻塞问题。

2. 切换到异步框架aiogram

aiogram是异步的Telegram Bot框架,天生适配IO密集型任务(如爬虫),无需手动管理线程即可高效处理并发请求:

from aiogram import Bot, Dispatcher, types
from aiogram.filters import CommandStart, Command
import asyncio
from functions.scrape import scrape

API_KEY = 'MY_KEY'
bot = Bot(token=API_KEY)
dp = Dispatcher()

@dp.message(CommandStart() | Command("help"))
async def help_handler(message: types.Message):
    await message.answer("""
        ℹ️ **Command Menu** ℹ️
       /help - Displays the command menu
       /run - scrape information
""")

@dp.message(Command("run"))
async def run_handler(message: types.Message):
    await message.answer("爬虫任务已启动,请稍候...")
    # 将同步爬虫函数放到线程池执行,不阻塞异步事件循环
    values = await asyncio.to_thread(scrape)
    await message.answer(f"scraped values: {values}")

async def main():
    await dp.start_polling(bot)

if __name__ == "__main__":
    asyncio.run(main())

内容的提问来源于stack exchange,提问作者eternalodballl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 18:53:30