使用 Python 抓取 IMDb:真正能运行的代码

最后更新于 April 28, 2026
使用 Python 抓取 IMDb:真正能运行的代码

如果你最近搜过“使用 Python 抓取 IMDb”,你大概率已经发现一件事:你找到的大多数教程都已经不能用了。不是那种“有点过时”的坏,而是那种“返回 0 个结果,还一堆 NoneType 报错”的坏。

过去几周里,我测试了能找到的几乎所有主流 IMDb 抓取教程——GeeksforGeeks、Medium、freeCodeCamp、Kaggle 笔记本,能找的我都试了。在 214+ 个公开的 GitHub 仓库 里,绝大多数都还在引用 td.titleColumntd.ratingColumn 这类 CSS 选择器,但自从 IMDb 在 2023 年 6 月重做 Top 250 页面后,这些选择器就已经不存在了。结果就是:论坛里一堆开发者在问“为什么我的代码返回空结果?”,而像 Cinemagoer 这样的热门库维护者也只能承认“除了把每个解析器都修一遍,也没什么别的办法。”这篇指南会介绍两种现在仍然有效的 Python 方法,教你处理分页和常见错误,说明什么时候 Python 根本不是最佳工具,并告诉你如何让爬虫更耐用,避免进“报废爬虫墓地”。

用 Python 抓取 IMDb 到底是什么意思?

网页爬取指的是通过程序从网页中提取数据——不用手动复制粘贴,而是写脚本替你完成。我们说“抓取 IMDb”时,指的是用 Python 从 IMDb 网页中提取结构化电影数据,比如片名、评分、类型、演员表、时长和投票数。

Python 里最常见的技术栈由三个库组成:requests(抓取网页)、BeautifulSoup(解析 HTML 并定位数据)、pandas(整理并导出结果)。有些教程还会用 SeleniumPlaywright 去处理需要 JavaScript 渲染的页面,不过你会看到,其实还有更快的方法。

还有一个重要提醒:本指南中的所有内容都以 2025 年中期 IMDb 当前的页面结构为准做了验证。IMDb 大约每 6–12 个月就会改一次页面,所以如果你在 2027 年读这篇文章,部分选择器可能已经变了。(我也会教你怎么处理这种情况。)

为什么要用 Python 抓取 IMDb?真实应用场景

在写任何一行代码之前,你真的会拿 IMDb 数据做什么?答案取决于你是谁。

IMDb 评论数据集是全球使用最广泛的 NLP 基准之一——Maas 等人 2011 年的基础论文已经累积了 5,706 次引用,而且这个数据集已经内置到 TensorFlow、Keras 和 PyTorch 里。在 Hugging Face 上,stanfordnlp/imdb 数据集每月下载量达到 213,321 次,已经被用于训练 1,500 多个模型。所以如果你做机器学习,大概率早就对 IMDb 数据很熟悉了。

但它的用途远不止学术研究:

用途适合谁需要的数据字段
电影推荐引擎数据科学家、爱好者片名、类型、评分、演员表
流媒体平台内容策略产品/内容团队评分、投票数、上映年份、类型
情感分析 / NLP 训练机器学习研究者、学生评论、评分
竞品内容分析影视行业分析师票房、上映日期、评分趋势
影视旅游研究旅游局、旅行公司拍摄地点、热度指标
学术研究高校研究人员任意结构化电影元数据

单是影视旅游市场,预计在 2025 年全球规模就达到 660 亿美元。Netflix 在 2024 年内容投入超过 170 亿美元,而 80% 的观看行为都由个性化推荐驱动。说到底:IMDb 数据会影响各行各业的真实决策。

获取 IMDb 数据的几种方案(在写代码之前先想清楚)

这一部分通常会被大多数教程直接跳过。他们会直接让你 pip install beautifulsoup4,却完全不问:对你的场景来说,Python 抓取到底是不是最佳方案。

完整的选择如下:

