您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
视频下载 bilibili acfun youtube 西瓜 快手 抖音
当前为
// ==UserScript== // @name you-get // @description 视频下载 bilibili acfun youtube 西瓜 快手 抖音 // @namespace http://tampermonkey.net/ // @version 0.0.1 // @description try to take over the world! // @author You // @match https://www.ixigua.com/* // @match https://www.bilibili.com/video/* // @match https://www.douyin.com/* // @match https://www.kuaishou.com/* // @match https://www.acfun.cn/v/* // @match https://www.youtube.com/watch/* // @license MIT // @grant none // ==/UserScript== (function () { "use strict"; // Your code here... const CONFIG = "tampermonkey_config"; const download = async (blob, fileName) => { let link = window.URL.createObjectURL(blob); const a = document.createElement("a"); a.download = `${fileName}`; a.href = link; document.body.appendChild(a); a.click(); document.body.removeChild(a); window.URL.revokeObjectURL(link); }; const getConfig = (key) => { let item = localStorage.getItem(key); if (item) { try { item = JSON.parse(item); } catch (error) { item = null; console.log(error); } } return item; }; const fetchFile = async (url) => { const res = await fetch(url); const reader = res.body.getReader(); const contentLength = +res.headers.get("Content-Length"); if (!contentLength) { const data = await res.arrayBuffer(); return new Uint8Array(data); } let receivedLength = 0; let chunks = []; while (true) { const { done, value } = await reader.read(); if (done) { break; } chunks.push(value); receivedLength += value.length; console.log( `fileSize: ${contentLength} %c downloaded ${receivedLength}`, "background: #222; color: #bada55" ); } // const config = getConfig(CONFIG); // if (config?.merge === false) { return new Blob(chunks); // } // let chunksAll = new Uint8Array(receivedLength); // let position = 0; // for (let chunk of chunks) { // chunksAll.set(chunk, position); // position += chunk.length; // } // return chunksAll; }; const getUrlsByM3u8 = async (url) => { const res = await fetch(url); const data = await res.text(); return data.split("\n").filter((i) => !i.startsWith("#")); }; const getXiGuaVideoInfo = async () => { const res = await fetch(window.location.href); const str = await res.text(); const data = JSON.parse( str .match(/window?._SSR_HYDRATED_DATA=([\d\D]+?)<\/script>/)[1] .replaceAll("undefined", "null") ); const videoList = Object.values( data?.anyVideo?.gidInformation?.packerData?.video?.videoResource?.normal ?.video_list ?? {} ).sort((a, b) => b?.vheight - a?.vheight); const video = videoList?.[0]; return [ { url: atob(video.main_url, "base64"), fileName: `download.${video.vtype || "mp4"}`, }, ]; }; const getBilibiliVideoInfo = async () => { const res = await fetch(window.location.href); const str = await res.text(); const data = JSON.parse( str.match(/window.__playinfo__=([\d\D]+?)<\/script>/)[1] ); const dash = data.data.dash; const video = dash.video.sort((a, b) => b?.width - a?.width)?.[0]; const audio = dash.audio[0]; return [ { url: video.baseUrl, fileName: `download.${video?.mimeType?.split("/")?.[1] || "mp4"}`, }, { url: audio.baseUrl, fileName: `download.${video?.mimeType?.split("/")?.[1] || "mp4"}`, }, ]; }; const getDouyinVideoInfo = () => { const urls = [...document.querySelectorAll("video source")].map( (i) => i.src ); return [ { url: urls[0], fileName: `download.mp4`, }, ]; }; const getKuaishouVideoInfo = () => { const urls = [...document.querySelectorAll("video")].map((i) => i.src); return [ { url: urls[0], fileName: `download.mp4`, }, ]; }; const getYoutubeVideoInfo = async () => { const res = await fetch(window.location.href); const str = await res.text(); var parser = new DOMParser(); var doc = parser.parseFromString(str, "text/html"); const data = JSON.parse( doc.body.innerHTML.match(/("formats":)([\d\D]+?}]+?)/)[2] ); const video = data.sort((a, b) => b?.width - a?.width)?.[0]; return [ { url: video.url, fileName: `download.mp4`, }, ]; }; const getAcfunVideoInfo = async () => { const res = await fetch(window.location.href); const str = await res.text(); const m3u8FileUrl = JSON.parse(window.pageInfo.currentVideoInfo.ksPlayJson) .adaptationSet[0].representation[0].url; const baseUrl = m3u8FileUrl.substring(0, m3u8FileUrl.indexOf("acfun_video")) + "acfun_video/"; const urls = (await getUrlsByM3u8(m3u8FileUrl)).map( (i) => `${baseUrl}${i}` ); return urls.map((url) => ({ url, fileName: `download.mp4`, merge: true, })); }; const platform = { ixigua: getXiGuaVideoInfo, bilibili: getBilibiliVideoInfo, douyin: getDouyinVideoInfo, kuaishou: getKuaishouVideoInfo, youtube: getYoutubeVideoInfo, acfun: getAcfunVideoInfo, }; const youget = async function () { const handler = Object.entries(platform).find(([key, fn]) => window.location.host.toLocaleLowerCase().includes(key) )?.[1]; if (handler) { const urls = await handler(); const files = []; while (urls?.length) { const i = urls.shift(); if (i.merge) { const file = await fetchFile(i.url); files.push(file); if (!urls.length) { download(new Blob(files), i.fileName); } } else { const file = await fetchFile(i.url); await download(file, i.fileName); } } } }; youget.toString = () => { youget(); return 1; }; window.you = 1; window.get = youget; window.youget = youget; })();