效率工具

分析 Netflix 观看记录:按月统计与剧集排行

把 Netflix 账号里导出的“观看记录”CSV 变成一份个人观影小结:每个月看了多少条、看得最多的剧,以及哪天一口气连看了 4 集以上。日期格式会自动识别;遇到无法判断的情况(比如分不清 3/4 是 3 月 4 日还是 4 月 3 日),脚本会直接报错,而不是悄悄算错。

BINBHO · 图文教程

把 Netflix 账号里导出的“观看记录”CSV 变成一份个人观影小结:每个月看了多少条、看得最多的剧,以及哪天一口气连看了 4 集以上。日期格式会自动识别;遇到无法判断的情况(比如分不清 3/4 是 3 月 4 日还是 4 月 3 日),脚本会直接报错,而不是悄悄算错。

先看清成品

pytest 跑了 3 个测试,全部通过;用 9 行示例数据运行,输出了月份分布、排行和“2026-10-12《示例剧》4 集”。示例 CSV 是我按帮助中心的描述自己编写的(两列:Title、Date),没有拿真实账号的导出文件验证过。特别是日期写法,会随账号的语言和地区设置而不同,所以脚本做了自动识别和歧义检查。

注意:Netflix 没有面向公众的开放 API,本系列只用官方提供的功能和公开数据:账号里的观看记录导出、Tudum 的 Top 10 数据文件,以及 “What We Watched” 报告。不要爬取网站,不要绕过 DRM 或录屏,不要用 VPN 或代理切换地区,不要违反官方的家庭共享规则去共享账号(见“项目资源”里的帮助页面)。套餐价格以官方页面为准,本文不列数字。

做完之后你会得到什么?

成果 说明
viewing_stats.py 识别日期格式、按月统计、剧集排行、找出连看的日子
歧义保护 日/月顺序无法判断时直接报错,可以用 --format 指定
本地处理 数据不上传到任何地方

需要准备哪些环境?

项目 要求 说明
Netflix 账号 你自己的账号和档案 只分析你有权查看的档案
浏览器 网页版 导出功能在网页版的账号页面里
Python 3.8 以上 只用标准库

文件结构

33-netflix-A-src/
├── viewing_stats.py
├── sample_history.csv     # 自己编写的示例
└── test_stats.py

第 1 步:导出(官方帮助中心的步骤)

  1. 用网页浏览器打开账号页面(Account)。
  2. 选择 Profiles,再选一个档案。
  3. 打开 Viewing activity;如果列表不完整,点 Show More。
  4. 在页面底部点 Download all,下载 CSV 文件。

如果账号已经不再有效,帮助中心说明要通过“下载你的个人信息”来获取观看记录(链接见文末)。

第 2 步:脚本

viewing_stats.py:

"""分析 Netflix “观看记录”(Account → Profiles → 某个档案 → Viewing activity → Download all)导出的 CSV。
文件有两列:Title、Date。日期写法随账号的语言和地区设置而不同,脚本会自动判断,判断不了就报错。
用法:python viewing_stats.py NetflixViewingHistory.csv"""
import csv, sys
from collections import Counter, defaultdict
from datetime import datetime

FORMATS = ["%Y-%m-%d", "%m/%d/%y", "%d/%m/%y", "%m/%d/%Y", "%d/%m/%Y", "%d.%m.%y", "%d.%m.%Y", "%Y/%m/%d"]

def detect_format(dates):
    ok = [f for f in FORMATS if all(_try(d, f) for d in dates)]
    if not ok: raise ValueError(f"认不出日期格式,例如 {dates[0]!r}")
    families = {f.replace("y", "Y") for f in ok}       # 两位/四位年份算一类
    if len(families) > 1:
        raise ValueError(f"日期有歧义({', '.join(sorted(ok))} 都能解析),请用 --format 指定")
    return ok[0]

def _try(s, f):
    try: datetime.strptime(s, f); return True
    except ValueError: return False

def split_title(t):
    """'Show: Season 1: Episode' → ('Show', 'Season 1', 'Episode');电影只有一段"""
    parts = [p.strip() for p in t.split(": ")]
    return (parts[0], parts[1] if len(parts) > 2 else "", ": ".join(parts[2:]) if len(parts) > 2 else (parts[1] if len(parts) == 2 else ""))