方案最适合优点缺点
Python + BeautifulSoup学习、定制提取完全可控、灵活选择器脆弱,经常失效
JSON-LD / __NEXT_DATA__ 提取想要稳定性的开发者能处理 JS 内容,更抗变化需要理解 JSON 结构
IMDb 官方数据集大规模分析、学术用途合法、完整、2600 万+ 条目、每日更新TSV 格式,没有评论/图片
Cinemagoer(IMDbPY)库按条目程序化查询Python 风格 API、字段丰富88 个未解决问题,最后发布于 2023 年 5 月
TMDb API电影元数据 + 图片免费 API key、JSON、文档完善数据来源不同(不是 IMDb 评分)
Thunderbit(无代码)不写代码的人、快速导出2 步抓取,AI 自动建议字段,可导出到 Excel/Sheets大规模抓取按额度计费

关于这些选项有几点说明。Cinemagoer 自 2023 年 5 月以来就没在 PyPI 发布过新版本,而且在 IMDb 2025 年 6 月重设计后,它的大多数解析器都坏了——我现在不建议用于生产环境。TMDb 很不错,但它用的是自己的评分系统,不是 IMDb 的。至于 IMDb 官方企业 API,通过 AWS Data Exchange 购买的话一年要 5 万美元以上,这对大多数人来说都不现实。

如果你根本不想写代码,Thunderbit 的 AI 网页爬虫可以读取 IMDb 页面,自动建议提取字段(片名、评分、年份、类型),并且只需两步就能导出到 Excel、Google Sheets、Airtable 或 Notion。IMDb 改版时,AI 会自动适配布局变化,所以你不用维护任何选择器。后面我会再详细说。

现在,如果你确实想写 Python——下面有两种真正能用的方法。

方法 1:使用 BeautifulSoup 抓取 IMDb(传统做法)

这是大多数教程里的经典方法。它能用,但我得先说明白:在我介绍的几种方法里,它是最脆弱的。IMDb 的 CSS 类名是自动生成的,重设计时就会变化。不过,它仍然是学习网页爬取基础知识的最佳方式。

第 1 步:安装并导入 Python 库

你需要四个包:

pip install requests beautifulsoup4 pandas lxml

分别作用如下:

  • requests —— 发送 HTTP 请求,获取网页内容
  • beautifulsoup4 —— 解析 HTML,方便查找特定元素
  • pandas —— 将提取的数据整理成表格,并导出为 CSV/Excel
  • lxml —— 快速 HTML 解析器(BeautifulSoup 可以把它当后端)

导入代码如下:

import requests
from bs4 import BeautifulSoup
import pandas as pd

第 2 步:向 IMDb 发送 HTTP 请求

这一步通常就是新手第一次卡住的地方。IMDb 会拦截不带正确 User-Agent 请求头的请求——你会得到 403 Forbidden 错误。Python Requests 默认的 user-agent 字符串(python-requests/2.31.0)会立刻被标记。

url = "https://www.imdb.com/chart/top/"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "Accept-Language": "en-US,en;q=0.9"
}

response = requests.get(url, headers=headers)

if response.status_code != 200:
    print(f"抓取页面失败:{response.status_code}")
else:
    print("页面抓取成功")

Accept-Language 请求头也很重要——没有它的话,IMDb 可能会根据你 IP 的地理位置返回不同语言的内容。

第 3 步:用 BeautifulSoup 解析 HTML

拿到 HTML 后,创建一个 BeautifulSoup 对象,然后开始寻找正确的元素。你可以在 Chrome 里打开 IMDb Top 250 页面,右键点击电影标题,选择“检查”,查看底层 HTML 结构。

soup = BeautifulSoup(response.text, "lxml")

截至 2025 年中期,Top 250 页面使用的选择器如下:

  • 电影容器li.ipc-metadata-list-summary-item
  • 标题h3.ipc-title__text
  • 年份span.cli-title-metadata-item(第一个 span)
  • 评分span.ipc-rating-star--rating

提醒一下:这些带 ipc- 前缀的类名是 IMDb 组件系统生成的。自 2023 年 6 月改版以来它们一直比较稳定,但不能保证以后不会再变。

