feat(sitemap): 支持本地 XML 回退(官网 sitemap 受 WAF 保护)+ 记录 5.1-5.3 数据面结果

This commit is contained in:
wangliang
2026-10-23 11:13:24 +08:00
parent 696916ad50
commit 3b8997b565
3 changed files with 88 additions and 4 deletions
+25 -3
View File
@@ -33,19 +33,41 @@ function tokensFor(pathPart) {
.toLowerCase();
}
async function fetchSitemap(url) {
function parseLocs(xml) {
return [...xml.matchAll(/<loc>([^<]+)<\/loc>/g)].map((m) => m[1].trim()).filter(Boolean);
}
// 官网 sitemap 受阿里云 WAF JS 挑战保护,直接 fetch 会返回挑战 HTML(0 个 <loc>)。
// 支持从本地缓存的 XML 读取:SITEMAP_XML_<SITE> 环境变量,或 var/sitemap-<site>.xml。
function localSitemapFile(name) {
const fromEnv = process.env['SITEMAP_XML_' + name.toUpperCase()];
if (fromEnv && fs.existsSync(fromEnv)) return fromEnv;
const p = path.join(ROOT, 'var', `sitemap-${name}.xml`);
return fs.existsSync(p) ? p : null;
}
async function fetchSitemap(name, url) {
const local = localSitemapFile(name);
if (local) {
console.log(`[site-map] ${name}: 使用本地 sitemap ${local}`);
return parseLocs(await fs.promises.readFile(local, 'utf8'));
}
const res = await fetch(url, {
headers: { 'User-Agent': 'Mozilla/5.0 (compatible; YehwangSiteMapBot/1.0)' },
signal: AbortSignal.timeout(90000),
});
if (!res.ok) throw new Error(`sitemap HTTP ${res.status}: ${url}`);
const xml = await res.text();
return [...xml.matchAll(/<loc>([^<]+)<\/loc>/g)].map((m) => m[1].trim()).filter(Boolean);
const locs = parseLocs(xml);
if (!locs.length) {
throw new Error(`sitemap 返回 0 个 <loc>(可能被 WAF 挑战):先下载 XML 到 var/sitemap-${name}.xml,或设置 SITEMAP_XML_${name.toUpperCase()}`);
}
return locs;
}
async function buildSite(client, name) {
const cfg = SITES[name];
const urls = await fetchSitemap(cfg.sitemap);
const urls = await fetchSitemap(name, cfg.sitemap);
const rows = [];
const seenPaths = new Set();
for (const url of urls) {