使用python在discord上抓取数据

Wil*_*ula 4 python web-scraping discord

我目前正在尝试学习网络抓取并决定抓取一些不和谐的数据。代码如下:

import requests
import json

def retrieve_messages(channelid):
    num=0
    headers = {
        'authorization': 'here we enter the authorization code'
    }
    r = requests.get(
        f'https://discord.com/api/v9/channels/{channelid}/messages?limit=100',headers=headers
        )
    jsonn = json.loads(r.text)
    for value in jsonn:
        print(value['content'], '\n')
        num=num+1
    print('number of messages we collected is',num)

retrieve_messages('server id goes here')
Run Code Online (Sandbox Code Playgroud)

问题:当我尝试更改此处的限制时,messages?limit=100显然它只接受 0 到 100 之间的数字,这意味着我可以获得的最大消息数是 100。例如,我尝试将此数字更改为 900,以抓取更多消息。但后来我得到了错误TypeError: string indices must be integers

关于如何获取频道中的所有消息有什么想法吗?

非常感谢您的阅读!

小智 8

返回一堆记录的 API 几乎总是限于一定数量的项目。否则,如果请求大量项目,API 可能会因内存不足而失败。

为此,大多数 API 使用limitbeforeafter参数实现分页,其中:

  • limit:告诉您要获取多少条消息
  • before:获取该消息ID之前的消息
  • after:获取此消息ID之后的消息

正如文档告诉我们的那样,Discord API 也不例外。操作方法如下:

首先,您需要多次查询数据。为此,您可以使用 while 循环。确保添加一个 if 条件,以防止循环无限期地运行 - 我添加了一个检查是否有任何消息留下。

    while True:
        # ... requests code
        jsonn = json.loads(r.text)
        if len(jsonn) == 0:
            break
        
        for value in jsonn:
            print(value['content'], '\n')
            num=num+1
Run Code Online (Sandbox Code Playgroud)

定义一个变量,其中包含您获取的最后一条消息并保存您已打印的最后一条消息 ID

        
def retrieve_messages(channelid):
    last_message_id = None

    while True:
        # ...
        
        for value in jsonn:
            print(value['content'], '\n')
            last_message_id = value['id']
            num=num+1
Run Code Online (Sandbox Code Playgroud)

现在,在第一次运行时,last_message_id 为 None,在后续请求中,它包含您打印的最后一条消息。

用它来构建您的查询

    while True:
        query_parameters = f'limit={limit}'
        if last_message_id is not None:
            query_parameters += f'&before={last_message_id}'

        r = requests.get(
            f'https://discord.com/api/v9/channels/{channelid}/messages?{query_parameters}',headers=headers
            )
        
        # ...
Run Code Online (Sandbox Code Playgroud)

注意:discord 服务器首先给你最新的消息,所以你必须使用该before参数

这是您的代码的完整工作示例

import requests
import json

def retrieve_messages(channelid):
    num = 0
    limit = 10

    headers = {
        'authorization': 'auth header here'
    }

    last_message_id = None

    while True:
        query_parameters = f'limit={limit}'
        if last_message_id is not None:
            query_parameters += f'&before={last_message_id}'

        r = requests.get(
            f'https://discord.com/api/v9/channels/{channelid}/messages?{query_parameters}',headers=headers
            )
        jsonn = json.loads(r.text)
        if len(jsonn) == 0:
            break

        for value in jsonn:
            print(value['content'], '\n')
            last_message_id = value['id']
            num=num+1

    print('number of messages we collected is',num)

retrieve_messages('server id here')
Run Code Online (Sandbox Code Playgroud)