第 4 步:提取电影数据(片名、年份、评分)

这里我和大多数教程不一样:我加入了 try/except 错误处理。我看过的竞品指南里几乎都没有这一步,也正因为如此,它们在选择器变化时会静默报错。

movies = []
movie_items = soup.select("li.ipc-metadata-list-summary-item")

for item in movie_items:
    try:
        title_tag = item.select_one("h3.ipc-title__text")
        title = title_tag.text.strip() if title_tag else "N/A"

        year_tag = item.select_one("span.cli-title-metadata-item")
        year = year_tag.text.strip() if year_tag else "N/A"

        rating_tag = item.select_one("span.ipc-rating-star--rating")
        rating = rating_tag.text.strip() if rating_tag else "N/A"

        movies.append({
            "title": title,
            "year": year,
            "rating": rating
        })
    except Exception as e:
        print(f"解析电影时出错:{e}")
        continue

print(f"已提取 {len(movies)} 部电影")

第 5 步:用 Pandas 保存为 CSV 或 Excel

df = pd.DataFrame(movies)
df.to_csv("imdb_top_250.csv", index=False)
df.to_excel("imdb_top_250.xlsx", index=False)
print(df.head())

示例输出:

                          title  year rating
0  1. The Shawshank Redemption  1994    9.3
1           2. The Godfather    1972    9.2
2     3. The Dark Knight        2008    9.0
3  4. The Godfather Part II     1974    9.0
4         5. 12 Angry Men       1957    9.0

这样是能跑的。但它依赖的是可能随时失效的 CSS 选择器——这就引出了我真正推荐的方法。

方法 2:JSON-LD 技巧——完全跳过 HTML 解析

这是没有任何竞品文章会讲的方法,也是我在任何认真项目里都会用的方法。IMDb 会在每个页面的 <script type="application/ld+json"> 标签里嵌入结构化数据,也就是 JSON-LD(面向链接数据的 JavaScript 对象表示法)。这些数据遵循 Schema.org 标准,Google 也会拿它来生成富搜索结果,而且它比 CSS 类名稳定得多。

生产级工具 Apify IMDb Scraper 的提取优先级是:“JSON-LD > NEXT_DATA > DOM”。这也是我建议你采用的顺序。

为什么 JSON-LD 比 CSS 选择器更可靠

方法支持 JS 内容吗?能抗 UI 变化吗?速度复杂度
BeautifulSoup + CSS 选择器❌ 否⚠️ 脆弱(类名会变)
JSON-LD 提取✅ 是✅ 遵循 Schema.org 标准低-中
__NEXT_DATA__ JSON 提取✅ 是✅ 相对稳定低-中
Selenium / Playwright✅ 是⚠️ 脆弱中-高
Thunderbit(无代码,2 步)✅ 是(AI 直接读取页面)✅ AI 自动适配

ipc-metadata-list-summary-item 这样的 CSS 类名,是 IMDb React 组件系统自动生成的,改版时就会变化。JSON-LD 模式表达的是实际数据模型,而不是展示层。它们的区别就像:一个是看书的目录,另一个是试图根据字号大小来猜章节。

css-selectors-vs-json-ld.webp

逐步操作:从 JSON-LD 提取 IMDb 数据

第 1 步:抓取页面

和前面一样——使用带正确 User-Agent 请求头的 requests

import requests
from bs4 import BeautifulSoup
import json
import pandas as pd

url = "https://www.imdb.com/chart/top/"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "Accept-Language": "en-US,en;q=0.9"
}

response = requests.get(url, headers=headers)
soup = BeautifulSoup(response.text, "lxml")

第 2 步:找到 JSON-LD 脚本标签

script_tag = soup.find("script", {"type": "application/ld+json"})

if not script_tag:
    print("这个页面没有找到 JSON-LD")
else:
    data = json.loads(script_tag.string)
    print(f"找到 JSON-LD,类型为:{data.get('@type', 'unknown')}")

第 3 步:解析结构化数据

