Files
blog/scripts/lighthouse/summarize.py
T
wait4xandGLM-5.3 f8add5ad15 feat(deploy): 裸 clone 构建改造与 en/archives 补页(T1/T4)
- build.sh:构建源改 ~/docker_apps/blog/build-repo(fetch+reset 硬跟
  origin/main,匿名 fetch)——线上=远端 main 确定性闭环,Sveltia 保存
  即自动上线生效;stamp 记录构建 commit;node_modules 留仓内做增量
  (loader 逻辑变更时须清 node_modules/.astro——EXIF 教训已注)
- en/archives/index.astro 补缺(此前 404):PostList locale 复用 +
  译题映射;三级目录 import 深度坑再犯一次(已修)

验证: bash infra/deploy/build.sh → staging 29 html @0e792a7(裸 clone
      实测);build 本地 28+1 页;E2E 30/30 PASS

Spec: 2026-10-25_add-blog-5c

Co-authored-by: GLM-5.3
2026-10-25 19:23:40 +08:00

78 lines
3.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""汇总 lighthouse 五页报告:分数表 + 未达标项的文件级嫌疑清单。
输入:目录内 page-*.json(lighthouse 全量输出)
输出:/tmp/e2e-shots/lighthouse-report.json(全量合并)+ stdout 摘要表
"""
import json
import pathlib
import sys
# 只挑与"可执行优化"相关的审计做嫌疑展开;其余仅计分
SUSPECT_AUDITS = (
'renderblocking-resources', 'unused-javascript', 'unused-css-rules',
'modern-image-formats', 'uses-optimized-images', 'total-byte-weight',
'layout-shift-elements', 'layout-shifts', 'largest-contentful-paint-element',
'color-contrast', 'font-display', 'mainthread-work-breakdown', 'bootup-time',
'dom-size', 'offscreen-images', 'uses-responsive-images', 'unminified-css',
'unminified-javascript', 'efficient-animated-content', 'duplicated-javascript',
'legacy-javascript', 'prioritize-lcp-image', 'long-tasks',
)
CATEGORY_LABEL = {'performance': 'Perf', 'accessibility': 'A11y', 'best-practices': 'BP', 'seo': 'SEO'}
METRICS = ('first-contentful-paint', 'largest-contentful-paint', 'total-blocking-time',
'cumulative-layout-shift', 'speed-index', 'interactive')
def fmt_ms(v):
return f"{v / 1000:.1f}s" if isinstance(v, (int, float)) else str(v)
def main(outdir: pathlib.Path):
pages = {}
rows = []
for f in sorted(outdir.glob('page-*.json')):
data = json.loads(f.read_text())
url = data.get('finalDisplayedUrl') or data.get('finalUrl') or f.stem
path = '/' + url.split('/', 3)[-1].replace('127.0.0.1:18743', '') if url.count('/') >= 3 else url
cats = {k: round(v['score'] * 100) for k, v in data['categories'].items() if v.get('score') is not None}
metrics = {m: fmt_ms(data['audits'][m].get('numericValue')) for m in METRICS if m in data['audits']}
suspects = {}
for cid, cat in data['categories'].items():
if cats.get(cid, 100) >= 100:
continue
for ref in cat.get('auditRefs', []):
aid = ref['id']
a = data['audits'].get(aid, {})
if a.get('score') is not None and a['score'] < 0.9 and aid in SUSPECT_AUDITS:
items = (a.get('details', {}) or {}).get('items', [])
hint = []
for it in items[:4]:
for key in ('url', 'node.selector', 'node.path', 'source.url'):
v = it
for seg in key.split('.'):
v = v.get(seg) if isinstance(v, dict) else None
if v:
hint.append(str(v).split('?')[0][:110])
break
else:
hint.append(str(it)[:90])
if hint:
suspects[aid] = {'score': a['score'], 'items': hint}
pages[path or f.stem] = {'scores': cats, 'metrics': metrics, 'suspects': suspects}
rows.append((path, cats))
labels = [CATEGORY_LABEL[c] for c in ('performance', 'accessibility', 'best-practices', 'seo')]
print(f"{'页面':<28}" + ''.join(f"{l:>6}" for l in labels))
for path, cats in rows:
cells = ''.join(f"{str(cats.get(c, "-"))[:3]:>6}" for c in ('performance', 'accessibility', 'best-practices', 'seo'))
mark = ''.join(' ✗' if cats.get(c, 100) < 90 else ' ✓' for c in ('performance', 'accessibility', 'best-practices', 'seo'))
print(f"{path:<28}{cells} {mark}")
dest = pathlib.Path('/tmp/e2e-shots/lighthouse-report.json')
dest.write_text(json.dumps(pages, ensure_ascii=False, indent=1))
print(f"\n全量合并报告: {dest}({dest.stat().st_size} B)")
if __name__ == '__main__':
main(pathlib.Path(sys.argv[1]))