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

Python中如何加速TMDB API分页Get请求以获取剧集ID?

如何高效获取TMDB 2017年12月发布的所有剧集ID

嘿,我完全懂你现在的烦恼——3600多次串行请求确实慢到让人崩溃。先给你明确结论:TMDB的Discover API本身没有直接返回所有结果的批量接口,所以完全不用循环是做不到的,但我们可以通过并发请求来大幅缩短耗时,这是目前最可行的优化方案。下面给你具体的优化思路和代码示例:

核心优化思路:并发请求替代串行循环

TMDB的API速率限制是每10秒最多40个请求,所以只要控制并发数在合理范围内(比如一次同时发4-8个请求),就不会触发限流,同时能把耗时从串行的几十分钟压缩到几分钟。

方案1:使用线程池并发(适合不熟悉异步的开发者)

可以用requests-futures库,它基于requests和线程池实现,代码改动很小:

首先安装依赖:

pip install requests-futures

然后修改代码:

import requests
from requests_futures.sessions import FuturesSession

# 配置API参数
API_KEY = "你的API密钥"
BASE_TV_URL = "https://api.themoviedb.org/3/discover/tv"
params = {
    'release_date.gte': '2017-12-01',
    'release_date.lte': '2017-12-31',
    'api_key': API_KEY,
}

# 初始化会话,设置线程池大小(控制并发数,建议4-8,避免触发限流)
session = FuturesSession(max_workers=6)

# 先获取总页数
response = requests.get(BASE_TV_URL, params=params)
response.raise_for_status()  # 处理请求错误
total_pages = response.json()['total_pages']
print(f"总页数:{total_pages}")

# 批量提交所有页面的请求
futures = []
for page in range(1, total_pages + 1):
    page_params = params.copy()
    page_params['page'] = page
    future = session.get(BASE_TV_URL, params=page_params)
    futures.append(future)

# 收集所有结果
tv_ids = set()
for future in futures:
    response = future.result()
    if response.ok:
        data = response.json()
        # 直接提取id,不用遍历所有键值对
        for item in data['results']:
            if item.get('id'):
                tv_ids.add(item['id'])

print(f"共获取到{len(tv_ids)}个剧集ID")

方案2:使用异步请求(性能更优)

如果追求更高效率,可以用aiohttp实现异步请求,这在处理大量请求时比线程池更高效:

首先安装依赖:

pip install aiohttp

代码示例:

import aiohttp
import asyncio

API_KEY = "你的API密钥"
BASE_TV_URL = "https://api.themoviedb.org/3/discover/tv"
params = {
    'release_date.gte': '2017-12-01',
    'release_date.lte': '2017-12-31',
    'api_key': API_KEY,
}

async def fetch_page(session, page):
    """异步获取单页数据并提取ID"""
    page_params = params.copy()
    page_params['page'] = page
    async with session.get(BASE_TV_URL, params=page_params) as response:
        if response.status == 200:
            data = await response.json()
            return {item['id'] for item in data['results'] if item.get('id')}
        return set()

async def main():
    # 先获取总页数
    async with aiohttp.ClientSession() as session:
        async with session.get(BASE_TV_URL, params=params) as response:
            response.raise_for_status()
            total_pages = (await response.json())['total_pages']
            print(f"总页数:{total_pages}")

        # 分批处理请求(避免一次性创建太多任务,控制并发数)
        batch_size = 8
        tv_ids = set()
        for i in range(0, total_pages, batch_size):
            batch_pages = range(i+1, min(i+batch_size+1, total_pages+1))
            tasks = [fetch_page(session, page) for page in batch_pages]
            batch_results = await asyncio.gather(*tasks)
            for result in batch_results:
                tv_ids.update(result)

        print(f"共获取到{len(tv_ids)}个剧集ID")

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

额外的代码优化细节

除了并发,你原来的代码还有几个可以优化的点:

  • 使用response.json()替代手动json.loads(myResponseTv.content.decode('utf-8')),更简洁高效;
  • 直接通过item['id']提取ID,不用遍历所有键值对,节省时间;
  • 使用requests.Session或aiohttp.ClientSession复用HTTP连接,减少TCP握手的开销;
  • 用params字典构建请求参数,避免字符串拼接导致的错误(比如URL中的&符号问题)。

注意事项

  • 严格遵守TMDB的API速率限制:如果并发数太高,可能会收到429错误(限流),此时可以降低并发数,或者添加重试机制;
  • 可以考虑添加错误重试逻辑,比如请求失败时自动重试几次,避免因网络波动导致数据缺失;
  • 如果剧集数量很大,建议把ID分批保存到文件或数据库,避免内存占用过高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:34:06