利于puppeteer获取网络资源的直链
背景
比如我想使用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);
})
最后
因为puppeteer是基于无头浏览器实现的,每次请求他都要打开一次浏览器,所以比较吃内存。
如果你想要的资源固定,而且你也不要求实时,为了体验和性能,你可以定时爬取资源 下载到你自己的服务器即可!