IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android初学 抖音短视频无水印下载APP的实现 -> 正文阅读

[移动开发]Android初学 抖音短视频无水印下载APP的实现

实现效果:

  1. 在抖音复制分享链接
    点击抖音分享复制分享链接
  2. 粘贴分享链接到App, 点击解析
    粘贴分享链接到App, 点击解析
  3. 点击 去下载 进入浏览器下载
    点击去下载进入浏览器下载

获取无水印视频链接

首先我们使用浏览器打开分享的链接

8.97 teO:/ 一起玩水吧 在这炽热的夏天%%蓝色治愈系 %%夏天 %%游泳 https://v.douyin.com/Y5SpHKD/ 复制此链接,打开Dou音搜索,直接观看视频!

然后打开控制台找到对应的视频, 右键检查可以找到视频的链接
https://www.douyin.com/aweme/v1/play/?video_id=v0200fg10000ca08sgbc77udtm7m06p0
F12查看视频原链接
然后在浏览器中打开此链接发现是没有水印的视频, 稍后下载的视频使用的是此链接.
打开此链接发现是没有水印的视频
通过测试其他分享的视频发现不同视频对应的video_id不同, 于是需要找到获取video_id的请求.
https://www.douyin.com/aweme/v1/play/?video_id=xxx
通过控制台将设备改成移动端设备, 点击分享的链接https://v.douyin.com/Y5SpHKD/, 这时有一条请求进入我们的视线:
https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=7097830584419962125
在这里插入图片描述
该请求的响应有我们需要的video_id
该请求有一个参数item_ids, 此参数正是点击分享链接后重定向链接的一部分
在重定向链接中找到item_ids
因此我们只需要解析该链接就可以拿到item_ids

至此, 就得到了下载无水印视频的全过程。

  1. 根据https://v.douyin.com/Y5SpHKD/的重定向地址https://www.iesdouyin.com/share/video/7097830584419962125获取item_ids=7097830584419962125
  2. 根据https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=7097830584419962125的响应拿到vid
  3. 根据www.douyin.com/aweme/v1/play/?video_id=v0200fg10000ca08sgbc77udtm7m06p0下载视频

实现

model层

通过传入的分享链接, 获取无水印视频链接

public class DouyinDownloadModel {
    private final OkHttpClient mOkHttpClient = new OkHttpClient();

    public void download(InputBean inputBean, DownloadListener downloadListener) {
        Request.Builder builder = new Request.Builder().get().url(inputBean.getShareUrl());
        requestInit(builder);
        Request request = builder.build();
        mOkHttpClient.newBuilder()
                .followRedirects(false).build().newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                downloadListener.fail();
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) {
                if (response.code() == 302) {
                    String location = response.header("location");
                    if (location != null) {
                        System.out.println(location);
                        String itemIds = parseItemIds(location);
                        if (!TextUtils.isEmpty(itemIds)) {
                            getVidByItemIds(itemIds, new GetVidRequestListener() {
                                @Override
                                public void success(JsonRootBean bean) {
                                    Item_list item_list = bean.getItem_list().get(0);
                                    String vid = item_list.getVideo().getVid();
                                    String url = "https://www.douyin.com/aweme/v1/play/?video_id="
                                            + vid;
                                    DownLoadResult downLoadResult = new DownLoadResult();
                                    downLoadResult.setVideoUrl(url)
                                            .setNickName(item_list.getAuthor().getNickname())
                                            .setVideoDesc(item_list.getDesc());
                                    downloadListener.success(downLoadResult);
                                }

                                @Override
                                public void fail() {
                                    downloadListener.fail();
                                }
                            });
                        } else {
                            downloadListener.fail();
                        }
                    }
                }
            }
        });
    }

    public void getVidByItemIds(String itemIds, GetVidRequestListener getVidRequestListener) {
        String url = "https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=" + itemIds;
        System.out.println(url);
        Request.Builder builder = new Request.Builder().get().url(url);
        requestInit(builder);
        Request request = builder.build();
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                getVidRequestListener.fail();
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response)
                    throws IOException {
                if (response.code() == 200) {
                    response.body();
                    String jsonString = response.body().string();
                    Gson gson = new Gson();
                    System.out.println(jsonString);
                    JsonRootBean jsonRootBean = gson.fromJson(jsonString, JsonRootBean.class);
                    System.out.println(jsonRootBean.getItem_list().get(0).getVideo().getVid());
                    getVidRequestListener.success(jsonRootBean);
                }
            }
        });
    }

    public interface DownloadListener {
        void success(DownLoadResult downLoadResult);

        void fail();

        void onProgress(int progress);
    }

    interface GetVidRequestListener {

        void success(JsonRootBean bean);

        void fail();
    }

    public void requestInit(Request.Builder builder) {
        builder.addHeader("user-agent",
                "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 "
                        + "(KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1 Edg/101.0.4951.41");
    }

    public String parseItemIds(String text) {
        String regex = "\\d{19}";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(text);
        if (m.find()) {
            return m.group();
        }
        return null;
    }
}

Presenter层

View层

源代码 + Apk

参考

  1. 重定向的链接在谷歌F12中看不到
  2. 认识Android中的MVP设计模式
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-06-25 18:16:18  更:2022-06-25 18:17:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 2:30:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码