const express = require('express'); const cors = require('cors'); const axios = require('axios'); const cheerio = require('cheerio'); const app = express(); app.use(cors()); app.use(express.json()); // 镜像代理核心 app.get('/mirror', async (req, res) => { const targetUrl = req.query.url; if (!targetUrl) { return res.status(400).send('缺少 url 参数'); } try { // 获取目标页面 const response = await axios.get(targetUrl, { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8', }, timeout: 30000, maxRedirects: 5, }); let html = response.data; const baseUrl = new URL(targetUrl).origin; // 使用 cheerio 解析和重写 const $ = cheerio.load(html); // 重写所有资源路径为绝对路径 $('link[href]').each((i, el) => { const href = $(el).attr('href'); if (href && !href.startsWith('http') && !href.startsWith('//') && !href.startsWith('data:')) { $(el).attr('href', new URL(href, baseUrl).href); } }); $('script[src]').each((i, el) => { const src = $(el).attr('src'); if (src && !src.startsWith('http') && !src.startsWith('//') && !src.startsWith('data:')) { $(el).attr('src', new URL(src, baseUrl).href); } }); $('img[src]').each((i, el) => { const src = $(el).attr('src'); if (src && !src.startsWith('http') && !src.startsWith('//') && !src.startsWith('data:')) { $(el).attr('src', new URL(src, baseUrl).href); } }); $('a[href]').each((i, el) => { const href = $(el).attr('href'); if (href && !href.startsWith('http') && !href.startsWith('//') && !href.startsWith('#') && !href.startsWith('javascript:')) { $(el).attr('href', new URL(href, baseUrl).href); } }); // 处理 CSS 中的 url() $('style').each((i, el) => { let css = $(el).html(); if (css) { css = css.replace(/url\(["']?(?!https?:\/\/|data:)([^"')]+?)["']?\)/g, (match, path) => { try { const absolute = new URL(path.trim(), baseUrl).href; return `url("${absolute}")`; } catch { return match; } }); $(el).html(css); } }); // 添加 base 标签 $('head').prepend(``); // 移除 CSP $('meta[http-equiv="Content-Security-Policy"]').remove(); $('meta[content*="content-security-policy"]').remove(); res.set('Content-Type', 'text/html; charset=utf-8'); res.send($.html()); } catch (error) { console.error('镜像失败:', error.message); res.status(500).send(` 镜像失败

❌ 加载失败

无法镜像 ${targetUrl}

${error.message}

← 返回首页

`); } }); // 提供前端页面 app.get('/', (req, res) => { res.send(` 网站镜像工具
⚡ 就绪

🌐 输入网址开始镜像

输入任意网站地址,点击「加载」即可在镜像中查看完整页面

⚠️ 部分站点可能因反爬机制无法加载

`); }); const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log('🪞 镜像服务运行在 http://localhost:' + PORT); });