您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
在抖音/快手主页右小角显示视频下载按钮
当前为
// ==UserScript== // @name 抖音/快手主页视频下载 // @namespace shortvideo_homepage_downloader // @version 0.0.2 // @description 在抖音/快手主页右小角显示视频下载按钮 // @author hunmer // @match https://www.douyin.com/user/* // @match https://www.kuaishou.com/profile/* // @icon https://lf1-cdn-tos.bytegoofy.com/goofy/ies/douyin_web/public/favicon.ico // @grant GM_download // @license MIT // ==/UserScript== (function() { const HOSTS = { 'www.kuaishou.com': { url: 'https://www.kuaishou.com/graphql', type: 'json', list: json => json?.data?.visionProfilePhotoList?.feeds, item: ({photo}) => { console.log(photo) return { video_url: photo.videoResource.h264.adaptationSet[0].representation[0].url, title: photo.originCaption, } } }, 'www.douyin.com': { url: 'https://www.douyin.com/aweme/v1/web/aweme/post/', type: 'network', list: json => json?.aweme_list, item: ({video, desc}) => { if(video.format == 'mp4') return { video_url: video.play_addr.url_list[0], title: desc, } } }, } const DETAIL = HOSTS[location.host] console.log({DETAIL, host: location.host}) if(!DETAIL) return var originalSend = XMLHttpRequest.prototype.send; var resources = [], fv var callback = json => { let cnt = resources.push(...DETAIL.list(json) || []) if(!cnt > 0) return if(!fv){ fv = document.createElement('div') fv.style.cssText = `position: fixed;bottom: 50px;right: 50px;border-radius: 20px;background-color: #fe2c55;color: white;z-index: 999;cursor: pointer;` fv.onclick = () => { console.log(resources) if(confirm(`确定要下载${resources.length}个视频吗?`)){ let done = 0 const next = () => { let item = resources.splice(0, 1) fv.innerHTML = `${++done}/${resources.length}` if(!item.length) return alert("下载完成") let {video_url, title} = DETAIL.item(item[0]) || {} if(!video_url) return let detail = { url: video_url, name: safeFileName(title) + '.mp4', conflictAction: 'overwrite', onload: () => endOutput(`下载完成...`), onerror: () => endOutput(`下载失败...`), ontimeout: () => endOutput(`下载失败...`), // onprogress: console.log, headers: { 'User-Agent': 'Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30', 'Referer': video_url } } console.log(detail) GM_download(detail) } const endOutput = (...args) => console.log(args) & next() endOutput('开始下载') } } document.body.append(fv) } fv.innerHTML = `下载 ${cnt} 个视频` } switch(DETAIL.type){ case 'json': var parse = JSON.parse; JSON.parse = function(raw) { let json = parse(raw) callback(json) return json; } return case 'network': XMLHttpRequest.prototype.send = function() { this.addEventListener('load', function() { if (this.responseURL.startsWith(DETAIL.url)) { callback(JSON.parse(this.responseText)) } }); originalSend.apply(this, arguments); }; const originalFetch = window.fetch; window.fetch = function() { return originalFetch.apply(this, arguments).then(response => { if (response.url.startsWith(DETAIL.url)) { response.clone().json().then(callback); } return response; }); } return } function safeFileName(str) { return str .replaceAll('(', '(') .replaceAll(')', ')') .replaceAll(':', ':') .replaceAll('*', '*') .replaceAll('?', '?') .replaceAll('"', '"') .replaceAll('<', '<') .replaceAll('>', '>') .replaceAll("|", "|") .replaceAll('\\', '\') .replaceAll('/', '/') } })();