下载抖音短视频
当前为
// ==UserScript==
// @name 抖音短视频下载
// @namespace http://tampermonkey.net/
// @version 0.3.8
// @description 下载抖音短视频
// @author 抖音兔不迟到
// @license MIT License
// @run-at document-start
// @grant GM_download
// @include *://*douyin.com
// @include *://*.douyin.com/*
// @require https://gf.qytechs.cn/scripts/439696-mono-js/code/monojs.js?version=1017359
// ==/UserScript==
var _META_URL_ = "https://www.douyin.com/web/api/v2/aweme/iteminfo/?item_ids=";
var itemCache = {}
var parseItem = (item) => {
var key = item.video?.origin_cover?.uri;
if (!key) return;
itemCache[key] = item;
itemCache[key].video_id = itemCache[key].aweme_id;
itemCache[key].title = itemCache[key].desc;
itemCache[key].cover = itemCache[key].video?.origin_cover?.url_list[0];
itemCache[key].url = itemCache[key].video?.play_addr?.url_list[0];
}
var origOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url, ...rest) {
this.addEventListener('load', function() {
if (url.includes("general/search/single")) {
var json = JSON.parse(this.responseText);
if (!json?.data?.length) return;
for (var mixItem of json.data) {
if (mixItem.aweme_mix_info?.mix_items?.length) {
for (var item of mixItem.aweme_mix_info?.mix_items) {
parseItem(item);
}
} else if (mixItem.aweme_info) {
parseItem(mixItem.aweme_info);
}
}
// console.log({itemCache});
}
});
origOpen.call(this, method, url, ...rest);
};
(function () {
var mono = window['mono-descargar'];
var useDefaultErr = mono.FAIL_TO_DEFAULT;
var $ = mono.jQuery;
var md5 = mono.md5;
var filename = (title) => {
const name = title.replace(' ', '').replace(/[/\\?%*:|"<>]/g, '-');
return `${name}.mp4`;
}
var updateItems = async (items) => {
if (items.length <= 0) return;
var resp = await fetch(_META_URL_ + items.map(im => im.meta.video_id).join(','))
var json = await resp.json()
metas = {}
for (var i in json.item_list) {
metas[json.item_list[i].aweme_id] = json.item_list[i]
}
for (var i in items) {
meta = metas[items[i].meta.video_id]
if (!meta) continue;
meta.title = meta.desc;
meta.cover = meta.video.cover.url_list[0];
meta.name = filename(meta.title);
items[i].url = meta.video.play_addr.url_list[0].replace("playwm", "play");
items[i].meta = Object.assign(meta, items[i].meta);
}
}
var getItemByDetailUrl = (detail_url) => {
var url = new URL(detail_url);
var video_id = url.pathname.slice("/video/".length);
var id = `dy-${md5(video_id)}`;
if ($(`[mono-dsg-id=${id}]`).length > 0) return null;
var meta = { video_id }
var position = { x: 0, y: 0 };
return { id, url:"", meta, position };
}
var getItemsByATag = async () => {
var items = [];
var a = $(`a[href*="douyin.com/video/"]`);
if (a.length <= 0) return;
for (var i = 0; i < a.length; i++) {
var item = getItemByDetailUrl(a[i].href);
if (!item) continue;
item.container = a[i];
items.push(item);
// 每次返回N个,分多次
if (items.length >= 10) break;
}
if (items.length > 0) {
await updateItems(items);
}
return items;
}
var getItemsBySearchRes = async () => {
var items = [];
var containers = $(`.playerContainer`);
if (containers.length <= 0) return;
for (var i = 0; i < containers.length; i++) {
let key;
var container = containers[i];
var $ele = $(container);
try {
var img = $ele.find('.imgBackground img')[0];
var url = new URL(img.src.startsWith('//') ? 'https:' + img.src : img.src);
if (url && url.pathname.includes('~')) {
key = url.pathname.substring(1, url.pathname.indexOf('~'));
}
} catch (e) {
console.log('err', e);
continue;
}
if (!key || !itemCache[key]) continue;
var meta = itemCache[key];
var id = `dy-${md5(meta.video_id)}`;
var url = meta.url;
meta.name = filename(meta.title);
var position = { x: 0, y: 0 };
var item = { id, url, container, meta, position }
items.push(item);
// 每次返回N个,分多次
if (items.length >= 10) break;
}
return items;
}
var pageParsers = {
detail: async () => {
var item = getItemByDetailUrl(window.location.href);
if (!item) return [];
video = $('video')
if (video.length <= 0) return [];
item.container = video[0].parentNode;
await updateItems([item]);
return [item];
},
user: async () => {
return getItemsByATag()
},
list: async () => {
let items = await getItemsByATag();
return items || getItemsBySearchRes()
}
}
var getPageParser = () => {
var url = new URL(window.location.href);
var path = url.pathname.split('/')[1];
if (path === "video") {
return pageParsers.detail;
} else if (path === "user") {
return pageParsers.user;
} else if (["discover", "search", "channel", "hot"].includes(path)) {
return pageParsers.list;
} else {
throw useDefaultErr;
}
}
var parser = async function () {
var pr = getPageParser()
if (!pr) return []
return pr()
}
if (mono?.init) mono.init({
parser,
interval: 100,
});
})()
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址