找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4769

积分

0

好友

617

主题
发表于 1 小时前 | 查看: 3| 回复: 0

我经常在 Pinterest 上找图片和视频素材。图片保存起来很直接,视频却经常停在“浏览器里能看,手上只有一个 URL”这一步。为了把一条公开视频存到本地,还得再找下载站或者跑一段脚本;偶尔用一次问题不大,用得多了就很烦,尤其是有些下载站的广告比下载按钮还积极。

Pinch 解析失败时的捂脸表情

所以我写了 Pinch。它和常见 Pinterest 下载工具的区别比较明确:只处理单个公开的视频 Pin,不做图板、个人页、图片和批量抓取;整个解析过程都在浏览器里运行,没有后端服务,也不需要代理,可以直接部署到 GitHub Pages。

我主要想解决两个问题:一是把单个公开 Pin 里的渐进式 MP4 找出来,省掉来回倒腾 URL 的步骤;二是验证这件事能不能只靠一个静态网页完成。静态解析现在已经跑通,不过下载能力只覆盖 MP4;HLS 只做到识别、探测和报错,还不能把 .m3u8 转成可下载的 MP4。

怎么用

在线页面放在 GitHub Pages,打开后只有一个输入框。Pinch 不要求登录,也不上传视频;浏览器会直接向 Pinterest 请求公开数据。

Pinch 网站首页界面,含 URL 输入框和 Get MP4 按钮

把公开 Pin 的完整 URL 粘进去,点击 Get MP4。解析成功后,页面会显示视频预览、分辨率、格式,以及当前浏览器可以执行的操作。

下面这次测试找到了一个 720 × 1280 的 MP4。结果页显示的是 Open MP4,因为 Pinterest CDN 没有允许当前网页直接读取视频字节;点开原始视频后,再使用浏览器自己的保存命令即可。

Pinch 解析结果页,显示视频预览和 Open MP4 按钮

如果视频响应允许跨域读取,按钮会显示 Download MP4,Pinch 会直接保存原始 MP4,不转码,也不重新压缩。页面显示哪个按钮,取决于浏览器实际探测到的结果。

静态网页怎么找到视频

一开始我试过直接读取 Pinterest 的 Pin 页面。页面返回的 HTML 里确实有不少数据,但浏览器受同源策略限制,无法从 GitHub Pages 读取它的响应内容。用命令行能看到 HTML,不等于网页里的 JavaScript 也能看到,这是做纯前端版本时遇到的第一个限制。

后来我找到了 Pinterest 小组件使用的公开 JSON 接口。它不需要登录、Cookie 或 API 密钥,而且允许其他网页跨域读取。Pinch 从输入的 URL 中提取数字 Pin ID,请求这份 JSON,再从普通 Pin 和 Story Pin 的嵌套结构里收集视频源。

公开 Pin URL
  → 提取数字 Pin ID
  → 请求公开的 widget JSON
  → 收集并归一化视频源
  → 校验媒体域名和 HTTPS 协议
  → 去重并优先选择渐进式 MP4
  → 探测浏览器能否读取视频响应

解析时不能只看 Pinterest 返回的顶层字段。有些 Story Pin 的顶层会显示 videos: null,真正的视频地址却放在更深的 video_list 里。Pinch 会递归检查这些结构,但最终只接受 Pinterest 视频 CDN 上的 HTTPS MP4 或 HLS 地址,其他域名即使混在返回数据里也不会进入结果。

这个 widget 接口是 Pinterest 的公开接口,但不是它承诺长期稳定的官方开发 API,数据结构以后可能变化。因此我把它封装在独立的 PinResolver 后面,解析逻辑也有脱敏测试样本。上游发生变化时,修改解析器就行,不需要把 UI 一起重写。

MP4 为什么有时只能打开

静态网页找到 MP4 地址以后,还有一道浏览器跨域限制。一个跨域视频可以在 <video> 标签里正常播放,但同一页面里的 fetch() 不一定能读取它的响应体。播放视频和让 JavaScript 拿到文件字节,在浏览器看来是两种权限。

Pinch 会先发送一个很小的 Range 请求探测媒体是否可读,然后按结果选择操作:

  • 响应可读时,获取原始 MP4 字节并通过 Blob 下载,按钮显示 Download MP4
  • 视频可以播放但响应体不可读时,不会把“打开链接”算作下载成功,而是显示 Open MP4,让用户在原始视频页面里保存;
  • 视频源不可用时,直接显示错误。

我也测试过给链接加 download 属性、使用 no-cors、Service Worker 等做法。它们都不能把不可读的跨域响应变成可读响应,所以纯静态页面无法强制把所有 Pinterest MP4 都保存成文件。加一个后端代理可以绕开浏览器这一层限制,但那会带来服务器、带宽、日志和素材中转,已经不是我想做的这个工具了。

MP4 与 HLS

Pinch 选择视频源时会优先使用渐进式 MP4。只要公开 Pin 里有 MP4,就走上面的预览和保存路径,这也是当前版本实际验证过的主要流程。

如果公开 Pin 没有 MP4,只有 .m3u8,Pinch 会识别出它是 HLS,并探测播放列表能否读取。目前无论播放列表被 CORS 拦截,还是能够读取但转封装流程尚未验证,页面都会返回明确错误,不会把 HLS 当成已经支持的下载能力。

Pinch 没有接入 ffmpeg.wasm,因为浏览器拿不到 HLS 播放列表和分片时,转封装库没有数据可处理。当前版本有 MP4 就走 MP4;只有 HLS 时会报错。以后如果能稳定读取完整的 HLS 资源,再考虑浏览器端无转码封装。

为什么只做单个公开 Pin

我在实现时参考过开源项目 pinterest-downloader 对单个 Pin、Story Pin 和 video_list 的处理,不过没有把它的图板、个人页、图片和批量下载功能搬过来。Pinch 从一开始就只想处理“我手上已经有一个公开 Pin URL,现在要把里面的视频存下来”这个场景。

当前支持的是路径中带数字 ID 的公开 Pinterest Pin 链接,包括常见子域和地区域名;pin.it 短链、私密 Pin、登录态、图板、个人页和批量抓取都不在范围内。工具不配置第三方 CORS 代理,也不处理 DRM 或访问控制绕过。

范围收窄以后,页面可以保持简单,安全边界也更容易检查。外部 JSON 一律按未知数据处理,媒体地址限定在 Pinterest CDN,标题和描述通过 textContent 写入页面,不直接插入 HTML。生产构建没有运行时 npm 依赖,静态文件部署到 GitHub Pages 就能运行。

代码与地址

Pinch 使用 TypeScript 和 Vite 编写。仓库里有 URL 校验、JSON 提取、视频源排序、媒体探测、下载路径和 DOM 行为测试,页面流程也使用 Playwright 在 Chrome、Firefox 和 WebKit 下检查。依赖 Pinterest 线上行为的测试单独运行,避免外部接口变化影响默认测试结果。

如果你也会从 Pinterest 保存单个公开视频,可以直接试一下。遇到解析失败或者 Pinterest 数据结构变化,也欢迎在评论区留言或在 GitHub 提 Issue。下载前请确认自己拥有相关内容,或者已经获得使用授权。

下载完成后的开心狗头表情




上一篇:搜索query难度评估:从推理链token复杂度说起
下一篇:CozyClay:开源浏览器3D预演工具,npx一条命令搞定AI视频分镜
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-8-31 06:45 , Processed in 1.127496 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表