将以下步骤作为工作清单,并根据项目的证据、范围和限制进行调整。
实用步骤
- 打开要检查的页面和浏览器开发者控制台。检查移动端溢出时,先使用响应式模式。
- 审查代码,将完整代码片段粘贴到控制台并按 Enter。脚本读取当前页面;只有 sitemap 元数据工具和同源检查工具会在有限范围内发出请求。
- 查看控制台输出或下载的 CSV/JSON。浏览器策略、身份验证和服务器不支持的方法可能导致部分检查无法得出结论。
(async () => {
const MAX_VARIANTS = 30;
const deadline = Date.now() + 30000;
const currentCanonical = new URL(document.querySelector('link[rel="canonical"]')?.href || location.href, location.href).href;
const tags = [...document.querySelectorAll('link[rel="alternate"][hreflang][href]')].slice(0, MAX_VARIANTS);
const rows = [];
for (const tag of tags) {
const target = new URL(tag.href, location.href);
const item = { language: tag.hreflang, url: target.href, sameOrigin: target.origin === location.origin, reciprocal: 'not checked' };
if (item.sameOrigin) {
if (Date.now() >= deadline) { item.reciprocal = 'skipped: 30-second runtime limit'; rows.push(item); continue; }
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), Math.min(5000, deadline - Date.now()));
try {
const response = await fetch(target.href, { credentials: 'omit', redirect: 'follow', signal: controller.signal });
if (!response.ok || new URL(response.url).origin !== location.origin) throw new Error('HTTP ' + response.status + ' or cross-origin redirect');
const doc = new DOMParser().parseFromString(await response.text(), 'text/html');
const reciprocal = [...doc.querySelectorAll('link[rel="alternate"][hreflang][href]')].some((link) => {
try { return new URL(link.href, target.href).href === currentCanonical; } catch { return false; }
});
item.reciprocal = reciprocal ? 'yes' : 'missing';
} catch (error) { item.reciprocal = error.name === 'AbortError' ? 'timeout' : 'could not check'; }
finally { clearTimeout(timer); }
}
rows.push(item);
}
console.table(rows);
console.info('Current canonical:', currentCanonical, '· hreflang variants found:', tags.length);
if (Date.now() >= deadline) console.warn('The 30-second runtime limit was reached; remaining links were not checked.');
if (tags.length >= MAX_VARIANTS) console.warn('Only the first ' + MAX_VARIANTS + ' language variants were checked.');
if (!tags.length) console.warn('No link rel=\"alternate\" hreflang entries were found.');
console.info('Cross-origin and inaccessible pages are not fetched. A “missing” reciprocal link may also result from a canonical URL variant or redirect; review it manually.');
})();运行前请先审查代码。脚本读取当前页面;只有 sitemap 和链接审查工具会在有限范围内发出同源请求。请求不携带 cookies;脚本不会更改网站内容。