油猴脚本注入js获取DY作品数据

发布时间:2024年01月19日

油猴脚本的执行时机: 元素还未生成
https://bbs.tampermonkey.net.cn/thread-3843-1-1.html

而在控制台执行时, 通常元素已经生成

逻辑就是在网页每次发送请求时, 拦截它请求的响应数据作操作; 所以当用户作品很多时, 也需要一直滚动到全部作品请求加载完成, 触发下载
(当然这都可以改 什么时候触发下载)

// ==UserScript==
// @name         抖音个人主页作品抓取注入
// @namespace    http://tampermonkey.net/
// @version      2024-01-18
// @description  try to take over the world!
// @author       You
// @match        https://www.douyin.com/user/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=douyin.com
// @grant        none
// ==/UserScript==

(function() {
'use strict';

// 通过 hook XMLHttpRequest 的 send 方法,捕获返回的数据
let aweme_post_list = [];
let page = 0;

// 1. 保存原始的 send 方法
const nativeXMLHttpRequestSend = XMLHttpRequest.prototype.send;

// 2. 重写 send 方法
XMLHttpRequest.prototype.send = function (body) {
    // https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/readystatechange_event

    // XMLHttpRequest.readyState 属性返回一个 XMLHttpRequest 代理当前所处的状态, 4表示下载操作已完成。
    // https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/readyState

    // console.log('body', body);
    this.addEventListener('readystatechange', function () {
        console.debug({
            'readyState': this.readyState,
            'status': this.status,
            'responseURL': this.responseURL
        });
        // 响应正常完成
        if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {

            if (this.responseURL.includes('/aweme/v1/web/aweme/post/')) {
                // 3. 解析返回数据
                let json_data = JSON.parse(this.responseText);
                console.log(`${++page}页, 本页${json_data.aweme_list.length}条作品`);

                const data = json_data.aweme_list.map(item => {
                    const { aweme_id, desc: title, create_time, video: { play_addr: { url_list: play_addr_list } } } = item;
                    const create_date = new Date(create_time * 1000);
                    const addr = 'https://www.douyin.com/video/' + aweme_id;
                    return { aweme_id, title, create_date, addr, play_addr_list };
                })
                aweme_post_list = aweme_post_list.concat(data);

                // 判断是否完成
                if (json_data.has_more === 0) {
                    console.log(`全部完成, 共${aweme_post_list.length}条作品, 开始下载...`);
                    downloadAwemePostJson(aweme_post_list, 'aweme_post_list.json');

                    // 下載視頻
                    aweme_post_list.forEach((item, index) => {
                        const title = legalizationFilename(item.title);
                        const filename = `${index + 1}-${title}.mp4`;
                        downloadAwemePostVideo(item.play_addr_list[0], filename);
                    });
                }
            }

        }

    });
    // 4. 调用原始的 send 方法
    return nativeXMLHttpRequestSend.call(this, body);
}




/**
 * 将JS对象保存为JSON文件
 * @param {object} data 需要下载的JS对象
 */
function downloadAwemePostJson(data, filename) {
    let blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
    let a = document.createElement('a');
    a.href = URL.createObjectURL(blob);
    a.download = filename;
    a.click();
}

/**
 * 下載抖音作品視頻
 * @param {*} url
 * @param {*} filename
 */
function downloadAwemePostVideo(url, filename) {
    url = url.replace('http://', 'https://');
    fetch(url)
        .then(res => res.blob())
        .then(blob => {
            console.debug(url, filename);
            const a = document.createElement("a");
            const objectUrl = URL.createObjectURL(blob);
            a.download = filename;
            a.href = objectUrl;
            a.click();
            URL.revokeObjectURL(objectUrl);
            a.remove();
        }).catch(err => {
            console.error(err);
        });
}
/**
 * 合法化文件名
 * @param {*} filename
 * @returns
 */
function legalizationFilename(filename) {
    return filename.replace(/[\\/:*?"<>|]/g, '');
}
})();

其实DY本生也重写了XHR的send方法, 也可能是框架重写的
在这里插入图片描述

视频演示:

2.89 09/20 RKW:/ w@S.yG 油猴脚本js注入批量下载DY视频 https://v.douyin.com/iLfWLdeo/ 复制此链接,打开Dou音搜索,直接观看视频!

参考:
【小红书数据采集教学(2)通过重写XMLHttpRequest的send方法来获取POST响应体数】https://www.bilibili.com/video/BV1VC4y1e7RR?vd_source=603d76094f4b03d34ae4f468d5e77227

文章来源:https://blog.csdn.net/qq_50969362/article/details/135694617
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。