【Rust 实战】抖音短视频解析工具

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 【Rust 实战】抖音短视频解析工具

0x00 开篇


一直都在写教程,今天咱们换换主题,一起来做一个小工具。咱们用 Rust 来写一个抖音短视频下载地址解析工具。本文用到异步、网络请求等相关知识。另外公众号官方社群(文末)也开放了,欢迎大家加入,一起畅谈 Rust 的未来。本篇文章的阅读时间大约 8 分钟。


0x01 视频解析原理


原理其实很简单,每个短视频对应一个 id,我们将 id 传给官方的 api 地址:https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids={id} 以得到当前短视频一些信息,如:视频名称,封面图片,音频地址,视频地址等等。这其中的视频地址就是可以下载的地址了。

id = 7162104318923967752 为例,请求的信息如下:


0a2653c851af460fa595bd959398a8f1.png


最终 video/url_list 中的值就是我们想要的了。


0x02 代码实现


添加第三方 crate 依赖


本篇文章将使用下面的依赖:

  • 异步:tokio
  • 网络请求:reqwest
  • json 解析: serde
# 异步
tokio = { version = "1.21.2", features = ["full"] }
# 网络
reqwest = {version = "0.11.12", features = ["json"] }
# json
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }


获取短视频 id


首先,我们通过用户输入的地址,获取短视频 id。短视频的地址都是如 https://v.douyin.com/xxxxxxx这种形式。当我们在浏览器请求此链接时,将会重定向为一个新的地址,我们所需的 id 就在新的地址中。

请求接下来以 https://v.douyin.com/h1YcUow 为例

直接上代码了:

let mut input = String::new();
// 输入 https://v.douyin.com/h1YcUow
std::io::stdin().read_line(&mut input).expect("read line error!");
// 获取 response
let result = create_default_client().get(input.as_str()).send().await;
let result = result.unwrap();
dbg(&result);
// 获取重定向后的地址,并解析id
let path = result.url().path();
let id = path.replace("/video/", "");

用户先输入短视频分享的链接https://v.douyin.com/h1YcUow, 然后请求这个链接,通过返回结果 response 中的 path 获取 id。下面是 response 的结果。

&result = Response {
    url: Url {
        scheme: "https",
        cannot_be_a_base: false,
        username: "",
        password: None,
        host: Some(
            Domain(
                "www.douyin.com",
            ),
        ),
        port: None,
  // 7162104318923967752 就是我们所需的 id
        path: "/video/7162104318923967752",
        query: Some(
            "previous_page=web_code_link",
        ),
        fragment: None,
    },
.....
}


通过 id 拼接链接并请求


// 请求拼接请求地址
let url = "https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=";
let url = format!("{}{}", url, id);
// 请求该链接
let result = create_default_client().get(url.as_str()).send().await;
// 结果转化为结构体
let result = result.unwrap().json::<DouYinResult>().await;

id 与链接拼接并请求,将请求结果通过 serde 转为 Rust 相对应的结构体。(DouYinResult 请参见源码)。


解析结果


let dou_yin_items = result.item_list.unwrap();
let dou_yin_item = dou_yin_items.into_iter().nth(0).unwrap();
// 视频名称
let video_name = dou_yin_item.desc.unwrap_or_default();
// 视频地址
let dou_yin_video = dou_yin_item.video.unwrap();
// 获取 play_address
let play_address = dou_yin_video.play_addr.unwrap();
// 获取 play_list
let play_list = play_address.url_list.unwrap_or_default();
// video url
let video_url = play_list.into_iter().nth(0).unwrap_or_default();

由于篇幅有限,上面解析的代码使用了大量 unwrap(),详细代码请参阅源码,项目中不建议大量使用 unwrap()。我们最终拿到的地址如下:

https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200fg10000cdieeejc77ucgndnburg&ratio=720p&line=0

这个地址就可以下载了。但是有个缺点,这个地址有水印,如果想要去掉水印,我们把地址中的 playwm 替换为 play就可以了。

最终地址:

https://aweme.snssdk.com/aweme/v1/play/?video_id=v0200fg10000cdieeejc77ucgndnburg&ratio=720p&line=0

获取最终视频源地址

其实到上面一步已经可以正常下载了,如果我们将上面的地址再请一次,链接会重定向到最终的视频地址,代码详见源码:

