使用 PRAW 进行 Reddit 搜索时经常收到 503 错误

问题描述 投票:0回答:4

我正在使用PRAW查看大量Reddit搜索结果(包括提交和评论),而我使用的收集数据的方法经常产生503错误:

prawcore.exceptions.ServerError: received 503 HTTP response

据我了解,如果是速率限制问题,PRAW 会抛出

praw.errors.RateLimitExceeded
错误。

产生错误的函数如下:

def search_subreddit(subreddit_name, last_post=None):
    params = {'sort': 'new', 'time_filter': 'year', 
                      'limit': 100, 'syntax':'cloudsearch'}

    if last_post:
        start_time = 0 
        end_time = int(last_post.created) + 1
        query = 'timestamp:%s..%s' % (start_time, end_time)
    else: 
        query = ''

    return reddit.subreddit(subreddit_name).search(query, **params)

这是在循环中调用的。知道为什么会产生 503 错误,以及如何防止它发生吗?

python praw reddit
4个回答
7
投票

为什么要生成它?

503 是为通知服务器暂时不可用而保留的 HTTP 协议代码。在几乎所有情况下,这意味着它在请求时没有资源由于过载而无法生成响应。

如何预防?

因为这是服务器端问题,我在这里假设你不是 reddit 网络团队的一员,你不能直接做任何事情来解决这个问题。我会尝试在这里列出您可能的选择

  • 在社交媒体上抱怨 reddit 服务器很烂(可能无效)
  • 尝试联系 reddit 网络单位并告知他们这个问题(仍然无效,但从长远来看可能会有好处)
  • 向 PRAW 建议功能 - 关键字
    repeat_in_case_of_server_overload
    repeat_in_case_of_server_overload_timeout
    ,当第一次设置为
    True
    (默认
    False
    )时,将尝试重复请求一段可自定义的时间。 (这会很有趣,但不太可能以这种形式被接受,也需要一些时间来处理)
  • 修改PRAW 自己做上面描述的事情,然后在github 中添加pull request。 (你会立即拥有它,但仍然可能不会被接受并且需要一些工作)
  • 你可以尝试在 reddit 服务器不那么忙的时候运行你的脚本(如果你手动运行它并且偶尔只需要数据,那真的可以工作)
  • 添加简单的机制,将尝试多次获取搜索结果直到成功(是的,这可能是推荐的一种)

类似的东西:

result = None
last_exception = None
timeout = 900 #seconds = 15 minutes
time_start = int(time.time())
while not result and int(time.time()) < time_start + timeout:
    try:
        result = reddit.subreddit(subreddit_name).search(query, **params)
    except prawcore.exceptions.ServerError as e:
        #wait for 30 seconds since sending more requests to overloaded server might not be helping
        last_exception = e
        time.sleep(30)
if not result:
    raise last_exception
return result

此外,上面的代码更多的是伪代码,因为我没有以任何方式对其进行测试,它甚至可能无法逐字地工作,但希望能清楚地传达这个想法。


4
投票

如果您使用

Subreddit.submissions
,您可能会收到此错误,因为它在 PRAW 中已被弃用:https://github.com/praw-dev/praw/pull/916


0
投票

如果上述解决方案给您“时间”未定义错误

import time
from time import sleep

result = None
last_exception = None
timeout = 900 #seconds = 15 minutes
time_start = int(time.time())
while not result and int(time.time()) < time_start + timeout:
    try:
        result = reddit.subreddit(subreddit_name).search(query, **params)
    except prawcore.exceptions.ServerError as e:
        #wait for 30 seconds since sending more requests to overloaded server might not be helping
        last_exception = e
        time.sleep(30)
if not result:
    raise last_exception
return result

0
投票

其他答案给出了正确的想法,即当您出于某种原因没有从 Reddit 获得答案时,您需要某种重试系统。但是,如果您的应用程序在很多地方都使用 PRAW,那么将每个地方都包装在重试逻辑中真的很痛苦。 PRAW其实内置了一个重试机制,叫做

FiniteRetryStrategy
,但是它只重试了几次就放弃了。它没有记录,但你可以自己编写并将其插入:

from prawcore.sessions import RetryStrategy
import random

class InfiniteRetryStrategy(RetryStrategy):
    """Retries requests forever using capped exponential backoff with jitter."""

    def _sleep_seconds(self):
        if self._attempts == 0:
            return None
        return random.randrange(0, min(self._cap, self._base * 2 ** self._attempts))

    def __init__(self, _base = 2, _cap = 60, _attempts = 0):
        self._base = _base
        self._cap = _cap
        self._attempts = _attempts

    def consume_available_retry(self):
        return type(self)(_base=self._base, _cap=self._cap, _attempts=self._attempts + 1)

    def should_retry_on_failure(self):
        return True

# To use it, slot it in right after you initialize your praw.Reddit object:
reddit = praw.Reddit(client_id=...,
                     client_secret=...,
                     username=...,
                     password=...,
                     user_agent=...)
reddit._core._retry_strategy_class = InfiniteRetryStrategy

这将使 PRAW 无限重试它发出的每个请求,而不是在几次之后放弃。

© www.soinside.com 2019 - 2024. All rights reserved.