官方数据渠道是首选

面向推荐系统、片单分析、内容中台或版权运营的团队,往往需要成规模的影视元数据,包括片名、题材、上映日期、时长、评分、演职员以及各地区译名。虽然「IMDb 爬虫」「TMDB 数据抓取」是常见搜索词,但两个平台都提供了官方数据获取方式,同时也对自动化抓取网页设有明确限制。

核心结论是:TMDB 应走 API 和每日 ID 导出,IMDb 应走官方非商业数据集或授权 API;轮换代理并非用于绕过这两家的限制,而是服务于其他明确允许自动化访问的公开页面,例如院线排片页和发行方档期公告。无论采用哪种方式,采集范围都仅限于元数据,不涉及影视作品本身。

IMDb 与 TMDB 官方渠道对比

  • TMDB API:申请 API Key 后调用 REST 接口,返回 JSON,支持实时查询;变更接口可查最近 24 小时,单次最多 14 天。非商业用途免费,须署名;商业用途需单独授权。适合详情补全、增量同步和多语言字段。
  • TMDB 每日 ID 导出:从 files.tmdb.org 下载,每行一个 JSON 对象。每天约 UTC 7:00 开始生成,8:00 前全部可用,文件保留 3 个月。适合获取全量 ID 清单、发现新增和下线条目。
  • IMDb 非商业数据集:从 datasets.imdbws.com 下载 gzip 压缩的 TSV 文件,每日刷新,仅限个人和非商业用途。适合片目、评分、演职员关系的批量分析。
  • IMDb API(授权):通过 AWS Data Exchange 订阅,使用 GraphQL 接口,按需查询,面向商业授权场景。适合需要商用 IMDb 数据的产品。

TMDB API 的高效用法

TMDB 的电影、剧集、人物详情接口均支持 append_to_response 参数,一次请求即可附带 credits、release_dates、external_ids 等子资源,显著减少调用次数。增量同步可使用 /movie/changes,该接口返回发生变更的电影 ID,每页 100 条,单次查询跨度最多 14 天;全量清单则通过每日 ID 导出,对比前后两天的文件即可发现新增和消失的条目。

授权方面,TMDB 开发者 FAQ 明确:API 对非商业用途免费,前提是注明 TMDB 为数据来源;以创收为主要目的的项目属于商业用途,需联系 TMDB 获取授权。署名须使用官方认可的 logo,并在应用的「关于」或「致谢」页面放置声明:This product uses the TMDB API but is not endorsed or certified by TMDB.

IMDb 数据集构成

IMDb 非商业数据集共包含 7 个文件:title.basics(片名、类型、年份、时长、题材)、title.akas(各地区译名)、title.crew(导演和编剧)、title.episode(剧集季号和集号)、title.principals(主要演职员及角色)、title.ratings(加权平均分和投票数)、name.basics(人物信息)。文件以 tconst、nconst 为主键,缺失值用 \N 表示。官方说明这些数据仅限个人和非商业用途;商业项目需通过 IMDb 数据授权渠道获取,例如在 AWS Data Exchange 上订阅的 IMDb API。

合规边界决定项目能否长期运行

许多「IMDb 爬虫教程」忽略了合规边界,但它直接决定采集项目能否持续运行。以下几点可在官方页面直接核对:

  • IMDb 网页:imdb.com 的 robots.txt 对通用爬虫(User-agent: *)设置了 Disallow: /,文件开头还注明,未经 IMDb 事先书面许可,禁止使用自动化手段挖掘或抓取网站内容。因此 IMDb 页面不应成为采集目标,应改用数据集或授权 API。
  • TMDB 网站:TMDB 网站服务条款禁止在个人非商业用途之外复制、抓取站内资料,也禁止在未获书面授权的情况下用这些资料训练或验证机器学习和 AI 模型。程序化访问应走 API,并遵守 API 条款。
  • 版权:片名、年份、时长、演职员名单等事实性元数据风险较低;海报、剧照、剧情简介和用户评论受版权或平台条款保护,需单独确认授权。影视作品本身(视频、字幕、下载链接)不属于任何数据采集项目的范围。
  • 个人信息:演职员的出生年份等属于个人数据。在适用 GDPR 等法规的地区,只保留业务确实需要的字段。

对其他公开站点,判断顺序是:先看是否有官方 API 或数据授权;再读服务条款和 robots.txt;条款允许且 robots.txt 未禁止的路径,才进入后续采集流程。

三层采集架构与代理定位

推荐将采集系统分为三层:

  1. 批量层:每天下载 IMDb 数据集和 TMDB ID 导出,装入数据仓库,作为全量片目和 ID 映射的基础。
  2. 增量层:用 TMDB 变更接口拉取最近更新的条目,再调用详情接口补全字段,写入暂存表。
  3. 补充层:对条款允许的公开页面(如院线排片页、发行方新闻稿和档期公告、电影节片单)做定向采集,补上官方接口没有的本地化信息。

三层数据进入同一套标准化和去重流程,再发布给下游。轮换代理只出现在补充层。

补充层使用代理的合理场景

官方 API 不需要、也不应通过轮换 IP 调用。TMDB 速率限制文档说明,旧的限速规则已于 2019 年 12 月停用,但仍保留大约每秒 40 次的上限,用于抑制不必要的大批量抓取,该上限随时可能调整,收到 429 应退避。补充层使用代理有三个合理理由:

  • 地区视角:同一部电影在不同国家的上映日期、译名和分级不同,从目标国家网络出口访问才能看到当地页面的真实内容。
  • 出口稳定:采集任务分布在多个地区站点时,统一经由代理网络出口,可减少单一机房网络故障对全局的影响。
  • 故障隔离:某个出口 IP 异常时可切换,不拖累其他任务。

