you-get

视频下载 bilibili acfun youtube 西瓜 快手 抖音

目前为 2023-02-28 提交的版本。查看 最新版本

// ==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;
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址