https://v5-colda.douyinvod.com/e7c51c7e6ee10322808d96a89931383a/638b1b04/video/tos/cn/tos-cn-ve-15c001-alinc2/38ba1730579642d1a2a1c70822caa4e6/?a=1128&ch=0&cr=0&dr=0&cd=0%7C0%7C0%7C0&cv=1&br=1676&bt=1676&cs=0&ds=3&ft=BajzJVVywhiRF_80mo~MWwQlQmpF2O_CvrKzCHsUdo0gl-A&mime_type=video_mp4&qs=0&rc=MzwzOjM7aWg0ZGZlZWVpNUBpanhxcWY6ZmhoZzMzNGkzM0AzYWFiYTUzXzExNl9fLTYuYSNvX2FkcjRnYmZgLS1kLS9zcw%3D%3D&l=202212031645330102091481403F60B65C&btag=a8000

这个地址可以在任意浏览器或者下载工具中下载了。


0x03 小结


原理和代码都还算比较容易,用到的接口也是官方接口,失效的几率很低,大概率可以长期使用。通过测试我也发现并不是所有的视频都可以下载,极少数视频无法下载。大家如果感兴趣可以下载源码并完善。但是是不是如果有GUI界面就好了,文章还没有结束,接下来我将会结合 tauri 来完成一个跨平台的短视频解析工具。

相关文章
|
13天前
|
人工智能 JavaScript 数据可视化
Cursor 、v0 和 Bolt.new:当今 AI 编程工具的全面解析与对比
本文对 Cursor AI、v0 和 Bolt.new 三大 AI 编程工具进行了全面比较,分析其各自优势与局限性,帮助开发者在不同工作流中灵活应用。
116 8
Cursor 、v0 和 Bolt.new:当今 AI 编程工具的全面解析与对比
|
6天前
|
架构师 关系型数据库 MySQL
MySQL最左前缀优化原则:深入解析与实战应用
【10月更文挑战第12天】在数据库架构设计与优化中,索引的使用是提升查询性能的关键手段之一。其中,MySQL的最左前缀优化原则(Leftmost Prefix Principle)是复合索引(Composite Index)应用中的核心策略。作为资深架构师,深入理解并掌握这一原则,对于平衡数据库性能与维护成本至关重要。本文将详细解读最左前缀优化原则的功能特点、业务场景、优缺点、底层原理,并通过Java示例展示其实现方式。
17 1
|
7天前
|
机器学习/深度学习 人工智能 算法
揭开深度学习与传统机器学习的神秘面纱:从理论差异到实战代码详解两者间的选择与应用策略全面解析
【10月更文挑战第10天】本文探讨了深度学习与传统机器学习的区别,通过图像识别和语音处理等领域的应用案例,展示了深度学习在自动特征学习和处理大规模数据方面的优势。文中还提供了一个Python代码示例,使用TensorFlow构建多层感知器(MLP)并与Scikit-learn中的逻辑回归模型进行对比,进一步说明了两者的不同特点。
26 2
|
7天前
|
Rust 编译器 开发者
Rust宏之derive的设计及实战
【10月更文挑战第18天】在 Rust 中,`derive` 宏是一种自动生成代码的工具,可为结构体和枚举类型自动实现特定 trait,减少重复代码。它通过语法糖简化代码,支持 Debug、Clone、PartialEq 等 trait 的自动实现,并允许开发者自定义 `derive` 宏以扩展功能。
|
9天前
|
JavaScript 调度
Vue事件总线(EventBus)使用指南:详细解析与实战应用
Vue事件总线(EventBus)使用指南:详细解析与实战应用
22 1
|
14天前
|
域名解析 网络协议 安全
DNS查询工具简介
DNS查询工具简介
70 4
|
27天前
|
Python
命令行解析工具 argparse
命令行解析工具 argparse
42 14
|
28天前
|
JSON Rust 安全
30天拿下Rust之实战Web Server
30天拿下Rust之实战Web Server
39 7
|
27天前
|
域名解析 网络协议 安全
DNS查询工具简介
DNS查询工具简介
49 4
|
4天前
|
存储 前端开发 JavaScript
前端模块化打包工具的深度解析
【10月更文挑战第13天】前端模块化打包工具的深度解析

推荐镜像

更多