在 Top 250 页面上,JSON-LD 包含一个 itemListElement 数组,里面有全部 250 部电影。每个条目都包括排名、名称、URL、aggregateRating、发布日期、类型、描述、导演和演员数组。

movies = []

for item in data.get("itemListElement", []):
    movie = item.get("item", {})
    rating_info = movie.get("aggregateRating", {})

    movies.append({
        "rank": item.get("position"),
        "title": movie.get("name"),
        "url": movie.get("url"),
        "rating": rating_info.get("ratingValue"),
        "vote_count": rating_info.get("ratingCount"),
        "date_published": movie.get("datePublished"),
        "genre": ", ".join(movie.get("genre", [])),
        "description": movie.get("description"),
    })

第 4 步:导出为 CSV

df = pd.DataFrame(movies)
df.to_csv("imdb_top_250_json_ld.csv", index=False)
print(df.head())

示例输出:

   rank                      title                                     url  rating  vote_count date_published              genre
0     1  The Shawshank Redemption  https://www.imdb.com/title/tt0111161/     9.3     2900000     1994-10-14     Drama
1     2            The Godfather   https://www.imdb.com/title/tt0068646/     9.2     2000000     1972-03-24     Crime, Drama
2     3          The Dark Knight   https://www.imdb.com/title/tt0468569/     9.0     2800000     2008-07-18     Action, Crime, Drama

250 部电影全部到手。干净、结构化、没有任何 CSS 选择器的花活。并且因为这些数据遵循 Schema.org 标准(Google 做搜索结果也依赖它),所以比可视化布局更不容易变化。

额外技巧:用 __NEXT_DATA__ 获取单个电影页信息

如果你想拿到单个电影页更丰富的数据(时长、完整演员表、剧情简介、海报图片),IMDb 还会嵌入一个 __NEXT_DATA__ JSON 对象。这就是 React 用来“水合”页面的数据——如果删掉它,网站就会坏。

# 在类似 /title/tt0111161/ 这样的单个电影页面上
next_data_tag = soup.find("script", {"id": "__NEXT_DATA__"})

if next_data_tag:
    next_data = json.loads(next_data_tag.string)
    above_fold = next_data["props"]["pageProps"]["aboveTheFoldData"]

    title = above_fold["titleText"]["text"]
    year = above_fold["releaseYear"]["year"]
    rating = above_fold["ratingsSummary"]["aggregateRating"]
    runtime_seconds = above_fold.get("runtime", {}).get("seconds", 0)
    genres = [g["text"] for g in above_fold["genres"]["genres"]]
    plot = above_fold["plot"]["plotText"]["plainText"]

列表页用 JSON-LD,单个电影页用 __NEXT_DATA__。这就是生产级做法。

为什么你的 IMDb 爬虫老是坏掉(以及怎么修)

这是我查过的每一个 IMDb 抓取论坛里,被提到最多的痛点。用户会写:“因为 UI 变化,部分代码坏了”“2024 年还不能用!”——而回复通常要么是沉默,要么就是“试试 Selenium”。

根本原因是 IMDb 正在持续向 React/Next.js 前端迁移。下面是几个导致大规模失效的重要时间点:

日期变化内容受影响内容
2022 年 11 月姓名页重设计旧的姓名页爬虫
2023 年 6 月Top 250 页面重设计所有 td.titleColumn / td.ratingColumn 选择器
2023 年 4 月作品子页面重设计简介、奖项、新闻爬虫
2023 年 10 月高级搜索重设计基于搜索的爬虫
2025 年 6 月/reference 页面重设计Cinemagoer 库(大多数解析器)

差不多每 6–12 个月就会有一次重大破坏性变化。如果你的爬虫依赖 CSS 类名,那你基本是在跑步机上追页面。

常见错误以及修复方法

结果为空 / NoneType 报错

这是最常见的错误。你会看到 AttributeError: 'NoneType' object has no attribute 'text'。这表示 BeautifulSoup 没找到你要找的元素——通常是因为 CSS 类名变了,或者内容是由 JavaScript 渲染的。

