首页/新闻资讯/正文详情

小红书笔记详情API item_get_video_pro:从签名到批量采集全解析

发布时间:2026/9/25 3:55:18 来源:云帆数科 栏目:资讯中心
小红书笔记详情API item_get_video_pro:从签名到批量采集全解析
如果你正在做小红书内容分析、竞品调研或者达人运营大概率遇到过这个需求拿到某篇笔记的标题、正文、图片、视频、点赞收藏评论数最好还是结构化的 JSON。小红书官方开放平台并没有面向普通开发者的笔记详情接口所以这类需求通常要落到第三方聚合 API 上。今天要拆解的 item_get_video_pro就是这类接口里非常有代表性的一个——传入笔记 ID一次性拿回完整笔记详情。这篇文章会把一段可运行的示例代码从头到尾逐行解析一遍包括 App Key 准备、笔记 ID 提取、参数签名、请求与响应解析、图片视频下载以及我实际使用中踩过的坑。不管你是刚接触第三方接口的新手还是想搞清楚内部细节的开发者都能找到能直接抄作业的内容。1. item_get_video_pro 是什么为什么值得用它1.1 从命名看接口定位先说命名。item_get_video_pro 并不是小红书官方接口名而是第三方数据服务商沿用电商开放平台那套命名习惯起的。拆开看就是 item内容条目 get获取 video视频相关 pro专业版、完整版。用过淘宝、拼多多第三方 API 的人应该很眼熟它们的商品详情接口就叫 item_get后面加不同后缀表示不同版本。第三方服务商把这个体系平移到了小红书笔记场景好处是开发者一眼就能明白接口是干嘛的不用猜。同一个体系里通常还会存在几个变体常见的有接口名返回内容典型场景item_get标题、摘要、封面图快速判断笔记是否存在item_get_video视频直链、时长、封面只想下载视频素材item_get_video_pro笔记全字段正文、图片、视频、互动数据、作者信息深度分析、完整备份我一般建议直接使用 pro 版本。原因很实际一次调用拿到所有字段省得因为字段不够再去补一次请求而且多数服务商对 pro 接口单独计费或配独立 QPS很少出现基础版够用、pro 反而被限制的情况。当然最终还是要看你自己的需求粒度如果只是临时确认链接是否有效基础接口就够了。1.2 为什么不自己写采集脚本聊技术之前先回答一个绕不开的问题这东西不是用 requests 就能写吗为什么还要买第三方接口公开接口和自建采集的差距主要体现在维护成本上。小红书笔记页面不是纯静态的评论区、视频播放地址、互动数据接口都有独立的风控策略前端页面结构也经常调整。我早几年自己写过一版采集脚本第一周跑得好好的第二周页面改了个 className整个解析逻辑就废了。再加上笔记 ID 后面挂的一串 xsec_token参数不齐根本拿不到完整数据。这三笔账算下来自研的隐性成本远超买接口的费用。第三方 API 的价值在于把“解析页面 维护规则 处理风控”这件事集中做完了你只负责带上自己的密钥调用拿回来的 JSON 字段还是统一的。对内容分析、素材归档这种业务来说这是性价比最高的路径。不是说自研完全不行而是在大多数非核心业务里没有必要把时间花在跟页面结构较劲上。1.3 适合和不适合的场景结合我自己的使用经验item_get_video_pro 这类接口适合下面这些场景竞品笔记调研批量采集目标账号或话题下的笔记数据分析点赞、收藏、评论的比例结构。达人合作核验在合作前确认达人的真实内容数据、历史笔记避免只看后台截图被蒙。历史内容备份在自己的笔记被删除、账号异常时保留一份内容归档。指定清单的视频素材下载比如运营需要把某个博主的部分视频存到本地做二次分析。不适合的场景也很明确全站级采集、实时流式抓取、用户隐私字段获取。这些要么技术上成本极高要么合规风险很大最关键的是和平台规则直接冲突没必要碰。2. 调用前的准备密钥、链接提取与签名2.1 App Key 和 App Secret 从哪来第三方 API 服务商一般都有自己的开发者平台注册账号、创建应用之后会给你一对 App Key 和 App Secret也就是调用凭证。App Key 相当于用户名请求时明文传App Secret 相当于密码用来生成签名绝对不能在请求里直接暴露。有些平台还会额外生成 access_token用于更细粒度的权限控制这个看具体文档。我的习惯是用环境变量管理密钥不进代码、不进 Git 仓库。export XHS_APP_KEYyour_app_key_here export XHS_APP_SECRETyour_app_secret_here export XHS_API_BASEhttps://api.example.com/routerPython 里读取环境变量只需要 os.environ。这样做的好处是即使代码不小心被公开密钥也不会一并泄漏。真实发生过因为密钥硬编码在代码里、然后仓库被设为 public 的翻车事件几分钟内就被扫号工具抓到乱刷流量损失不小。密钥这类东西越晚落到文件系统越好。2.2 从分享链接里精准提取笔记 ID调用接口前核心参数只有一个note_id。用户手里拿到的往往不是 ID而是一个小红书分享链接。常见形态有这么几种短链http://xhslink.com/a/AbCdEf一般从微信、微博分享卡片里复制得到。网页链接https://www.xiaohongshu.com/explore/{note_id}?xsec_tokenxxx发现页链接https://www.xiaohongshu.com/discovery/item/{note_id}小程序链接路径里会带 /pages/note-detail/index?id{note_id}所以写一个提取函数处理多种格式是调用前的第一步。参考实现如下import re from urllib.parse import unquote def extract_note_id(text: str) - str | None: if not text: return None text unquote(text) patterns [ rexplore/([0-9a-zA-Z]), rdiscovery/item/([0-9a-zA-Z]), rnote-detail/index\?id([0-9a-zA-Z]), ritem/([0-9a-zA-Z]{20,32}), r([0-9a-zA-Z]{24}), ] for pattern in patterns: match re.search(pattern, text) if match: return match.group(1) return None有几个细节要注意。一是最前面的unquote(text)因为从微信分享出来的链接ID 部分可能被 URL 编码直接正则匹配容易落空。二是最后一条([0-9a-zA-Z]{24})属于兜底策略只在前面都匹配不到时才启用避免从链接参数里抓出别的字段。三是短链没法直接提取因为真实 ID 在跳转后的地址里这种情况可以先用 requests 跟随重定向拿到最终 URL再交给上面的函数处理。另外链接里那个 xsec_token 是给前端页面鉴权用的第三方接口一般只认 note_id不要把它拼进 API 请求里也不要存到数据库里没有任何长尾价值。2.3 签名与时间戳为什么参数要排序第三方接口最基本的安全机制是签名。常见签名规则是把所有业务参数按参数名的字典序ASCII 顺序排序拼成k1v1k2v2这样的字符串最后再拼接 App Secret整体做 MD5结果转成大写作为 sign 参数提交。import hashlib def make_sign(params: dict, secret: str) - str: ordered .join(f{k}{params[k]} for k in sorted(params)) raw ordered app_secret secret return hashlib.md5(raw.encode(utf-8)).hexdigest().upper()为什么要按字典序排序因为服务端校验时也要用同样的规则重新生成签名如果两边拼接顺序不一致结果必然对不上。这类校验规则的命名一般是“按 key 升序排列”。理解了这个你就能反过来排查签名错误先把你生成的参数字符串打出来和服务端文档里的例子逐字符比对。timestamp 参数也很关键。它一般是 10 位秒级时间戳服务端会校验它是否在合理时间窗口内通常是 ±5 分钟防止请求被重放。如果你的服务器时间不准就会出现“签名正确但时间戳过期”的诡异报错。同步一次系统时间就能解决。3. 示例代码逐行解析3.1 完整代码一览下面这段代码是我在实际项目里精简过的版本把核心链路都串起来了从粘贴的分享链接提取 ID请求接口解析返回 JSON再提供图片视频的下载能力。可以直接复制到本地改密钥使用。import hashlib import json import os import re import time import requests from urllib.parse import unquote APP_KEY os.getenv(XHS_APP_KEY, ) APP_SECRET os.getenv(XHS_APP_SECRET, ) API_BASE os.getenv(XHS_API_BASE, https://api.example.com/router) def extract_note_id(text: str) - str | None: if not text: return None text unquote(text) patterns [ rexplore/([0-9a-zA-Z]), rdiscovery/item/([0-9a-zA-Z]), rnote-detail/index\?id([0-9a-zA-Z]), ritem/([0-9a-zA-Z]{20,32}), r([0-9a-zA-Z]{24}), ] for pattern in patterns: match re.search(pattern, text) if match: return match.group(1) return None def make_sign(params: dict, secret: str) - str: ordered .join(f{k}{params[k]} for k in sorted(params)) raw ordered app_secret secret return hashlib.md5(raw.encode(utf-8)).hexdigest().upper() def get_note_detail(note_id: str) - dict: params { method: item_get_video_pro, app_key: APP_KEY, timestamp: str(int(time.time())), format: json, note_id: note_id, } params[sign] make_sign(params, APP_SECRET) resp requests.get(API_BASE, paramsparams, timeout10) resp.raise_for_status() result resp.json() if result.get(code) ! 0: raise RuntimeError(fAPI错误: {result.get(msg)} (code{result.get(code)})) return result[data] def download_file(url: str, path: str, referer: str https://www.xiaohongshu.com/) - bool: headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64), Referer: referer, } r requests.get(url, headersheaders, timeout20) if r.status_code 200 and r.content: with open(path, wb) as f: f.write(r.content) return True return False if __name__ __main__: raw_input_text input(粘贴小红书链接或笔记ID: ).strip() note_id extract_note_id(raw_input_text) if not note_id: raise SystemExit(未识别到笔记ID) data get_note_detail(note_id) print(json.dumps(data, ensure_asciiFalse, indent2)) media_dir fmedia/{note_id} os.makedirs(media_dir, exist_okTrue) if data.get(video) and data[video].get(url): download_file(data[video][url], f{media_dir}/note.mp4) for index, image in enumerate(data.get(images, [])): download_file(image.get(url, ), f{media_dir}/{index:02d}.jpg)3.2 预处理环境变量与笔记 ID 提取第 8 到 10 行从环境变量读配置为空时给一个占位默认值方便本地调试。第 13 行的 extract_note_id 函数整体不难但 two 细节值得多说一句正则顺序就是优先级顺序explore 优先兜底正则放在最后。很多人写正则提取时喜欢把最宽泛的规则放前面结果从链接里抓了 xsec_token 的一截出来定位半天才发现是顺序问题。先解码 URL再用顺序正确的正则列表去匹配能省很多排查时间。注意str | None这种写法需要 Python 3.10 以上实测用 3.9 会直接报语法错误。如果公司机器是 3.8可以改成from typing import Optional然后用Optional[str]功能一样。3.3 签名函数原理与实现make_sign 函数的逻辑在上文已经展开过这里补充一个容易忽略的点签名必须在业务参数确定后、且 sign 字段加入之前生成。看代码顺序就明白params 先填好 method、app_key、timestamp、format、note_id然后一行params[sign] make_sign(params, APP_SECRET)把签名补进去。如果先把 sign 放进 params 再签名那就变成“用包含自己的字符串去签名自己”永远对不上。如果服务商用的是更严格一点的 HMAC-SHA256把 MD5 的部分替换成 hmac 逻辑即可import hmac import hashlib def make_sign_hmac(params: dict, secret: str) - str: ordered .join(f{k}{params[k]} for k in sorted(params)) return hmac.new(secret.encode(), ordered.encode(), hashlib.sha256).hexdigest().upper()规则不外乎“拼接 加密”无非拼接顺序和摘要算法不同。先读懂文档再看代码就不会被各种签名库带偏。3.4 请求发送与返回解析get_note_detail 函数里requests.get 的 params 参数会自动把 dict 转成查询字符串中文和特殊字符也会自动编码这是 requests 库最方便的地方。timeout10 是必须加的不加的话遇到网络问题会一直挂在那里批量任务时线程越堆越多最后整池卡死。响应解析分两层第一层是 HTTP 状态码resp.raise_for_status()会把 4xx 和 5xx 直接抛成异常省得自己写判断第二层是业务状态码也就是返回 JSON 里的 code。很多第三方接口 HTTP 200 但业务报错所以不能只看 HTTP 状态。先判断result.get(code) ! 0非零就抛 RuntimeError这样调用方在捕获异常时能直接把业务错误信息带上排查问题很高效。3.5 图片视频下载与 Referer 处理download_file 函数是实战里很容易踩坑的一环。小红书 CDN 上的资源普遍有防盗链校验简单说就是看 HTTP 请求头里的 Referer 是不是来自小红书官方页面。不带 Referer或者带了个搜索引擎的 Referer大概率返回 403。所以下载时必须显式带上Referer: https://www.xiaohongshu.com/User-Agent 也要改成正常浏览器模样不能用 requests 的默认 python-requests。一个更隐蔽的坑是第三方接口返回的视频和图片 URL 是带签名的临时地址链接里有 Expires、Signature、x-oss-expires 这类参数过期时间从几小时到一天不等。所以拿到的链接不要只存数据库第二天再下载几乎是必然失败的。正解是拿到数据后尽快落盘或者安排一个定时任务及时拉取我后面第七部分会讲工程化做法。4. 返回数据结构与关键字段详解4.1 一次真实返回的 JSON 长什么样不同服务商的字段命名会有差异但核心结构大同小异。最外层通常是 code、msg、data 三件套data 里的结构大致如下{ note_id: 65f2d3d4000000001a01abcd, type: video, title: 周末露营装备清单, desc: 这周去了郊区的营地分享几个实用的装备..., images: [ { url: https://sns-img-qc.xhscdn.com/xxx?imageView2/0/w/1080/format/jpg, width: 1080, height: 1440 } ], video: { url: https://sns-video-qc.xhscdn.com/xxx.mp4?sign...t..., cover: https://sns-img-qc.xhscdn.com/xxx_cover.jpg, duration: 63, width: 720, height: 1280 }, interact_info: { liked_count: 1024, collected_count: 218, comment_count: 76, share_count: 12 }, user: { user_id: 5f4e3d2c1a00000000000001, nickname: 山系生活家, avatar: https://sns-avatar.qc.xhscdn.com/xxx.jpg, following_count: 365, follower_count: 12000 }, time: 1717000000, tag_list: [露营, 周末去哪儿] }拿到返回数据后第一件事不是对着文档找字段而是先print(json.dumps(data, ensure_asciiFalse, indent2))把完整结构打出来看一遍。因为服务商可能加了自定义字段或者改了嵌套层级直接按文档写代码往往会在真实数据上翻车。我自己的经验是先跑通一条把结构和索引关系摸清楚再写批量逻辑。4.2 图文笔记与视频笔记的判断type 字段决定了数据读取方式。常见值一般是 video 和 normal分别对应视频笔记和图文笔记。判断逻辑要按顺序覆盖三种情况if data.get(type) video: video_url data.get(video, {}).get(url) cover_url data.get(video, {}).get(cover) elif data.get(images): image_list data[images] else: # 纯文字笔记或者只带一张封面图的特殊类型 print(该笔记无视频且无图片列表)一个容易忽略的点视频笔记的封面图通常在 video.cover 字段里而不是 images 数组里。如果代码里只读取 images视频笔记就会得到空列表给运营同学交付时少了一张重要的封面图。图文笔记虽然也可能有 video 字段但一般为空对象或 None取值时要用.get(video, {})避免 NoneType 报错。4.3 互动数据、时间戳与类型陷阱interact_info 里的点赞、收藏、评论、分享数据是做竞品分析和达人核验的核心指标。这个字段名字还算统一但不同服务商返回的类型不统一——有的返回 int有的返回 str还有的用1024和1.2k这种简化格式。这在批量统计时会埋雷。最简单的做法是写一个统一转换函数def to_int(value) - int: if isinstance(value, int): return value if isinstance(value, float): return int(value) if isinstance(value, str): return int(value.replace(k, 000).replace(w, 0000)) return 0time 字段也是同理。可能是 ISO 字符串2024-06-01 12:00:00也可能是秒级时间戳。统一处理函数可以参考from datetime import datetime def parse_time(value): if isinstance(value, int): return datetime.fromtimestamp(value) if isinstance(value, str) and value.isdigit(): return datetime.fromtimestamp(int(value)) return datetime.fromisoformat(value)这些看起来都是小事但批量跑到一半报TypeError: can only concatenate str的时候你就知道统一类型转换有多重要了。4.4 媒体链接的有效期与防盗链上一节说过媒体链接是临时签名地址这里展开讲。图片 URL 里常见imageView2/0/w/1080/format/jpg这种参数可以控制目标尺寸。有需要可以手动改成/w/720或/w/1440但注意不要改签名相关参数否则链接就无效了。视频 URL 里的sign、t、x-oss-expires是签名参数改动任何一个都好直接废掉链接。我的处理原则是拿回链接后先按业务需要立刻下载不要只存 URL。如果确实需要长期保存把文件下载到本地或对象存储不要在数据库里依赖第三方临时链接。下载失败时先检查 Referer再检查是否过期不要反复用同一个失效 URL 重试浪费时间。5. 别小看风控合规调用与频率控制5.1 我的 Key 是怎么被限流的第三方接口虽然帮你处理了对平台页面的访问但它自己也有风控和配额限制因为它在服务上游同样要承受平台的压力。每个 App Key 都有 QPS 和日调用量上限超过就会被网关限流返回 HTTP 429 或者业务错误码。我自己踩过真实的坑。有一批笔记要做历史数据对比我写了个 for 循环没加任何 sleep一秒钟发出去十来个请求。跑了不到五十条接口就开始报错后台看消耗记录瞬时并发已经顶到套餐上限好几倍。等了大概十分钟限流才自动解除。所以别把第三方接口当作无限制的公共数据源它一样有成本、有容量。5.2 一个稳健的调用节奏后来的做法简单可靠单线程逐条调用每次请求之间至少间隔 1 秒。如果要上多线程并发也要用锁把“最后请求时间”保护起来。import threading import time lock threading.Lock() last_request_ts 0.0 def rate_limited_get_note(note_id: str, min_interval: float 1.2): global last_request_ts with lock: now time.time() wait last_request_ts min_interval - now if wait 0: time.sleep(wait) last_request_ts time.time() return get_note_detail(note_id)1.2 秒间隔对应 QPS 大约是 0.8稳妥且够用。如果套餐支持更高 QPS可以把 min_interval 调小到 0.2但初期阶段还是保守一点好。批量任务里还可以加一个本地缓存按 note_id 存结果TTL 一小时同样一条笔记不要重复请求。这既省调用量也避免对同一数据反复查询。5.3 数据使用边界与合规红线接口本身是工具用在哪里决定合规性责任在调用方。我的习惯是给自己定几条明确红线只获取公开可见的笔记信息不碰用户的私信、手机号、邮箱等隐私字段。不做全站级采集不批量导出他人内容用于二次售卖或骚扰式营销。数据用完即删备份最小化尤其涉及第三方个人内容的存档。关注服务商的用户协议如果协议里明确禁止某类用途就坚决不做。很多人觉得“第三方接口都买了怎么用是我的自由”实际上不是这回事。从内容生态的长远角度看正当使用公共数据做分析是一回事绕开规则去薅资源是另一回事。保持克制才能把这条路走得更长。6. 常见问题与排查实录6.1 高频报错速查表现象可能原因排查方向code0 但 data 为空笔记被删除、笔记 ID 不存在、链接解析错误在浏览器打开链接确认笔记存在打印传入的 note_id 对照sign 校验失败App Secret 错误、参数顺序不一致、中文编码问题本地打印待签名串与服务端文档逐字符比对timestamp 过期系统时间不准、时区差异同步 NTP 时间确认用int(time.time())HTTP 429触发频率限制降速等待检查套餐剩余配额图片/视频下载 403防盗链校验、链接过期带 Referer 请求重新调用接口拿新链接字段类型是字符串服务商字段类型不统一先 print 真实数据再做统一类型转换短链提取不到 ID链接在微信卡片中被包装过先跟随重定向再丢给 extract_note_id6.2 一次“视频打不开”的排查过程有次朋友反馈“接口返回正常视频 URL 也有但浏览器打开就 403。”我让他把 URL 发过来一眼就看到里面带了Expires和Signature再用浏览器访问果然显示签名过期。问题不在接口而在他把 URL 放在表格里存了两天才下载。排查步骤拆开看其实很简单先用浏览器直接打开返回的 URL确认 HTTP 状态。观察 URL 上是否有过期相关参数。如果过期重新调一次接口换新链接。如果链接没过期再检查 Referer 和 User-Agent。这套顺序下来90% 的“打不开”都能定位。日常开发中不要一上来就怀疑接口有问题先排除链接本身的时效性和防盗链比换接口、换服务商高效得多。6.3 用日志代替猜线上批量任务最忌讳“出错了不知道哪一条笔记、什么参数、什么错误”。加日志是成本最低、收益最高的习惯。import logging logging.basicConfig( levellogging.INFO, format%(asctime)s %(levelname)s %(message)s, filenamexhs_api.log, ) logger logging.getLogger(xhs_api) # 在请求完成后记录 logger.info(note_id%s statusok cost%.2fs, note_id, end_time - start_time) # 在异常处记录 logger.error(note_id%s error%s, note_id, exc)注意一个细节日志里可以记录 note_id、耗时、错误码但绝对不要记录 App Secret 和完整签名串。我有一次把整个签名前的字符串打进日志结果日志文件被其他人拷走后演练了一次“猜密钥”的风险。密钥相关的一律打码这是底线。7. 从脚本到工具批量采集的工程化落地7.1 用 Session 复用连接脚本单个跑没问题批量任务就要考虑性能了。requests 模块每次都新建 TCP 连接对短时大量请求是很浪费的。改用 Session 复用连接池速度会明显提升代码改动也不大。session requests.Session() session.headers.update({ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64), Referer: https://www.xiaohongshu.com/, }) def get_note_detail_session(note_id: str) - dict: params { method: item_get_video_pro, app_key: APP_KEY, timestamp: str(int(time.time())), format: json, note_id: note_id, } params[sign] make_sign(params, APP_SECRET) resp session.get(API_BASE, paramsparams, timeout10) resp.raise_for_status() result resp.json() if result.get(code) ! 0: raise RuntimeError(fAPI错误: {result.get(msg)} (code{result.get(code)})) return result[data]7.2 SQLite 去重与断点续跑批量任务如果用 CSV 保存进度跑挂了再重启要么重复请求要么漏跑。更稳的做法是用 SQLite 做主键去重note_id 唯一天然防止重复插入。CREATE TABLE IF NOT EXISTS notes ( note_id TEXT PRIMARY KEY, title TEXT, type TEXT, raw_json TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP );主流程可以这样写import csv import sqlite3 import time conn sqlite3.connect(xhs_notes.db) cursor conn.cursor() with open(note_ids.csv, r, encodingutf-8) as f: note_ids [row[0] for row in csv.reader(f) if row] for note_id in note_ids: exists cursor.execute( SELECT 1 FROM notes WHERE note_id?, (note_id,) ).fetchone() if exists: continue try: data get_note_detail(note_id) cursor.execute( INSERT INTO notes (note_id, title, type, raw_json) VALUES (?,?,?,?), (note_id, data.get(title, ), data.get(type, ), json.dumps(data, ensure_asciiFalse)), ) conn.commit() logger.info(note_id%s saved, note_id) except Exception as exc: logger.error(note_id%s error%s, note_id, exc) time.sleep(1.2)这里的关键好处是断点续跑任务中断后重新启动已经成功的笔记会被 exists 判断跳过只有失败的才需要重试不用自己维护复杂的进度文件。7.3 定时增量更新与变化跟踪做账号健康度分析时只抓一次快照不够用需要对比不同时间点互动数据的变化。可以加一个定时任务每天固定时间更新一遍 watch_list 里的笔记。from apscheduler.schedulers.blocking import BlockingScheduler def update_job(): for note_id in watch_list: try: data get_note_detail(note_id) update_note(data) except Exception as exc: logger.error(note_id%s error%s, note_id, exc) time.sleep(1.2) scheduler BlockingScheduler() scheduler.add_job(update_job, cron, hour9, minute0) scheduler.start()更新时记录一份历史变化表就能算出来“这条笔记最近一周涨了多少赞、多少收藏”这也是很多内容运营关心的核心指标。接口返回的互动数据在这里就有了更强的分析价值。7.4 素材归档目录设计如果下载图片和视频目录规划个人建议按“日期 笔记 ID”组织data/raw/2024-06-01/65f2d3d4000000001a01abcd/cover.jpg data/raw/2024-06-01/65f2d3d4000000001a01abcd/001.jpg data/raw/2024-06-01/65f2d3d4000000001a01abcd/note.mp4日期前缀方便按天清理和备份笔记 ID 保证唯一性文件名里的序号表示图片顺序。下载失败的媒体文件单独记录一个 failed.csv二次补拉时只需要读这个文件不会影响已成功的部分。最后补一句个人经验真正跑批量任务之前先拿 30 条数据做一次冒烟测试把返回字段、媒体链接时效、错误码全部打印出来看一遍确认接口行为没变化再放全量跑。这个习惯帮我避掉过很多次全量跑完之后才发现字段名已经调整的尴尬情况。接口文档会过期但你自己留下的那批真实返回数据不会过期它们才是后续开发最可靠的参考。