def stats(rows, fmt=None):
    dates = [r["Date"] for r in rows]
    fmt = fmt or detect_format(dates)
    per_month, per_show, per_day = Counter(), Counter(), defaultdict(int)
    for r in rows:
        d = datetime.strptime(r["Date"], fmt).date()
        per_month[d.strftime("%Y-%m")] += 1
        show, season, ep = split_title(r["Title"])
        per_show[show] += 1
        per_day[(d, show)] += 1
    binges = sorted(((n, d, s) for (d, s), n in per_day.items() if n >= 4), reverse=True)
    return {"format": fmt, "total": len(rows), "months": dict(sorted(per_month.items())),
            "top_shows": per_show.most_common(5), "binges": binges[:5]}

if __name__ == "__main__":
    args = sys.argv[1:]
    fmt = args[args.index("--format") + 1] if "--format" in args else None
    rows = list(csv.DictReader(open(args[0], encoding="utf-8-sig")))
    s = stats(rows, fmt)
    print(f"共 {s['total']} 条记录(日期格式 {s['format']})")
    print("每月条数:", "  ".join(f"{m}:{n}" for m, n in s["months"].items()))
    print("看得最多:", ";".join(f"{t}({n})" for t, n in s["top_shows"]))
    for n, d, show in s["binges"]: print(f"连看:{d} 《{show}》{n} 集")

剧集标题一般写成“剧名: 季: 集名”,脚本按 ": " 拆开,取第一段作为剧名。如果剧名本身带冒号,统计时会被拆开,这种情况需要手动合并。

第 3 步:测试和运行

sample_history.csv:

Title,Date
"示例剧: 第 1 季: 第 6 集",10/12/26
"示例剧: 第 1 季: 第 5 集",10/12/26
"示例剧: 第 1 季: 第 4 集",10/12/26
"示例剧: 第 1 季: 第 3 集",10/12/26
"示例剧: 第 1 季: 第 2 集",10/5/26
"示例剧: 第 1 季: 第 1 集",10/5/26
"示例电影",9/28/26
"另一部剧: 第 2 季: 归来",9/14/26
"另一部剧: 第 2 季: 出发",9/13/26
$ python -m pytest -q
3 passed
$ python viewing_stats.py sample_history.csv
共 9 条记录(日期格式 %m/%d/%y)
每月条数: 2026-09:3  2026-10:6
看得最多: 示例剧(6);另一部剧(2);示例电影(1)
连看:2026-10-12 《示例剧》4 集

调试示例

只有十月的数据时,报日期有歧义

只取示例数据的前 6 行(全是十月,日期是 10/12 和 10/5):

$ python viewing_stats.py oct.csv
ValueError: 日期有歧义(%d/%m/%y, %m/%d/%y 都能解析),请用 --format 指定
$ python viewing_stats.py oct.csv --format %m/%d/%y
共 6 条记录(日期格式 %m/%d/%y)

完整的示例数据里有一行 9/28/26:28 不可能是月份,所以格式能确定下来。只有十月的数据时,10/12 既可以是 10 月 12 日,也可以是 12 月 10 日。如果脚本随便选一种,统计结果会悄悄错掉一半,所以这里选择报错。

常见问题

现象 原因 处理
认不出日期格式 你的地区用了别的写法 看一行原始数据,用 --format 指定
有乱码 用 Excel 打开后又另存了一次 直接用下载的原文件
同一部剧被统计成两部 剧名本身带冒号 手动合并
有档案看不到 你没有那个档案的权限 只统计自己的档案

模板规则

  • 只用官方导出的数据,不要爬取网页。
  • 日期无法判断时报错,不要猜。
  • 个人数据只在本地处理。

项目资源

用途 地址
查看和下载观看记录 https://help.netflix.com/en/node/101917
获取你的个人信息副本 https://help.netflix.com/en/node/100624
Python csv 模块 https://docs.python.org/3/library/csv.html
分享账号(官方规则) https://help.netflix.com/en/node/123277
Extra Members https://help.netflix.com/en/node/123279
使用条款 https://help.netflix.com/legal/termsofuse

没有 API,也能用官方的导出功能做出有用的个人统计。关键在于老老实实处理好格式,日期有歧义的时候宁可报错,也不要猜。