修复方法:切换到 JSON-LD 提取(上面的方法 2)。数据就在初始 HTML 响应里,不需要 JavaScript。

403 Forbidden

IMDb 使用 AWS WAF 来检测并拦截机器人。最常见的触发原因是缺少或明显伪造的 User-Agent 请求头。这个问题在 多个开源项目以及 IMDb 自己的社区论坛里都有记录,IMDb 员工也承认过这个问题。

修复方法:始终带上真实浏览器的 User-Agent 字符串和 Accept-Language: en-US 请求头。使用 requests.Session() 做连接复用。

只返回 25 条结果

IMDb 搜索页和“最热门”列表使用的是懒加载——初始只渲染大约 25 条结果,随着你滚动再通过 AJAX 加载更多。

修复方法:使用 URL 参数分页(下一节会讲),或者直接切换到 Top 250 页面,因为它会在一次响应中加载完 250 部电影。

选择器突然失效

已经失效的旧选择器包括:td.titleColumntd.ratingColumn.lister-item-header.inline-block.ratings-imdb-rating。如果你的代码还在用这些,说明已经坏了。

修复方法:优先使用 data-testid 属性(比如 h1[data-testid="hero-title-block__title"]),不要用自动生成的类名。更好的办法是直接用 JSON-LD。

决策框架:短期修复 vs 长期修复

  • 短期修复:给每个选择器外层都包上 try/except,校验 HTTP 状态码,记录错误而不是直接崩溃
  • 中期修复:从 CSS 选择器切换到 JSON-LD 提取(方法 2)
  • 长期修复:如果要大规模分析,直接使用 IMDb 官方批量数据集,或者用像 Thunderbit 这样每次都会用 AI 重新读取页面结构的工具——不用维护选择器,AI 会自动适配布局变化

超越 25 条结果限制:IMDb 分页与大数据集抓取

我看过的每一个竞品教程都只抓一页。没有人讲分页。但如果你要的不只是一份单页列表,很快就会撞墙。

不需要分页的页面

好消息是:Top 250 页面会在一次服务器渲染响应里加载全部 250 部电影。JSON-LD 和 __NEXT_DATA__ 都包含完整数据集。不需要分页。

IMDb 搜索分页是怎么工作的

IMDb 搜索页通过 start= URL 参数分页,每次增加 50:

https://www.imdb.com/search/title/?groups=top_1000&start=1
https://www.imdb.com/search/title/?groups=top_1000&start=51
https://www.imdb.com/search/title/?groups=top_1000&start=101

下面是一段遍历结果的 Python 循环:

import time

all_movies = []

for start in range(1, 1001, 50):  # 遍历 top 1000
    url = f"https://www.imdb.com/search/title/?groups=top_1000&start={start}"
    response = requests.get(url, headers=headers)

    if response.status_code != 200:
        print(f"在 start={start} 处失败:{response.status_code}")
        break

    soup = BeautifulSoup(response.text, "lxml")
    # 用你喜欢的方法提取电影
    # ...

    print(f"已抓取起始于 {start} 的页面")
    time.sleep(3)  # 注意礼貌——IMDb 大约在 50 次快速请求后会开始封禁

这里的 time.sleep(3) 很重要。社区反馈显示,IMDb 在大约 50 次快速请求后就会开始封 IP。建议使用 2–5 秒之间的随机延迟。

什么时候可以完全不抓:IMDb 官方批量数据集

如果你真的需要大规模数据,IMDb 提供了 7 个免费的 TSV 文件,可在 datasets.imdbws.com 获取,并且每天更新:

文件内容大小
title.basics.tsv.gz片名、类型、类型标签、时长、年份~800 MB
title.ratings.tsv.gz平均评分、投票数~25 MB
title.crew.tsv.gz导演、编剧~300 MB
title.principals.tsv.gz主演/主创~2 GB
title.akas.tsv.gz各地区别名~1.5 GB
title.episode.tsv.gz电视剧集信息~200 MB
name.basics.tsv.gz人物:姓名、出生年份、代表作~700 MB