相关推荐

BigBlueButton 隐私与数据保护实践指南:录制、日志、缓存与 GDPR 合规配置
BigBlueButton 隐私与数据保护实践指南:录制、日志、缓存与 GDPR 合规配置

教育音视频后端前端 【免费下载链接】bigbluebutton A complete web conferencing system for virtual classes and more! 项目地址: https://gitcode.com/gh_mirrors/bi/bigbluebutton 点击查看 免费下载 本篇技术指南以 BigBlueButton 官方管理文档《Privacy》为… · 2026/9/25 3:55:12

网站添加百度统计:为 ChatGPT 微服务应用构建 PV/UV 数据观测能力
网站添加百度统计:为 ChatGPT 微服务应用构建 PV/UV 数据观测能力

文档教程后端 【免费下载链接】CodeGuide :books: 本代码库是作者小傅哥多年从事一线互联网 Java 开发的学习历程技术汇总,旨在为大家提供一个清晰详细的学习教程,侧重点更倾向编写Java核心内容。如果本仓库能为您提供帮助,请给予支持(关注、… · 2026/9/25 3:55:12

Kata Containers Agent Policy 实战:用 Rego 策略对 Guest 内 ttRPC 请求实施细粒度访问控制
Kata Containers Agent Policy 实战:用 Rego 策略对 Guest 内 ttRPC 请求实施细粒度访问控制

云原生容器运行时 【免费下载链接】kata-containers Kata Containers is an open source project and community working to build a standard implementation of lightweight Virtual Machines (VMs) that feel and perform like containers, but provide the workload isolat… · 2026/9/25 3:55:12

ODAC1120320Xcopy_32bit:可复位Oracle连接基线环境详解
ODAC1120320Xcopy_32bit:可复位Oracle连接基线环境详解

简介:本资源是面向.NET开发者与Oracle数据库运维人员的32位ODAC远程连接环境配置包,专为解决Windows平台下C#、ASP.NET等应用稳定连接Oracle数据库的部署难题。包内含ODAC 11.2.0.3.20核心组件(OLEDB、Oracle Managed Data Access、ASP.NET适… · 2026/9/25 4:23:47

J-Link隐藏技能:用VCOM虚拟串口一根线搞定调试与日志
J-Link隐藏技能:用VCOM虚拟串口一根线搞定调试与日志

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:23:47

videocache4cj LRU缓存清理策略详解:TotalSize与TotalCount怎么选
videocache4cj LRU缓存清理策略详解:TotalSize与TotalCount怎么选

videocache4cj LRU缓存清理策略详解:TotalSize与TotalCount怎么选 【免费下载链接】videocache4cj 一个支持边播放边视频缓存库,输入视频的URL就可方便快捷的实现视频边下边播功能 项目地址: https://gitcode.com/Cangjie-TPC/videocache4cj video… · 2026/9/25 4:23:41

ExternalDNS Node Source 实战:将 Kubernetes 节点 IP 自动同步到 DNS 托管区
ExternalDNS Node Source 实战:将 Kubernetes 节点 IP 自动同步到 DNS 托管区

云原生 【免费下载链接】external-dns Configure external DNS servers dynamically from Kubernetes resources 项目地址: https://gitcode.com/gh_mirrors/ex/external-dns 点击查看 免费下载 本文讲解如何在 ExternalDNS 中启用节点(Node&#xff09… · 2026/9/25 4:23:41

Cobalt Strike 4.5部署配置与红队实战避坑指南
Cobalt Strike 4.5部署配置与红队实战避坑指南

简介:Cobalt Strike 4.5是面向渗透测试、红队评估与安全研究的C2框架,支持HTTP/HTTPS/DNS/SMB等多种协议上线主机,内置提权、凭据导出、端口转发、Socket代理、Office攻击、文件捆绑、钓鱼等功能,并可调用Mimikatz等外部工具完成内… · 2026/9/25 4:23:35

宇树G1机器人SSH远程连接与网络调试实战指南
宇树G1机器人SSH远程连接与网络调试实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:23:29

数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)
数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码