利于puppeteer获取网络资源的直链

发布时间 2023-07-17 09:55:35作者: 丁少华

背景

比如我想使用curl 或者 页面按钮点击直接下载个网盘资源,那就会出现问题。
因为目前各大网盘给的分享链接都是一个页面,而且大部分还都做了防盗机制,你无法简单的获取真实下载连接!
但是我们可以利用puppeteer来做到!

蓝奏云

lanzou-helper.js

import { sleep } from './index.js';
import puppeteer from "puppeteer";


/**
 * 获取蓝奏云真实下载地址
 * @param lanzouShareUrl 蓝奏云分享页地址
 * @param fileName 蓝奏云分享的文件名(如果不传入filename 意味着是下载分享的是单个文件, 而不是文件夹)
 * @returns downUrl 真实下载地址
 */
export const getLanzouDownUrl = async (lanzouShareUrl, fileName) => {
  // 启动一个浏览器
  const browser = await puppeteer.launch({
    headless: 'new',
    args: ['--no-sandbox'],
    // executablePath: "C:/Users/boringsoft/AppData/Local/Google/Chrome/Application/chrome.exe",
  });
  // 在浏览器上下文中,创建一个Page对象
  const page = await browser.newPage();


  let getDownPageUrl = lanzouShareUrl;
  if (fileName) {
    // Page对象加载一个网址
    await page.goto(lanzouShareUrl);
    getDownPageUrl = await page.evaluate(({ fileName }) => {
      const list = document.querySelectorAll(".minPx-top");

      let downPageUrl = "";
      for (const it of list) {
        const filename = it.querySelector(".filename").innerHTML;
        if (filename.indexOf(fileName) > -1) {
          downPageUrl = it.href;
          break;
        }
      }
      return downPageUrl;
    }, { fileName });
  }

  // Page对象加载一个网址
  await page.goto(getDownPageUrl);
  const iframeUrl = await page.evaluate(() => {
    const ifm = document.querySelector(".n_downlink");
    return ifm.src
  });
  await page.goto(iframeUrl);
  await sleep(500);
  const downUrl = await page.evaluate(() => {
    const aDiv = document.querySelector(".load");
    const aButton = aDiv.querySelector('a');
    return aButton.href;
  });
  // 关闭浏览器释放Page
  await browser.close();
  return downUrl;
};

main.js

const commonRouter = async (ctx, next) => {
   
}


// 下载 tvbox(测试 文件夹分享的资源下载)
router.get('/tvbox', async (ctx, next) => {
    let fileName = '影视仓';
    if (ctx.params?.type === 'mobile') {
        fileName = '影视仓手机版';
    }
    const lanzouShareUrl = 'https://qiqi2020.lanzouw.com/b09svqv1c';
    const url = await getLanzouDownUrl(lanzouShareUrl, fileName);

    // 代理中间件方式 下载蓝奏云连接
    ctx.respond = false // 绕过koa内置对象response ,写入原始res对象,而不是koa处理过的response
    await koa2Connect(
        HttpProxyMiddleware.createProxyMiddleware({
            target: url,
            changeOrigin: true,
            onProxyReq: (proxyReq, req, res) => {
                proxyReq.setHeader('accept-language', 'zh-CN,zh;q=0.9');
            }
        })
    )(ctx, next);
    await next();
})

// 下载adwars app(测试单个文件分享 下载)
router.get('/adwars', async (ctx, next) => {
    const lanzouShareUrl = 'https://lanzoux.com/adWars';
    const url = await getLanzouDownUrl(lanzouShareUrl);
    await ctx.redirect(url);
})

gitHub Realse

github-helper.js

import axios from 'axios'

/**
 * 获取github release真实下载地址
 * @param lastVersionInfoUrl github release的信息
 * @returns downUrl 真实下载地址
 */
export const getGitHubDownUrl  = async (lastVersionInfoUrl) => {
    const lastVersionInfo = await axios.get(lastVersionInfoUrl);
    const {assets, tag_name} = lastVersionInfo.data;

    let downUrl = '';
    for(const item of assets) {
        // if(item.name === `cfa-${tag_name.substr(1,tag_name.length-1)}-foss-arm64-v8a-release.apk`){
        //     downUrl = item.browser_download_url;
        // }
        if(item.name.indexOf(tag_name)){  // 获取最新的资源
            downUrl = item.browser_download_url;
        }
    }
    return downUrl;
}
// 下载 lx-music app
router.get('/lxmusic', async (ctx, next) => {
    const lastVersionInfoUrl = 'https://api.github.com/repos/lyswhut/lx-music-mobile/releases/latest';
    const gitHubDownUrl = await getGitHubDownUrl(lastVersionInfoUrl);
    await ctx.redirect(gitHubDownUrl);
})