把它们载入 Pandas 很简单:

ratings = pd.read_csv("title.ratings.tsv.gz", sep="\t", compression="gzip")
basics = pd.read_csv("title.basics.tsv.gz", sep="\t", compression="gzip", low_memory=False)

# 按 tconst(IMDb 条目 ID)合并
merged = basics.merge(ratings, on="tconst")
top_movies = merged[merged["titleType"] == "movie"].nlargest(250, "averageRating")

这些数据集覆盖 2,600 多万条目。没有分页、没有选择器、没有 403 错误。许可证仅限个人和非商业用途——你不能重新发布或转售这些数据。

无代码捷径:Thunderbit 帮你处理分页

如果你需要带分页的 IMDb 数据,但又不想自己写分页逻辑,Thunderbit 原生支持点击分页和无限滚动。你只要告诉它抓取什么,剩下的它会自己处理——包括滚动加载内容。

试用 Thunderbit 处理分页 IMDb 数据

使用 Python 抓取 IMDb:完整可运行代码(可直接复制)

下面是两段可直接运行的独立脚本。

脚本 A:BeautifulSoup 方法(CSS 选择器)

import requests
from bs4 import BeautifulSoup
import pandas as pd

url = "https://www.imdb.com/chart/top/"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "Accept-Language": "en-US,en;q=0.9"
}

response = requests.get(url, headers=headers)

if response.status_code != 200:
    print(f"错误:{response.status_code}")
    exit()

soup = BeautifulSoup(response.text, "lxml")
movie_items = soup.select("li.ipc-metadata-list-summary-item")
movies = []

for item in movie_items:
    try:
        title = item.select_one("h3.ipc-title__text")
        year = item.select_one("span.cli-title-metadata-item")
        rating = item.select_one("span.ipc-rating-star--rating")

        movies.append({
            "title": title.text.strip() if title else "N/A",
            "year": year.text.strip() if year else "N/A",
            "rating": rating.text.strip() if rating else "N/A",
        })
    except Exception as e:
        print(f"因错误跳过电影:{e}")

df = pd.DataFrame(movies)
df.to_csv("imdb_top250_bs4.csv", index=False)
print(f"已保存 {len(df)} 部电影")
print(df.head())

脚本 B:JSON-LD 方法(推荐)

import requests
from bs4 import BeautifulSoup
import json
import pandas as pd

url = "https://www.imdb.com/chart/top/"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "Accept-Language": "en-US,en;q=0.9"
}

response = requests.get(url, headers=headers)

if response.status_code != 200:
    print(f"错误:{response.status_code}")
    exit()

soup = BeautifulSoup(response.text, "lxml")
script_tag = soup.find("script", {"type": "application/ld+json"})

if not script_tag:
    print("没有找到 JSON-LD 数据")
    exit()

data = json.loads(script_tag.string)
movies = []

for item in data.get("itemListElement", []):
    movie = item.get("item", {})
    rating_info = movie.get("aggregateRating", {})
    directors = movie.get("director", [])
    director_names = ", ".join(
        d.get("name", "") for d in (directors if isinstance(directors, list) else [directors])
    )

    movies.append({
        "rank": item.get("position"),
        "title": movie.get("name"),
        "url": movie.get("url"),
        "rating": rating_info.get("ratingValue"),
        "votes": rating_info.get("ratingCount"),
        "year": movie.get("datePublished", "")[:4],
        "genre": ", ".join(movie.get("genre", [])),
        "director": director_names,
        "description": movie.get("description"),
    })

df = pd.DataFrame(movies)
df.to_csv("imdb_top250_jsonld.csv", index=False)
print(f"已保存 {len(df)} 部电影")
print(df.head())

这两段脚本都包含错误处理,并能输出干净的 CSV。脚本 B 能给你更丰富的数据——导演、描述、URL——而且对布局变化更有韧性。

不写代码也能抓 IMDb(用 Thunderbit)

不是每个人都需要或想写 Python。也许你只是一个运营分析师,只想把本周评分最高的电影导到表格里。也许你是内容策略人员,想比较不同年份的类型趋势。在这些场景下,自己写爬虫就太大材小用了。

