刷短视频刷到一条特别对胃口的系列,想存到本地慢慢看,结果手动一条条点保存,点到第三十条的时候手指已经开始抗议;过两天发现作者又更新了,还得重新翻一遍主页找上次看到哪儿。后来我把这件事彻底交给命令行:固定三条命令,分别负责主页批量、合集定向、追更增量,跑完就进文件夹。下文提到的“平台”,指的就是标题里那个短视频平台,只是行文里统一用泛称,方便把方法迁移到其他同类站点。整套流程适合三类人:一是想给自己收藏的内容做本地归档的普通用户,二是需要整理素材做二次创作(在授权范围内)的内容从业者,三是想练手命令行批处理的开发者。不需要写代码,但需要愿意打开终端敲几行字。
1. 先把“手动保存”这件事拆开看
1.1 手动保存到底卡在哪三个环节
手动保存的痛点,从来不是“点一下”这个动作本身,而是这个动作背后的三件麻烦事。第一件是发现成本:你得先刷到、再点进作者主页、再往下翻,翻到上次的位置往往已经滑了十几屏。第二件是重复成本:同一个作者隔三差五更新,你每次都要从头翻,翻完还要凭记忆判断哪条是新的。第三件是整理成本:存下来的文件统一叫“视频”“视频(1)”“视频(2)”,过一周你根本不知道哪个是哪个,更别说按作者、按合集归类。
这三件事本质上都不是“观看”需求,而是“归档”需求。归档需求有两个硬指标:不能漏和不能重。手动操作在这两点上几乎必然翻车,因为人的短期记忆容量有限,翻到第八十条时你很难确定第三条到底存没存。用命令行做,就是把这个判断交给一个记录文件——下过的记一笔,下次直接跳过。这个思路在下载工具里叫“归档清单”,是整套流程的基石。
提示:归档清单是一个纯文本文件,里面一行一条已下载内容的唯一标识。它不需要你维护,工具会自动追加,但你要记得别随手删。
1.2 三条命令各自负责什么
很多人一上来就想找“一条命令搞定全部”的方案,结果参数越堆越长,出错时根本不知道是哪一段崩的。我的做法是拆成三条职责单一的命令,各自有独立的输出目录和归档文件:
| 命令 | 目标 | 输入 | 关键参数 | 输出目录 |
|---|---|---|---|---|
| 第一条 | 作者主页全部作品 | 主页链接 | 单页枚举、限速、写元数据 | archive/作者名/ |
| 第二条 | 指定合集/播放列表 | 合集链接 | 序号区间、序号前缀命名 | archive/合集名/ |
| 第三条 | 追更增量 | 主页链接(复用) | 归档清单、跳过已存在 | archive/作者名/ |
拆开的好处很直接:第一条跑挂了不影响第二条;第二条只想下前二十集时,改一个数字就行;第三条可以每天定时跑,跑完看一眼日志就知道新增了几条。这三条命令的底层参数有大量重叠,学会一条,另外两条只是换个链接和换几个开关。
1.3 为什么选命令行而不是图形界面
图形界面的下载器不是不能用,而是不适合批量。这类工具通常一次只处理一个链接,遇到主页合集要靠你手动一条条粘贴;就算支持批量,它们的进度展示也会把终端刷得满屏都是,你想回头看某一条的报错信息基本找不到。命令行工具的优势在于:可以 dry-run(只列清单不下载)、可以把输出重定向到日志、可以用脚本包起来定时跑、可以用参数精确控制“只下第 5 到第 20 条”。
还有一个容易被忽略的点是可复现。图形界面的设置藏在各种菜单里,换一台机器你得重新点一遍;命令行参数写在文本文件里,复制过去就能跑。我自己的习惯是把三条命令写进一个run.sh,注释标清楚每条是干什么的,换机器时连同配置文件一起打包带走。这套习惯在素材归档这种长期任务上,省下来的时间远超学习成本。
2. 开工前的环境、目录与边界
2.1 环境清单与版本核对
整套流程对硬件几乎没有要求,一台能正常上网的电脑即可,但软件侧有几项要提前确认。核心是一个支持命令行调用的通用下载器,下文所有示例统一用dl作为占位命令名,你安装好之后把dl替换成实际的可执行文件名即可。安装方式各平台不同,包管理器一条命令就能装,具体命令查对应项目的说明页,这里不展开。
装完先做版本核对,这一步别省:
dl --version版本太旧会出现两个典型问题:一是某些站点解析失效,表现为“能拿到标题但拿不到视频流”;二是归档清单的格式不兼容,导致追更判断失灵。我踩过一次坑,旧版本跑出来的归档文件里记录的是短标识,新版本比对的是长标识,结果第三条命令每次都觉得“全是新的”,把整个主页重下了一遍,磁盘直接告急。所以升级工具后,建议先用小批量试跑,确认归档逻辑没变。
另外要确认磁盘空间。这个不是拍脑袋估,有个简单公式:单条体积 ≈ 码率 × 时长 ÷ 8。以常见的 1080p 竖屏视频为例,码率按 2.5 Mbps 算,一条 3 分钟的视频约 2.5 × 180 ÷ 8 ≈ 56 MB,实际文件因为音轨和封装开销会略大,按 60 MB 估比较稳。一个三百条作品的主页就是 18 GB 左右。留出 1.3 倍余量,也就是准备 25 GB 以上再开跑。
2.2 目录结构怎么设计才不乱
目录结构这件事,我的建议是一条命令一个根目录,作者名和合集名做二级目录,序号做文件名前缀。听起来简单,但顺序不能反:如果先按日期分,你以后想找某个作者的全部作品就得跨十几个文件夹;如果先按作者分,同一个作者的所有内容天然聚在一起,合集作为一个子目录挂在他下面,层级清晰。
具体长这样:
archive/ ├── 作者A/ │ ├── 20240101_第一条标题.mp4 │ ├── 20240103_第二条标题.mp4 │ └── 合集-某系列/ │ ├── 001_第一集.mp4 │ └── 002_第二集.mp4 └── 作者B/ └── ...为什么不建议把序号放最前面做全局编号?因为你没法保证第二条命令和第一条命令的抓取顺序一致,全局编号很容易冲突。用作者内局部编号或者直接用内容唯一标识做文件名,才是稳妥的。我在命名模板里同时保留了唯一标识和标题,前者保证不重名,后者保证可读性。
注意:Windows 对文件名有长度限制(完整路径约 260 字符),标题特别长的视频会被截断甚至写入失败。下载器一般有截断参数,把标题部分限制在 60 个字符以内比较安全,这个细节后面第 4 节会细讲。
2.3 能存什么、不能存什么
这一段必须放在动手之前讲清楚。命令行批量下载,最容易出问题的地方不是技术,而是边界。我给自己定了三条规矩,供参考:
- 只存自己有权保存的内容:自己发布的、作者明确允许保存的、平台本身提供保存入口的。下载行为不等于获得传播授权,存到本地自己看和二次发布是两回事。
- 不绕过任何访问限制:只处理自己账号正常登录状态下可见的内容,不尝试获取需要额外权限的资源。
- 不公开分享下载结果:本地归档就放本地,不建群、不打包分发、不上传到任何公开位置。
这三条不是套话,是我实际吃过教训后总结的。早些年把一批素材打包发给朋友,后来才知道其中有些内容作者是限制转载的,虽然最后删掉了,但那种“不确定有没有越界”的感觉很不舒服。归档这件事,边界清楚,才能做得长久。
3. 三条命令的完整拆解
3.1 第一条:把作者主页整页搬下来
主页抓取的关键,是让工具能枚举出主页下所有作品的链接。有些站点的作者主页是分页加载的,工具需要跟着翻页;有些是滚动加载,工具需要走接口。不管哪种,通用下载器大多已经内置了处理逻辑,你要做的是给它正确的入口链接,加上必要的登录凭证。
先跑一次只列清单不下载的干跑,这是最值得养成的习惯:
dl --cookies cookies.txt --flat-playlist --print "%(id)s | %(title)s" "作者主页链接" > list.txt--flat-playlist的意思是“只枚举不解析详情”,速度快很多;--print把每条的唯一标识和标题打到标准输出,重定向到list.txt。跑完之后wc -l list.txt看一眼条数,和你肉眼估计的数量对不对得上。如果只出来一两条,说明主页链接不对,或者登录状态失效了,这时候先别急着下载。
确认清单没问题,再跑正式命令:
dl --cookies cookies.txt \ --output "archive/%(uploader)s/%(id)s_%(title).60s.%(ext)s" \ --write-info-json \ --write-thumbnail \ --sleep-requests 1.5 \ --limit-rate 2M \ --retries 5 \ "作者主页链接"逐项解释一下为什么这么配。--output里的%(uploader)s是作者名,自动按作者分目录,省去手动整理;%(id)s是唯一标识,保证重名不覆盖;%(title).60s把标题截到 60 字符;%(ext)s保留原始扩展名。--write-info-json把标题、发布时间、简介等元数据单独存一份,以后要按时间筛选或者做检索,靠这个文件比翻文件名靠谱得多。--write-thumbnail存封面,做素材整理时封面比视频本身更容易快速辨认。
--sleep-requests 1.5是每次请求之间停 1.5 秒,这个参数看起来是“拖慢速度”,实际上是保护自己。短时间高频请求很容易触发站点的访问频率限制,轻则返回空数据,重则临时封禁,反而更慢。我实测过,不加这个参数抓两百条,跑到八十条左右开始出现零星失败;加上 1.5 秒之后,两百条一次跑完,失败率为零。慢就是快,在这里是真的。
--limit-rate 2M是限速 2 MB/s。这个值怎么定?看你家带宽和是不是要同时干别的事。按 2M 算,一条 60 MB 的视频约 30 秒,三百条约 2.5 小时。如果你不急着要,甚至可以压到 500K,晚上挂着跑。限速的另一个作用是避免把上行下行占满,家里人刷视频不至于卡。
3.2 第二条:合集只抓你要的那一段
合集和主页的参数差异不大,核心在两个地方:入口链接不同,以及要能按序号区间截取。合集往往有几十上百集,你未必需要全部,比如只想补最新的二十集,或者只想存前十集做参考。
dl --cookies cookies.txt \ --playlist-items 1-20 \ --output "archive/%(uploader)s/合集-%(playlist_title).40s/%(playlist_index)03d_%(title).50s.%(ext)s" \ --write-info-json \ --sleep-requests 2 \ "合集链接"--playlist-items 1-20是区间参数,支持多种写法:1-20是连续区间,1,3,5是指定几条,5-是从第五条到结尾。我常用的组合是先跑--flat-playlist --print "%(playlist_index)s | %(title)s"把整个合集的目录打出来,看一眼总集数和每集标题,再决定要哪一段。这个动作花不了两分钟,但能避免“下完一百集才发现只要后二十集”的尴尬。
%(playlist_index)03d是补零到三位的序号,001、002、003 这样排。补零的意义在于排序正确:如果不补零,1、10、11、2 会按字符串顺序排,播放器里顺序全乱。三位数够用到 999 集,一般合集到不了这个量级;真超过了就改成%04d。
合集命名里我加了“合集-”前缀,目的是和主页抓下来的散条区分开。同一个作者的内容,散条在作者根目录,合集在子目录,两者不混。这里有个细节要注意:合集里的视频往往也会出现在作者主页的时间线里,如果两条命令都跑,同一个视频会被存两份。解决办法有两个:要么合集单独用一个归档文件,跑之前把主页已下的标识导进去;要么干脆约定“合集内容只走第二条命令”,主页抓取时用参数把合集内的条目排除掉。我选的是后者,规则简单,不容易乱。
3.3 第三条:追更模式,只下新的
追更模式是整套流程里最省心的,也是最能体现“三条命令”价值的。它的核心只有一个参数:--download-archive,指定一个归档清单文件。工具每下完一条,就往这个文件里追加一行唯一标识;下次跑的时候,先读这个文件,已经存在的直接跳过。
dl --cookies cookies.txt \ --download-archive archive/done.txt \ --output "archive/%(uploader)s/%(id)s_%(title).60s.%(ext)s" \ --sleep-requests 1.5 \ --limit-rate 2M \ --break-on-existing \ "作者主页链接"--break-on-existing这个参数值得单独说。它的作用是:遇到第一条“已下载”的记录就停下来,不再继续往后翻。为什么需要它?因为主页是按时间倒序排的,最新的在前面,你昨天已经下到第 50 条,今天跑的时候前 50 条都会命中归档,如果不加这个参数,工具会老老实实把 50 条挨个检查一遍才去找第 51 条,白费几十次请求。加上之后,翻到第一条旧的立即收工,追更一次通常十几秒就结束。
但这个参数有个副作用要注意:它假设更新是严格追加在头部的。如果作者删了旧视频又重发,或者合集顺序被调整过,--break-on-existing可能会提前停,导致漏掉夹在中间的新内容。我的应对办法是每周做一次不带该参数的完整检查,月底做一次全量核对。日常追更用快速模式,周期性用完整模式兜底,两者配合基本不会漏。
提示:归档文件不要和下载目录放太近,也不要放在会被清理工具扫到的位置。它一旦丢失,追更就会退化成全量重下,而且因为文件名带唯一标识,不会覆盖,只会产生重复文件。
4. 参数调优:让文件一眼能认、让跑批不翻车
4.1 命名模板的三个陷阱
命名模板看着简单,实际是最容易踩坑的地方。第一个陷阱是非法字符:标题里带斜杠、冒号、问号是常事,直接拼进文件名,在 Windows 上会写入失败,在 Linux 上会被当成路径分隔符,文件散落到意想不到的目录。解决办法是加--windows-filenames,让工具统一做字符替换。
第二个陷阱是标题过长。前面提过 260 字符限制,实际还要扣掉目录路径的长度。我的模板里标题部分一律用%(title).50s或.60s截断,宁可短一点,也不要赌运气。截断之后如果还想保留完整标题,靠--write-info-json存的元数据文件补回来。
第三个陷阱是同一作者改名或同标题多发。有些作者会改昵称,如果目录名依赖%(uploader)s,改一次名就多出一个目录。我的处理是第一次抓取后手动把目录名固定下来,后续命令直接写死路径,不再用变量。多花一分钟,省掉以后合并目录的麻烦。
4.2 画质、格式与体积怎么平衡
画质选择本质是体积和清晰度的取舍。竖屏短视频在手机上看,720p 和 1080p 的差别远没有想象中大,但体积可能差一倍。我的策略是分场景:纯收藏、以看内容为主的,选 720p 足够;涉及文字、图表、需要看清细节的,选 1080p 或更高。
工具一般支持格式选择参数,写法类似-f "bv*[height<=1080]+ba/b",含义是“优先选高度不超过 1080 的最佳视频流加最佳音频流,找不到就退而求其次选合并好的单文件”。这个写法的好处是不会因为某个清晰度缺失而整体失败,斜杠后面的部分是兜底方案。我自己踩过的坑是写死了某个格式编号,结果作者某条视频没提供那个清晰度,整批任务在这里中断,前面的都白等。
音频也是同理。有些视频的音轨是分离的,需要合并;合并需要系统里有相应的处理程序,缺了会报错。建议第一次跑之前先用一条视频试,确认合并环节正常,再上批量。
4.3 断点续传、重试与限速的组合
网络不是理想环境,跑几百条的任务一定会遇到中途失败。三个参数决定失败后能不能自动恢复:
| 参数 | 作用 | 推荐值 | 说明 |
|---|---|---|---|
--continue | 断点续传 | 开启 | 中断的分片文件下次接着下,不重头来 |
--retries | 单条重试次数 | 5 | 网络抖动导致的失败大多能在 5 次内恢复 |
--fragment-retries | 分片重试 | 10 | 分片下载模式下更细粒度的重试 |
--sleep-requests | 请求间隔 | 1.5 到 2 秒 | 防频率限制,比提速更重要 |
--limit-rate | 限速 | 1M 到 2M | 按带宽和时段调整 |
这几个参数组合起来,能让一个两三百条的任务在无人值守的情况下跑完。是否每次都开启--continue?我建议一直开着,它只在检测到部分文件时生效,正常情况没有副作用。真正需要留意的是磁盘写满导致的中断,这种情况续传也救不回来,所以跑大批量之前先看一眼剩余空间,别等跑到 90% 才发现不够。
5. 常见问题与排查实录
5.1 报错速查表
下面这些是我在实际跑批中反复遇到的,按出现频率排序:
| 现象 | 大概率原因 | 排查动作 | 处理方式 |
|---|---|---|---|
| 只拿到标题,视频流为空 | 登录状态失效 | 看日志里的状态码 | 重新导出登录凭证 |
| 请求返回 403 | 频率过高或凭证过期 | 检查是否刚跑过大批量 | 降速、加长间隔、更新凭证 |
| 合集只下到第一条 | 区间参数写错 | 干跑打印序号 | 修正--playlist-items |
| 文件名是乱码 | 编码不匹配 | 看系统 locale | 加文件名规范化参数 |
| 追更每次都重下 | 归档文件丢失或版本不兼容 | 检查文件是否存在、内容格式 | 重建归档或统一版本 |
| 进度卡在某个百分比 | 分片源异常 | 单独重跑该条 | 加重试、必要时跳过后补 |
| 磁盘写入失败 | 空间不足或路径过长 | 看剩余空间、路径长度 | 清理空间、缩短命名 |
这张表里,登录凭证失效是最高频的问题,没有之一。它通常在跑了一段时间后突然出现,表现是“原本正常的任务全部失败”。原因是凭证有有效期,过期了就得重新导出。我的做法是每周固定检查一次,别等跑挂了才发现。凭证文件本身要当敏感文件对待,权限收紧,不要随手放在共享目录里。
5.2 抓不全、重复下载、封面缺失
抓不全有三种典型场景。第一种是主页作品太多,工具默认只翻前几页,需要在参数里显式指定“遍历全部”,或者用--playlist-end给一个足够大的数。第二种是部分作品被作者设为仅粉丝可见或已删除,这类本来就不该抓,日志里会标出来,忽略即可。第三种是网络中途失败但被重试机制掩盖了,表面跑完了,实际少几条——这就是为什么我坚持跑完后用行数对账:ls | wc -l和日志里的成功计数比一下。
重复下载几乎都是归档文件的问题。要么是没用--download-archive,要么是归档文件被删了,要么是升级工具后标识格式变了。排查顺序很简单:先看文件在不在,再看里面记录的数量和已下载文件数量对不对得上。有个细节值得注意:如果文件名模板改过(比如加了前缀),老文件在磁盘上存在但工具判断“不存在”,因为它按新模板算出来的路径去找。这种情况要么别改模板,要么改之前先把老文件批量重命名对齐。
封面缺失通常不是致命问题,但在做素材整理时很影响效率。封面下载失败一般是因为封面资源单独走了另一个地址,而那个地址被限流了。解决办法是把封面下载和视频下载拆开跑,封面单独跑一遍,间隔放长一点。实在下不下来也不影响视频本身,可以先跳过,后面补。
5.3 追更失效的三种隐蔽原因
追更失效最让人头疼,因为它不报错,只是“什么都没下”,你以为没更新,其实是有新内容没抓到。我遇到过的三种原因:
第一种是主页链接带参数。有些链接后面跟了一串追踪参数,今天复制和明天复制不一样,工具会把它们当成两个不同的来源,归档记录对不上。解决办法是手动清理链接,只保留路径部分。
第二种是作者置顶内容打乱了顺序。置顶视频永远在最前面,如果它已经下载过,--break-on-existing会在第一条就停下,后面的新内容全部漏掉。这个坑我踩得很深,连续三天以为作者没更新,第四天手动翻才发现漏了五条。现在的做法是追更命令不加--break-on-existing,或者加了之后每周做一次完整检查。
第三种是归档文件被同步工具覆盖。如果归档文件放在网盘同步目录里,多台机器同时跑,后写的会覆盖先写的,记录就丢了。归档文件老老实实放本地,别同步,这是最省事的做法。
6. 长期维护:把三条命令变成日常习惯
6.1 定时任务与日志留痕
跑通一次不难,难的是坚持几个月还不乱。我的做法是把三条命令写进一个脚本,用系统自带的定时任务每天凌晨跑一次,输出全部重定向到带日期的日志文件:
#!/bin/bash DATE=$(date +%Y%m%d) LOG="logs/run_${DATE}.log" dl --cookies cookies.txt --download-archive archive/done.txt \ --output "archive/%(uploader)s/%(id)s_%(title).60s.%(ext)s" \ --sleep-requests 2 --limit-rate 1M --retries 5 \ "作者主页链接" >> "$LOG" 2>&1 echo "done $(date)" >> "$LOG"日志的价值在于事后可追溯。某天发现少了几条,翻日志能看到当时是报错了、还是根本没枚举到。日志文件按日期命名,保留三个月,老的定期清理。这个习惯坚持下来,你会发现自己对“哪条什么时候下的、为什么失败”心里有数,而不是每次出问题都从零排查。
定时任务的时间点也有讲究。选凌晨是因为这个时段网络相对空闲,限速可以压得更低,对别人影响小,自己也跑得稳。如果任务量不大,隔天跑一次也够用,没必要天天跑。
6.2 归档与去重:定期做一次体检
跑得越久,越容易积累“看不见的重复”。同一段内容可能因为作者重发、合集和主页交叉、模板变更等原因存了两份。我一般每月做一次体检,分三步走:
第一步,按文件大小和时长粗筛。完全相同的两个文件,大小一模一样,用find加-size很容易找出来。第二步,对疑似重复的做内容校验,比对比对文件头部的特征值。第三步,人工确认后删掉旧的、保留命名规范的那份。
去重这件事不要图省事用“文件名相同就删”,因为不同清晰度的同名文件很常见,删错了画质就降级了。宁可多花十分钟核对,也不要一键清理之后后悔。
还有一个容易被忽视的维护动作:归档文件定期备份。它很小,几百 KB,但价值极高。我把它和脚本一起放进一个独立的备份目录,每次跑完顺手复制一份带日期的。真出问题时,最多损失一天的记录,而不是全部重来。
6.3 我在实际操作中的几点体会
最后分享几个纯经验层面的东西,都是踩过坑之后才想明白的。
第一条命令不要一上来就跑全量。先拿一个作品少的作者练手,跑通全流程,确认目录结构、命名、元数据都符合预期,再换大号。我第一次直接拿一个几百条的主页开跑,跑到一半发现命名模板里有个参数写错,几百个文件全是不想要的名字,重命名花了半小时。先小后大,这个顺序不能省。
登录凭证要当成消耗品管理。它不是一次配置永久有效,过期是常态。与其等它失效后手忙脚乱,不如固定周期主动更新,比如每周一早上换一次。凭证文件权限收紧,不要提交到任何代码仓库,也不要放在会被自动同步的地方。
速度和稳定永远选稳定。我试过把请求间隔压到 0.3 秒,前五十条飞快,第六十条开始连续失败,最后不得不整体重跑。把间隔放回 1.5 秒,慢是慢了点,但一次跑完不用管。批量任务最怕的不是慢,是跑到一半断了还得重来。
目录名手动固定,别完全依赖变量。作者改名、合集改标题是常事,变量一跑,目录就分裂。第一次抓完,把目录名定死写进脚本,后面省心很多。
留一份清单给自己看。除了归档文件,我还会定期导出一份人类可读的清单:作者、标题、发布时间、文件路径。不用多复杂,一个文本表格就行。半年后回头找某条内容,翻清单比翻文件夹快得多。这个习惯听起来笨,但确实是长期归档里最实用的一招。