使用Python爬取Discord数据突破单次100条消息限制的方法问询
报错原因
limit参数的取值范围是Discord API的硬限制,最大仅支持100。当你传入超过阈值的数值时,API会返回错误响应而非预期的消息数组,你直接对错误返回的内容做遍历、取content字段的操作,自然触发TypeError: string indices must be integers类型错误。
全量消息拉取方案
你可以用API的分页逻辑实现全量历史消息拉取,核心是通过before参数逐页回溯更早的消息,具体逻辑为:
- 首次请求不带
before参数,拉取最新的100条消息 - 记录当前批次中最早的一条消息(即返回列表的最后一个元素)的
id - 下一次请求将上述
id作为before参数的值传入,即可拉取到早于该条消息的下一批100条消息 - 循环执行直到某次请求返回的消息列表为空,说明所有历史消息已经拉取完毕
可直接运行的修改后代码
import requests import json import time def retrieve_all_messages(channelid): num = 0 headers = { 'authorization': 'here we enter the authorization code' } last_message_id = None while True: # 拼接请求地址 base_url = f'https://discord.com/api/v9/channels/{channelid}/messages?limit=100' if last_message_id: base_url += f'&before={last_message_id}' # 发起请求 r = requests.get(base_url, headers=headers) # 异常捕获:请求失败直接终止 if r.status_code != 200: print(f"请求出错,状态码:{r.status_code},错误信息:{r.text}") break # 解析消息列表 messages = json.loads(r.text) if not messages: # 无更多消息,退出循环 break # 遍历输出当前批次消息 for msg in messages: print(msg['content'], '\n') num += 1 # 更新分页锚点为当前批次最早的消息ID last_message_id = messages[-1]['id'] # 增加请求间隔,避免触发速率限制 time.sleep(1) print('number of messages we collected is', num) retrieve_all_messages('server id goes here')
注意事项
- 不要高频发起请求,Discord API有严格的速率限制,短时间内多次请求会触发临时封禁,上面的代码已经加了1秒的请求间隔,你可以根据实际情况调整
- 如果你使用的是个人用户的Authorization token,要注意Discord官方禁止用户账号通过API批量爬取数据,被检测到会导致账号被封禁,正规用途建议申请官方Bot,使用Bot token发起请求
- 确保你使用的账号对应拥有目标频道的消息查看权限,否则会返回403无权错误
内容的提问来源于stack exchange,提问作者WildDracula
相关产品推荐
相关产品推荐