下面是用 Thunderbit 获取同样数据的方法:

开始前:

  • 难度:初学者
  • 所需时间:约 2 分钟
  • 你需要准备:Chrome 浏览器、Thunderbit Chrome 扩展(免费版可用)

第 1 步: 打开你想抓取的 IMDb 页面。在 Chrome 中打开 IMDb Top 250(或任何其他 IMDb 列表/搜索页面)。

第 2 步: 在 Thunderbit 侧边栏点击“AI 建议字段”。AI 会扫描页面并推荐列——通常会包括片名、年份、评分、类型,以及根据页面不同的其他字段。你会看到一个预览表,里面显示建议字段。

第 3 步: 按需调整字段。删除你不需要的列,或者点击“+ 添加列”,用自然语言描述你想要的内容(例如“导演名字”或“投票数”)。

第 4 步: 点击“抓取”。Thunderbit 会提取数据。对于无限滚动或分页页面,它会自动处理滚动。

第 5 步: 导出。点击导出按钮,选择你的格式——Excel、Google Sheets、CSV、Airtable 或 Notion。数据会在几秒内到达你的目标位置。

这里的关键优势不仅仅是省事——更重要的是 Thunderbit 的 AI 每次都会重新读取页面结构。IMDb 改版时(而且它一定会改),AI 会自动适配。没有要更新的选择器,没有要修的代码。对于任何曾经在截止日前夜 2 点被坏掉的爬虫折磨过的人来说,这价值很高。

Thunderbit 还支持子页面抓取——你可以点进每部电影的详情页,把演员、导演、时长以及列表页看不到的其他字段补充进表格里。如果你想看实际效果,可以查看 Thunderbit YouTube 频道

抓取 IMDb 合法吗?你需要知道这些

用户在论坛里经常直接问:“这样做合法吗?IMDb 不希望别人抓他们的网站。” 这是个很合理的问题,而且没有竞品文章真正讲清楚。

IMDb 的 robots.txt:Top 250 页面(/chart/top/)、单个影片页面(/title/ttXXXXXXX/)和姓名页(/name/nmXXXXXXX/)都没有被 robots.txt 屏蔽。被屏蔽的路径包括 /find/_json/*/search/name-text/user/ur*/ratings 以及各种 AJAX 接口。文件里没有指定 Crawl-delay

IMDb 的使用条款:相关条款写的是:“除非获得我们明确书面同意,否则你不得在本网站上使用数据挖掘、机器人、屏幕抓取或类似的数据收集和提取工具。” 另外还有一条禁止转售或商业使用抓取数据。

实际意味着什么:最近 2024 年的法院裁决(Meta v. Bright Data、X Corp v. Bright Data)认为,如果用户从未同意过服务条款,那么条款未必能约束用户——如果你是在未登录的情况下抓取公开可见数据,服务条款的可执行性就比较有争议。但这仍然是一个在变化中的法律领域。

更稳妥的替代方案:IMDb 的 官方可下载数据集明确允许个人和非商业用途。TMDb 的 API 也很宽松,免费 key 就能用。如果你想确保没有明显风险,这两个方案都很好。

实用建议:如果你确实要抓取,请保持礼貌的抓取频率(请求间隔 time.sleep(3)),设置正确的请求头,不要访问 robots.txt 明确屏蔽的路径。如果是商业项目,请咨询法律专业人士,或者直接使用官方数据集/API。

我们在 Thunderbit 博客里已经深入讨论过 网页爬取的法律影响

结论:选择最适合你的 IMDb 抓取方式