IPxSS 住宅代理支持自动轮换和可自定义时长的粘性会话,可按国家、城市、州/省和 ASN 筛选出口,适合地区视角场景。若不想自建抓取集群,也可评估 IPxSS Scraper API 对目标站点的支持情况,直接获取结构化结果,详见 https://www.ipxss.com/ 。

速率限制、会话策略与重试

按域名限速而非按 IP 限速

规模化采集最常见的错误,是把 IP 数量当作放大并发的系数。正确做法是在调度层为每个目标域名设置全局令牌桶:无论背后有多少出口 IP,发往该域名的总速率都不超过对方可承受且条款允许的水平。对 TMDB,建议将速率控制在官方上限的一小部分(例如每秒 10 次以内),并用 append_to_response 合并请求;对没有公开说明的站点,从每秒 1 次左右起步,观察响应时间和错误率再调整。

代理会话:翻页用粘性,独立页面用轮换

需要保持上下文的流程(翻页、带 Cookie 的地区选择)应使用粘性会话,让同一任务在会话期内保持同一出口;互不相关的详情页请求可逐次轮换。会话 ID 与任务 ID 绑定,便于快速定位问题。请求头中的 User-Agent 应写明项目名称和联系邮箱,方便目标站点运维人员在需要时联系。

重试策略:区分错误类型

  • 429:读取 Retry-After 响应头,没有则采用指数退避加随机抖动,同时调低该域名的令牌桶速率。
  • 5xx 和超时:有限次数重试(例如 3 次),间隔逐次拉长。
  • 403、404、410:不重试。403 通常表示访问被拒绝,应暂停该域名并人工复核是否越过条款边界,而非换 IP 继续请求。
  • 单个域名错误率超过阈值时触发熔断,暂停一段时间后再恢复。

以下为精简的请求函数示意,限速器和日志需按实际框架实现:

import random, time

def fetch(session, url, bucket, max_retries=3):
    for attempt in range(max_retries + 1):
        bucket.acquire()  # 按域名的全局令牌桶
        r = session.get(url, timeout=20)
        if r.status_code == 200:
            return r
        if r.status_code == 429 or r.status_code >= 500:
            retry_after = r.headers.get("Retry-After", "")
            wait = int(retry_after) if retry_after.isdigit() else 2 ** attempt
            time.sleep(wait + random.uniform(0, 1))
            bucket.slow_down()  # 收到 429/5xx 后降速
            continue
        r.raise_for_status()  # 403/404 直接报错,不换 IP 重试
    raise RuntimeError(f"giving up: {url}")

字段设计与去重策略

字段设计原则是:按来源保留原始值,标准化后的值另存;每条记录都带上来源、抓取时间和许可类型。

核心字段建议

  • work_id:内部主键,跨来源统一,自建。
  • imdb_id / tmdb_id:外部 ID,分别对应 IMDb 的 tconst 和 TMDB 的数字 ID,来源于 IMDb 数据集、TMDB external_ids。
  • title / original_title / localized_titles:主标题、原名以及按地区和语言存储的译名,来源于 title.basics、title.akas、TMDB translations。
  • release_dates:按国家存储,并区分首映、限映、院线、数字、实体、电视六种发行类型,来源于 TMDB release_dates。
  • runtime_min / genres:时长(分钟)和题材,来源于 title.basics、TMDB 详情。
  • ratings:按来源分别存储评分和投票数,不做合并,来源于 title.ratings、TMDB vote_average / vote_count。
  • credits:人物 ID、职务、角色名、排序,来源于 title.principals、TMDB credits。
  • source / fetched_at / license:来源、抓取时间、许可类型(非商业或商业授权),由采集系统记录。
  • content_hash:标准化内容的哈希值,用于判断记录是否变化,由采集系统生成。

三步去重流程

  1. 同源去重:同一来源以外部 ID 为键做 upsert,content_hash 无变化则跳过写入。
  2. 跨源合并:TMDB 记录中的 imdb_id 可直接关联 IMDb 数据集;TMDB 也提供按外部 ID 查找条目的接口。
  3. 无 ID 数据:补充层数据往往没有外部 ID,用「标准化片名 + 年份 + 时长」生成候选匹配,相似度低于阈值的进入人工复核队列,不自动合并。

还有一个容易忽略的细节:许可类型要跟着字段走。某个字段来自 IMDb 非商业数据集,那么用它生成的数据产品也只能用于非商业场景。应在 license 字段上做好标记,下游发布时按场景过滤。

上线前检查清单

  • 每个数据源都有书面依据(API 条款、数据集许可或数据协议),并存档条款版本和日期。
  • 每次任务启动时重新读取并缓存 robots.txt,不允许的路径直接跳过。
  • 按域名的全局限速已生效,收到 429 会自动降速。
  • 代理仅用于补充层,每个请求都记录出口地区和会话 ID。
  • 只存元数据,不下载视频或字幕;海报、剧照等图片需单独确认授权后再使用。
  • 每次运行输出质量报告:新增、更新、删除、合并和待复核的数量。

规模化采集影视数据的难点不在于每秒能发多少请求,而在于选对来源、守住边界、让每条数据都能追溯。IMDb 和 TMDB 已给出官方入口,数据集、API 和变更接口能覆盖大部分片目、评分和演职员需求。轮换代理在这套方案中是配角:只服务于允许采集的地区化公开页面,并受按域名限速和重试规则约束。若团队正在搭建此类补充采集层,可从 IPxSS 网页数据采集方案入手,评估出口地区、会话策略和接入方式,参考 https://www.ipxss.com/ 。