Spaces:
Runtime error
Runtime error
const express = require('express'); | |
const puppeteer = require('puppeteer'); | |
const app = express(); | |
const port = 7860; | |
const colorCodes = { | |
reset: "\x1b[0m", | |
green: "\x1b[32m" | |
}; | |
let requestCounter = 0; | |
let browserInstance; | |
app.use(express.json()); | |
app.get('/api', async (req, res) => { | |
const { url, time } = req.query; | |
const timestamp = new Date().toLocaleString(); | |
const start = Date.now(); | |
const requestId = ++requestCounter; | |
let delayTime = parseInt(time) || 0; | |
let delayDuration = 0; | |
try { | |
if (!isNaN(delayTime) && delayTime >= 0 && delayTime <= 60) { | |
const formattedURL = formatURL(url); | |
if (!formattedURL) { | |
console.log(`[${colorizeTimestamp(timestamp)}] [${colorCodes.green}${requestId}${colorCodes.reset}] URL格式错误 ${colorizeURLAndMS(url)}`); | |
return res.status(400).send(`请求错误:URL格式错误`); | |
} | |
console.log(`[${colorizeTimestamp(timestamp)}] [${colorCodes.green}${requestId}${colorCodes.reset}] 请求截图 ${delayTime} ${colorizeURLAndMS(formattedURL)}`); | |
const browser = await getBrowserInstance(); | |
const page = await browser.newPage(); | |
await page.goto(formattedURL, { timeout: 60000 }); | |
//await page.setViewport({ width: 1920, height: 1080 }); | |
if (delayTime > 0) { | |
await new Promise(resolve => setTimeout(resolve, delayTime * 1000)); | |
delayDuration = Date.now() - start - delayTime * 1000; | |
} | |
const screenshot = await page.screenshot({ fullPage: true }); | |
res.set('Content-Type', 'image/png'); | |
res.send(screenshot); | |
// 关闭页面 | |
await page.close(); | |
} else { | |
console.log(`[${colorizeTimestamp(timestamp)}] [${colorCodes.green}${requestId}${colorCodes.reset}] 延时错误 ${colorizeURLAndMS(url)}`); | |
res.status(400).send(`请求错误:延时时间不正确!仅支持0到60秒之间`); | |
} | |
const end = Date.now(); | |
const totalTime = end - start - delayDuration; | |
console.log(`[${colorizeTimestamp(timestamp)}] [${colorCodes.green}${requestId}${colorCodes.reset}] 处理完成 ${colorCodes.green}${totalTime}ms${colorCodes.reset}`); | |
// 记录完整请求信息 | |
console.log(`[${colorizeTimestamp(timestamp)}] [${colorCodes.green}${requestId}${colorCodes.reset}] ${JSON.stringify(req.query)}`); | |
} catch (error) { | |
console.error(`[${colorizeTimestamp(timestamp)}] [${colorCodes.green}${requestId}${colorCodes.reset}] 处理错误:${error}`); | |
res.status(500).send(`处理错误:${error}`); | |
// 记录完整请求信息 | |
console.log(`[${colorizeTimestamp(timestamp)}] [${colorCodes.green}${requestId}${colorCodes.reset}] ${JSON.stringify(req.query)}`); | |
} | |
}); | |
app.listen(port, () => { | |
console.log(`服务已运行 监听端口${port}`); | |
}); | |
async function getBrowserInstance() { | |
if (!browserInstance) { | |
browserInstance = await puppeteer.launch({ | |
headless: "new", | |
args: [ | |
'--disable-gpu', | |
'--disable-dev-shm-usage', | |
'--disable-setuid-sandbox', | |
'--no-first-run', | |
'--no-sandbox', | |
'--no-zygote', | |
'--single-process', | |
'--lang=zh-CN,zh' | |
], | |
}); | |
} | |
const browser = await browserInstance; | |
await browser.pages().then(async (pages) => { | |
if (pages.length > 0) { | |
await pages[0].evaluateOnNewDocument(() => { | |
Object.defineProperty(navigator, "language", { | |
get: function() { | |
return "zh-CN"; | |
} | |
}); | |
Object.defineProperty(navigator, "languages", { | |
get: function() { | |
return ["zh-CN", "zh"]; | |
} | |
}); | |
}); | |
} | |
}); | |
return browserInstance; | |
} | |
function formatURL(url) { | |
const regex = /^(?:https?:\/\/)?([\w.-]+\.\w+(\.\w+)?)(.*)$/; | |
const match = url.match(regex); | |
if (match) { | |
const domain = match[1]; | |
const path = match[3] || '/'; | |
return `https://${domain}${path}`; | |
} | |
return null; | |
} | |
function colorizeTimestamp(text) { | |
const regex = /\[(.*?)\]/g; | |
return text.replace(regex, (match, p1) => { | |
return `[${colorCodes.green}${p1}${colorCodes.reset}]`; | |
}); | |
} | |
function colorizeURLAndMS(text) { | |
const regex = /(?:https?:\/\/[^\s]+)/g; | |
const msRegex = /\b\d+ms\b/g; | |
return text | |
.replace(regex, (match) => { | |
return colorCodes.green + match + colorCodes.reset; | |
}) | |
.replace(msRegex, (match) => { | |
return colorCodes.green + match + colorCodes.reset; | |
}); | |
} |