简短总结如下:

  • BeautifulSoup + CSS 选择器:适合学习基础知识。预计它每 6–12 个月就会坏一次。一定要加错误处理。
  • JSON-LD 提取:我最推荐给任何持续进行的 Python 项目。它遵循 Schema.org 标准,比 CSS 类名稳定得多,而且不用 JavaScript 渲染就能拿到干净的结构化数据。
  • __NEXT_DATA__ JSON:作为补充,用来获取单个影片页更丰富的数据(时长、完整演员表、剧情、海报图片)。
  • IMDb 官方数据集:适合大规模分析的最佳选择。2600 万+ 条目,每日更新,无需抓取。仅限个人/非商业用途。
  • Thunderbit:适合不写代码的人,或者想快速拿到数据、又不想维护代码的人。AI 会自动适配布局变化,支持分页,并可导出到 Excel/Sheets/Airtable/Notion。

把这篇指南收藏起来——等 IMDb 下次改结构时我会更新它。如果你想完全跳过代码,试试 Thunderbit 免费版,看看从一个 IMDb 页面到一份干净表格能有多快。如果你还会处理其他网站,我们关于把网站数据抓到 Excel 里的指南会覆盖更完整的工作流。

试试适用于 IMDb 及更多场景的 AI 网页爬虫 Get Started Free

常见问题

抓取 IMDb 合法吗?

IMDb 的使用条款禁止未经许可的抓取,但在最近 2024 年的法院裁决后,对于公开可访问数据上的服务条款是否具有约束力,法律上仍有争议。最稳妥的选择是使用 IMDb 的官方免费数据集(仅限个人/非商业用途)或 TMDb API(免费 key)。如果你确实要抓取,请尊重 robots.txt,设置合理的请求间隔,并避免访问被屏蔽的路径。商业用途请咨询法律专业人士。

为什么我的 IMDb 爬虫返回空结果?

几乎总是因为过时的 CSS 选择器——像 td.titleColumntd.ratingColumn 这样的类名自 2023 年 6 月起就已经不存在了。解决办法是改用 JSON-LD 提取(解析 <script type="application/ld+json"> 标签),或者把选择器更新为当前带 ipc- 前缀的类名。你还要确认自己加了正确的 User-Agent 请求头,因为缺少它会触发 403 错误,而这种错误看起来就像空结果。

如何抓取 IMDb 超过 25 条结果?

Top 250 页面会在一次响应里加载全部 250 部电影——不需要分页。对于搜索结果,请使用 start= URL 参数(每次增加 50)来翻页。例如:start=1start=51start=101。每次请求之间加上 time.sleep(3),避免被封。或者直接使用 datasets.imdbws.com 上的 IMDb 官方数据集,里面有 2600 万+ 条目,不需要分页。

什么是 __NEXT_DATA__,为什么要用它抓取 IMDb?

__NEXT_DATA__ 是一个嵌在 IMDb React/Next.js 页面 <script id="__NEXT_DATA__"> 标签里的 JSON 对象。它包含 React 用来渲染页面的完整结构化数据——片名、评分、演员表、类型、时长等。因为它代表的是底层数据模型,而不是视觉布局,所以比 CSS 选择器更能抵抗 UI 重设计。把它和 JSON-LD 一起使用,是最稳健的提取方式。

不写代码也能抓 IMDb 吗?

可以。主要有两种方式:(1)下载 IMDb 的官方批量数据集——7 个 TSV 文件,覆盖 2600 万+ 条目,每日更新,免费供非商业用途使用。(2)使用 Thunderbit 的 AI 网页爬虫,它会读取 IMDb 页面,自动建议提取字段,并且只需两步就能导出到 Excel、Google Sheets 或 CSV——不需要代码,也不需要维护选择器。

了解更多

Ke
Ke
Thunderbit 首席技术官 | 高级数据科学家与机器学习专家 Ke Shen 拥有近十年的机器学习和数据科学经验,毕业于哥伦比亚大学,曾任 Walmart Labs 高级数据科学家。他在 Python、R、Java 和统计学方面拥有深厚且备受同行认可的专业能力,并分享如何将复杂的 AI 算法从理论落地到生产级架构的实战经验。
目录

只要开口,就能抓取网页

用简单英文说出你的需求。或者更简单,什么都不用说。

试用 Thunderbit 免费
使用 AI 提取数据
轻松将数据传输到 Google Sheets、Airtable 或 Notion
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week