YouTube 数据 Api:如果达到配额限制,是否会破坏 nextPageToken while 循环?

YouTube Data Api: breaking a nextPageToken while loop if quota limit is reached?

我正在使用 Python 3 和 YouTube 数据 API V3 从 YouTube 视频中获取评论。这个特定的视频有大约 280,000 条评论。我正在尝试编写一个 while 循环,它会在达到配额限制之前获得尽可能多的评论,然后在达到配额限制时中断。

我的循环似乎成功地调用了下一页标记并将请求的元数据附加到我的列表中,但是当达到配额时,它并没有结束循环,而是注册了一个 HttpError,并且没有保存任何正确获取评论数据。

这是我当前的代码:

# Get resources:

def get(resource, **kwargs):
    print(f'Getting {resource} with params {kwargs}')
    kwargs['key'] = API_KEY
    response = requests.get(url=f'{YOUTUBE_BASE_URL}/{resource}',
                            params=remove_empty_kwargs(kwargs))
    print(f'Response: {response.status_code}')
    return response.json()


# Getting ALL comments for a video:

def getComments(video_id):
    comments = []
    res = get('commentThreads', part='id,snippet,replies', maxResults=100, videoId=video_id)

    try:
        nextPageToken = res['nextPageToken']
    except TypeError:
        nextPageToken = None

    while (nextPageToken):
        try:
            res = get('commentThreads', part='id,snippet,replies', maxResults=100, videoId=video_id)

            for i in res['items']:
                comments.append(i)

            nextPageToken = res['nextPageToken']

        except HttpError as error:
            print('An error occurred: %s' % error)
            break

    return comments

test = 'video-id-here'
testComments = getComments(test)

所以,发生的事情是这似乎正确地遍历了所有评论。但是过了一段时间,即循环了几百次之后,我得到以下错误:


Getting commentThreads with params {'part': 'id,snippet,replies', 'maxResults': 100, 'videoId': 'real video ID shows here'}
Response: 403

KeyError                                  Traceback (most recent call last)
<ipython-input-39-6582a0d8f122> in <module>
----> 1 testComments = getComments(test)

<ipython-input-29-68952caa30dd> in getComments(video_id)
     12             res = get('commentThreads', part='id,snippet,replies', maxResults=100, videoId=video_id)
     13 
---> 14             for i in res['items']:
     15                 comments.append(i)
     16 

KeyError: 'items'

所以,首先我在一段时间后从 API 得到了预期的 403 响应,这表明达到了配额限制。然后它抛出 'items' 的错误,但抛出此错误的原因是因为它不再捕获评论线程,所以没有更多的 'items' 可以追加。

我的预期结果是当达到配额限制时循环将中断并保存它在达到配额之前设法获取的评论数据。

我认为这可能与我的 'try' 和 'except' 处理有关,但我似乎无法弄清楚。

谢谢!

您正在捕获一个 HttpError 但它从未发生过,因为当您的限制用完时 API 只是 returns 403。

没有要捕获的 HttpError,因此您尝试读取一个不存在的值并得到一个 KeyError。

最可靠的方法可能是检查状态代码。

res = get('commentThreads', part='id,snippet,replies', maxResults=100, videoId=video_id)

if res.status_code != 200:
    break

for i in res['items']:
    comments.append(i)

nextPageToken = res['nextPageToken']

res.status_code 假设您正在使用请求。

最终用这段代码修复了它:

def getComments(video_id):
    comments = []
    res = get('commentThreads', part='id,snippet,replies', maxResults=100, videoId=video_id)

    try:
        nextPageToken = res['nextPageToken']

    except KeyError:
        nextPageToken = None

    except TypeError:
        nextPageToken = None

    while (nextPageToken):
        try:
            res = get('commentThreads', part='id,snippet,replies', maxResults=100, videoId=video_id)

            for i in res['items']:
                comments.append(i)

            nextPageToken = res['nextPageToken']

        except KeyError:
            break

    return comments

KeyError 的正确异常处理是最终的解决方案,因为我的 get() 函数 returns 是一个 JSON 对象。