← 返回足记

足记 · 工作手册(精简版 v2.4)

用途:每次工作前读本手册恢复状态;严格按流程执行;用户可随时拿本文档让 AI 接续工作。
为什么必须读手册(甲方诊断,2026-09-08):早期错误多、反复改,根因就两条——①规矩太松,手册写得不够清楚;②有手册长期不读,凭印象干活。为此已建成防错机制:执行前必读对应章节、新教训立即写回手册、检查经验库盖楼式防漏、发布门禁、命名规范定死。手册不是摆设:没读对应章节就不许开工。
项目名:足记(足球追踪网页)
在线地址:https://bxgj2030.top/(COS/CDN,2026-09-07起;surge.sh已废弃)
当前版本:v10.09
最后更新:2026-09-07(逐字逐句校订:统一积分榜数据源口径、场均高级数据主源改为StatMuse、球队数/部署平台/联赛数全部按现状更正)

0. 一分钟速览(恢复工作先看这里)

足记是什么:手机端看的静态足球网页。首页看赛程/积分榜/射手榜;31支俱乐部队+9支国家队专属球员页,看球员能力雷达、29项游戏能力、赛季真实数据。核心价值是"快速看懂、公正对比球员",基础数据准确是生命线。

8支重点关注球队:阿森纳、曼城、利物浦、切尔西、皇马、巴萨、巴黎圣日耳曼、拜仁慕尼黑。DESC(比赛前瞻后顾)重点写这8支球队。

扩展球队:英超其余16队+欧冠一档二档其余球队+意甲/德甲/法甲/葡超代表球队,共31支俱乐部,维护名单+OVR+六维+场均数据。

9支国家队页:巴西、英格兰、西班牙、法国、德国、意大利、葡萄牙、荷兰、阿根廷(brazil/england/spain/france/germany/italy/portugal/netherlands/argentina)。国家队大名单未正式公布前只搭框架,公布后按名单做,与俱乐部数据相互独立。

项目架构(2026-09-07现状:数据与视图分离 + 公共模块抽取):

三条铁律:

  1. 改球员数据 → 只改 data/players/对应球队.js,HTML不动
  2. 改样式/逻辑 → 改对应HTML或common.js/common.css,数据文件不动
  3. 任何部署 → 必须用 ./scripts_ops/deploy_site.sh --cos-only(硬门禁:本地 HEAD 必须=master,防旧工作区覆盖线上),自动上传+设置缓存头+制品指纹留痕(deployment_log.md),部署后浏览器抽验;新目录文件(如 data/js/i18n/zh.js)deploy 不传,需手动 put_object(ContentType=text/javascript + no-cache)

git版本控制:项目已初始化git,每次修改后commit,出问题可git reset --hard回滚。这是最基础的工程纪律,必须遵守。


1. 数据分级与锁定机制(2026-09-07球员分级已取消)

分级原则:按更新频率分层。锁定原则:低频数据确认后锁定,日常更新只能动第一级。重要变更:原A级/B级/C级/D级球员四级分级体系已于2026-09-07取消,所有球员一视同仁,详见1.5节。
层级包含内容更新频率当前状态解锁条件
第一级1A首页比分/进球轴/desc
1B积分榜/射手榜
1C球员出场/进球/助攻/零封
每场比赛后🔓 不锁每场更新
第二级名单/号码/位置/国籍/伤停转会窗🔒 已锁定(2026-09-07,31支俱乐部778人+9支国家队)用户明确说"解锁名单"
第三级FC评分(ovr)/六维(fc/abilities)/29项detailed赛季初/用户指定🔒 已锁定用户说"更新FC数据"

第一级铁律

第二级:单个球员修正(不需要解锁)

1.5 球员数据统一维护(2026-09-07取消分级)

核心原则:取消A级/B级/C级/D级四级分级体系,所有球员一视同仁。per90统一=25-26上赛季基准(per90Season=2025-26);26-27本赛季场均数据冬窗后统一更新(用户拍板,2026-09-08第22章定案,禁止赛季初小样本提前补),26-27只存seasonStats基础数(apps/goals/assists/cleanSheets)。关键认知:StatMuse数据源无反爬,球队级别页面一次返回整队数据,27队524人次约9分钟抓完,抓取成本极低,不需要通过分级来减轻维护工作量。

数据字段统一标准

数据类型字段维护频率说明
基础信息id/name/number/position/nationality/age/height/weight/club转会窗更新所有球员必须有
FC评分fc(OVR总评分)赛季初更新参考FC27官方数据
六维数据advanced(PAC/SHO/PAS/DRI/DEF/PHY)赛季初更新FC27官方六维或估算值
29项详细能力值detailed逐步补全优先补OVR≥80的核心球员
场均数据(per90)per90(26项非门将+门将综合页)26-27已上线,后续低频刷新StatMuse主源;详情页26-27(per90)与25-26(per90_2526)同格双值,列表页只显示26-27(见13.1b)

场均数据更新口径(以2026-09-08第22章为准,取代此前所有版本)

日常维护内容(不需要分级)

1.6 最近重大变更记录(2026-09-06)


2. 例行更新总流程(用户说"更新"时按这个走)

核心原则:用户只说"更新",AI自己判断该更什么、怎么更、验证完再部署。日常更新只动第一级。

标准步骤(每次必走,不能跳)

第1步:读手册 + 看锁定状态(30秒)

第1.5步:变更检测(必须第一步执行)

第2步:更新1A首页比赛(比分→进球轴→desc)

第3步:更新1C球员赛季数据

第4步:更新1B联赛排名

第5步:跑自动检查(必须全绿)

第6步:部署

第7步:更新状态表和日志


3. 数据源映射表(核心·以后直接照此查)

数据类型主源次源(验证)验证方式
比赛比分/进球时间轴直播吧/联赛官网(直接抄比分,不靠进球列表算)懂球帝两源进球者+分钟一致
赛季出场/进球/助攻FotMob球队页联赛官网统计页两源一致;进球之和=首页进球轴。不用FBref(英超滞后)
积分榜/射手榜直接抄现成榜单(球迷屋/新浪/联赛官网,方法见3.5.5)football-data API(程序化备选,key见关键配置)抄来即用,只用MATCHES反算关注队核对,不全量交叉
场均高级数据 per90StatMuse(球队页批量抓,详见第12章)FBref(仅xG/xA验证)Per90口径;StatMuse无反爬、一次返回整队,是当前主源
名单/号码/位置俱乐部官网+懂球帝转会新闻Transfermarkt⚠️ 所有阵容页都滞后,必须用转会新闻+官网双源
FC评分/六维FCRatings.com—fc六维=abilities对应项,统一采用FC27标准
29项detailedFCRatings.com球员页—29项齐全,值1-99
数据源沿革(避免再走弯路):①场均高级数据早期用FootyStats(Cloudflare反爬、单球员页、临时工取数不一致),后改用FBref,2026-09-06起全面改用StatMuse(无反爬、球队页一次返回整队29+14项),FootyStats方案废弃但保留在3.5.1作历史参考;②积分榜/射手榜早期靠MATCHES自己算(慢、且MATCHES只有关注队不完整、乌龙球算错),后确立直接抄原则;③FBref的26-27英超数据严重滞后(第3轮打完联赛页仍全0),绝不能作为基础数据和积分榜主源,只用于场均高级数据的交叉验证。

场均数据(advanced/per90)字段映射表(2026-09-07更新主源)

说明(重要):场均高级数据的主源已切换为 StatMuse(球队页一次返回整队、无反爬、Per90口径,抓取方法和字段对照见第12章)。下表是早期FootyStats/FBref时代的字段对照,仅在StatMuse缺某字段时用于补漏或交叉验证。FBref数据最全但有Cloudflare反爬、且英超更新滞后;FootyStats方案已废弃(见3.5.1)。

字段主数据源次源/验证获取方式备注
xG(预期进球)FBrefUnderstatFBref球员页scout报告 → npxGUnderstat只覆盖五大联赛,用于验证
xA(预期助攻)FBrefUnderstatFBref → xAG(Exp. Assisted Goals)FBref叫xAG,就是xA
进球FBrefFotMobFBref → Non-Penalty Goals + Penalties基础数据
助攻FBrefFotMobFBref → Assists基础数据
射门FBrefFotMobFBref → Shots Total基础数据
射正FotMobSofaScoreFotMob球员页 → Shots on targetFBref没有单独射正数
射正率FotMob(计算)—射正÷射门×100%计算得出,不用单独查
关键传球FBrefSofaScoreFBref → Shot-Creating ActionsFBref叫"创造射门动作",包含关键传球,范围更广
创造绝佳机会SofaScoreFotMobSofaScore球员页 → big chances created边锋/前腰关键字段
传球数FBrefFotMobFBref → Passes Attempted基础数据
传球成功率FBrefFotMobFBref → Pass Completion %基础数据
抢断FBrefFotMobFBref → Tackles基础数据
拦截FBrefFotMobFBref → Interceptions基础数据
夺回球权FBrefFotMobFBref → Ball RecoveriesFBref和FotMob都有,FBref更全
解围FBrefFotMobFBref → Clearances后卫关键字段
争顶成功数FBrefSofaScoreFBref → Aerials WonFBref有成功数,无总数
争顶成功率SofaScore—SofaScore → aerial duels won %FBref无法直接算(无总数),SofaScore有争顶总数和成功数
过人(成功)FBrefSofaScoreFBref → Successful Take-Ons边锋关键字段
传中(成功/总数)SofaScore—SofaScore → accurateCross / total crosses边后卫/边锋关键字段,FBref和FotMob都没有
传中成功率SofaScore(计算)—成功传中÷总传中×100%计算得出
被犯规FotMobSofaScoreFotMob → Fouls wonFBref没有此字段
触球FotMobSofaScoreFotMob → TouchesFBref只有分区触球,没有总数
门将扑救FBrefFotMobFBref → Saves门将专属
门将扑救成功率FBrefFotMobFBref → Save Percentage门将专属
门将零封FBrefFotMobFBref → Clean Sheets门将专属
门将失球FBrefFotMobFBref → Goals Against门将专属

数据源使用优先级(2026-09-07修订)

  1. StatMuse — 场均per90主数据源,球队页批量返回整队29项非门将+14项门将,无反爬、Node.js直连,详见第12章
  2. FBref — 交叉验证源(xG/xA等最权威),但有Cloudflare反爬、英超更新滞后,只用于验证和StatMuse缺字段时补漏
  3. FotMob — 基础数据(出场/进球/助攻)主源,补充射正、被犯规、触球等字段,中文界面好查
  4. SofaScore — 补充传中、争顶成功率、创造绝佳机会等细分字段
  5. Understat — 仅用于xG/xA验证,只覆盖五大联赛

按位置的关键字段速查

位置必查字段主数据源
边锋(LW/RW)xG、xA、射门、关键传球、过人、传中、被犯规FBref + SofaScore
中锋(ST/CF)xG、射门、射正率、争顶成功率、触球FBref + SofaScore
前腰(AMF)xA、关键传球、创造机会、传球成功率、过人FBref + SofaScore
后腰(DMF)传球数、传球成功率、抢断、拦截、夺回球权、触球FBref + FotMob
边后卫(LB/RB)助攻、xA、关键传球、传中、抢断、夺回球权、过人FBref + SofaScore
中后卫(CB)抢断、拦截、解围、夺回球权、争顶成功率、传球成功率FBref + SofaScore
门将(GK)扑救、扑救成功率、零封、失球FBref

铁律

  1. 查不到就换源,禁止填0、禁止估算、禁止按角色推断
  2. 两源不一致时,第三源裁决,少数服从多数
  3. 全部源不可用→保留上次值,更新日志标记,不编造
  4. 分清两类数据的源:基础数据(出场/进球/助攻)主源FotMob,不用FBref(英超滞后);场均per90主源StatMuse(第12章),FBref只做验证
  5. 补数据前先做三个圆分类(第14章),禁止不分类就一个一个查

关键配置

3.5 数据获取SOP(详细操作步骤,照着做就行,别走弯路)

核心原则:所有数据获取方法必须写死,包括用什么工具、什么数据源、URL格式、提取步骤、反爬应对、常见错误。这样不管是AI自己更新,还是别人接手,都能照着做,不用重新摸索。工具优先级:webfetch > Playwright/Puppeteer > curl。webfetch能自动处理反爬和JS渲染,是首选;curl大概率被拦截,不要用。

3.5.1 场均数据(advanced)获取方法 — ⚠️已废弃,保留作历史参考(主源改用StatMuse,见第12章)

⚠️ 本节为2026-09-06之前的FootyStats旧方案,已废弃。当时结论"不要用StatMuse"是错误的——后来验证StatMuse用Node.js https.get可直连、无反爬、球队页一次返回整队数据,已成为场均per90的主源(第12章)。本节仅在StatMuse确实缺某小众字段时作补漏参考,不要再按本节批量抓数据。

(旧)数据源:FootyStats(https://footystats.org)。旧方案曾认为FBref被Cloudflare拦截、StatMuse缺字段——这些结论已被第12章的StatMuse实践推翻。

工具优先级:

  1. webfetch(首选)— 自动处理反爬和JS渲染,直接返回页面纯文本,30秒搞定一个球员,不会被拦截
  2. Playwright/Puppeteer有头浏览器(备选)— webfetch不可用时用,每个页面等待3-4秒让JS渲染完成
  3. curl(禁止)— 大概率被Cloudflare拦截返回403,不要浪费时间

FootyStats球员页面URL格式:

https://footystats.org/players/{国家路径}/{球员slug}

11个字段的准确label和所在区块(一个字都不能错):

字段名含义FootyStats准确label所在区块取哪一列数据源
shots场均射门Shots TakenAttackingPer 90(第3列)FootyStats
shotsOnTarget场均射正Shots on Target(注意O大写)AttackingPer 90(第3列)FootyStats
xG场均预期进球Expected Goals (xG)AttackingPer 90(第3列)FootyStats
keyPasses场均关键传球Key PassesAttackingPer 90(第3列)FootyStats
xA场均预期助攻Expected Assists (xA)AttackingPer 90(第3列)FootyStats
dribbles场均成功过人Successful Dribbles(注意是Successful,不是Dribbles)AttackingPer 90(第3列)FootyStats
tackles场均抢断Tackles(注意不是Total Tackles)DefendingPer 90(第3列)FootyStats
interceptions场均拦截InterceptionsDefendingPer 90(第3列)FootyStats
passAccuracy传球成功率Pass Completion RatePassingTotal列(第2列),Per 90列显示N/AFootyStats
aerialDuelsWon场均争顶成功Aerial Duels WonDefendingPer 90(第3列)FootyStats
ballRecoveries场均夺回球权Ball RecoveriesMiscellaneousPer 90FBref搜索提取(FootyStats无此字段)

注意:前10个字段从FootyStats获取,第11个字段(ballRecoveries夺回球权)FootyStats没有,需要用general_search搜索FBref球探报告页面提取。搜索关键词格式:{球员英文名} Ball Recoveries per 90 2024-25 Premier League FBref。

提取步骤(webfetch方式,推荐):

  1. 用webfetch访问球员页面URL,获取页面纯文本
  2. 按区块分割文本:找到"Attacking"、"Defending"、"Passing"三个关键词的位置
  3. 在Attacking区块内搜索6个进攻字段的label,取Per 90列的值(第3个数值)
  4. 在Defending区块内搜索tackles和interceptions,取Per 90列的值
  5. 在Passing区块内搜索Pass Completion Rate,取Total列的百分比值,去掉%号
  6. 所有数值保留两位小数

提取步骤(Playwright方式,备选):

  1. 用page.goto()访问球员页面,waitUntil: 'networkidle'
  2. 用page.waitForFunction()等待页面包含"Shots Taken"关键词(必须等JS渲染完成,不要用固定等待时间)
  3. 用page.evaluate(() => document.body.innerText)获取页面纯文本
  4. 后续步骤同webfetch方式

反爬应对方法(用Playwright时必须看):

常见错误和解决方法(之前临时工犯过的,必须避免):

错误后果解决方法
用curl访问FootyStats被Cloudflare拦截返回403,全部数据为空用webfetch或Playwright,不要用curl
(旧结论,已推翻)用StatMuse作为数据源旧方案曾误判"StatMuse缺7字段、是SPA抓不到"已推翻:StatMuse正是当前主源(第12章),Node.js直连即可,本条作废
dribbles的label用"Dribbles"而不是"Successful Dribbles"dribbles字段抓不到,全部缺失label必须是"Successful Dribbles"
tackles和interceptions不限定区块,全局搜索可能抓到错误区块的数据,或者抓不到必须在Defending区块内搜索
只抓Attacking区块,不抓Defending和Passing缺抢断、拦截、传球成功率5个字段三个区块都要抓
passAccuracy取Per 90列Per 90列显示N/A,抓不到passAccuracy必须取Total列的百分比值
查不到数据就填0数据造假,后续无法区分"真实0"和"没查到"查不到就标记// No data available,禁止填0
国家路径用错(如英格兰球员用france)被重定向到列表页,返回空数据国家路径必须匹配球员国籍,不确定先查国籍

守门员数据说明:守门员的进攻字段(shots、shotsOnTarget、xG、dribbles)为0是正常的,但keyPasses、tackles、interceptions、passAccuracy应该有值。如果守门员的所有字段(包括passAccuracy)都是0,需要重新核实,可能是抓取失败。

3.5.1.1 标准提取脚本(必须用这个,禁止自己写提取逻辑)

铁律:所有场均数据提取必须使用标准脚本 extract_footystats.js,禁止自己写正则或提取逻辑。之前两个临时工取出不同的数据(Worker 1 tackles=0.51,DuMate tackles=1.50),就是因为各自写提取逻辑,一个取错了列,一个取对了。用标准脚本可以保证任何人跑出来的结果完全一致。

脚本位置:项目根目录 extract_footystats.js,每个任务包都会附带这个文件。

使用步骤:

  1. 用 webfetch 访问球员页面,把返回的内容保存到文件(如 saka.md)
  2. 运行:node extract_footystats.js saka.md
  3. 脚本输出 JSON 格式的10个字段数据(FootyStats可提取的,不含ballRecoveries),直接复制到数据文件中
  4. ballRecoveries(夺回球权)需要单独用general_search搜索FBref提取

脚本输出示例:

联赛: Premier League

{
  "shots": 2.87,
  "shotsOnTarget": 1.09,
  "xG": 0.4,
  "keyPasses": 2.59,
  "xA": 0.29,
  "dribbles": 1.86,
  "tackles": 1.5,
  "interceptions": 0.65,
  "passAccuracy": 77.25,
  "aerialDuelsWon": 1.2
}

✅ 10个字段全部提取成功

脚本处理的特殊情况:

如果脚本报错:

批量处理方法:

  1. 用webfetch并行获取多个球员页面(每批5-10个),保存为单独的文件
  2. 写一个简单的循环脚本,逐个调用 extract_footystats.js 提取数据
  3. 把提取结果汇总到球队的advanced.js文件中
  4. 每批之间间隔3-5秒,避免触发反爬

3.5.1.2 各位置核心字段要求(2026-09-06确定)

原则:每个位置有不同的核心字段要求,核心字段必须100%补全,次要字段尽量补全(容错率80%)。核心字段全有 + 次要字段达标 = 该球员数据达标。

位置核心字段(必须全有)次要字段(80%达标算过)次要至少要有
ST/CF 中锋射门、射正、xG关键传球、xA、过人、传球成功率3/4
LW/RW 边锋射门、xG、关键传球、xA、过人射正、传球成功率2/2(全有)
CAM/AM 前腰关键传球、xA、射门、xG过人、传球成功率、抢断、拦截3/4
CM 中前卫关键传球、xA、抢断、拦截、传球成功率射门、xG、过人、争顶成功3/4
CDM/DM 后腰抢断、拦截、传球成功率、夺回球权、争顶成功关键传球、xA、射门、xG、过人4/5
LM/RM 边前卫关键传球、xA、过人、抢断射门、xG、传球成功率、拦截3/4
CB 中后卫抢断、拦截、争顶成功、传球成功率、夺回球权射门、xG、xA3/3(全有)
LB/RB 边后卫抢断、拦截、关键传球、xA、传球成功率过人、争顶成功、射门3/3(全有)
GK 门将不需要补数据--

注意:夺回球权(ballRecoveries)是后腰和中后卫的核心字段,但FootyStats没有此字段,必须用general_search搜索FBref提取。这是数据补全中最耗时的部分。

3.5.1.3 大规模补全任务的临时工分工机制(2026-09-06建立)

背景:2026-09-06统计发现756名球员中有503人场均数据不达标,需要大规模补全。单个AI处理503人耗时太长,建立6人并行分工机制。

分工方法:

  1. 把503名未达标球员按顺序平均分成6份,每份约84人
  2. 每份打包成一个独立的任务包(zip),包含:任务说明书、球员名单CSV、标准提取脚本
  3. 每个任务包分配给一个临时工(数据协作伙伴),并行处理
  4. 临时工完成后,把结果文件(JS格式)发回,由CEO统一合并校验

任务包内容:

任务说明书必须包含的内容:

  1. 任务背景和目标
  2. 11个字段说明(10个FootyStats + 1个FBref)
  3. 各位置核心字段要求
  4. 如何从中文名搜索英文名(因为数据库中只有中文名)
  5. 如何构建FootyStats URL(国籍路径 + 球员slug)
  6. 标准提取脚本使用方法
  7. ballRecoveries(夺回球权)的FBref搜索提取方法
  8. 数据格式要求(JS格式,window.ADVANCED_DATA)
  9. 查不到数据的处理方式(留空不填0,标注原因)
  10. 回复要求(完成情况总结、交付文件、遇到的问题)
  11. 遇到困难怎么解决
  12. 实在解决不了怎么回复

文件名规范:

合并校验流程:

  1. 收到6个临时工的交付文件后,逐个检查JSON语法是否正确
  2. 检查每个球员的核心字段是否全有
  3. 检查数据是否合理(如OVR范围、数值是否异常)
  4. 合并到主数据库的data/players/*.js文件中
  5. 运行全量校验脚本validate_all.js,确保0错误
  6. 部署上线

历史教训:

3.5.2 OVR和六维数据获取方法

数据源:FCRatings.com(https://fcratings.com)。这是FC27官方评分的数据源,全队列表页可以批量提取,不需要逐个球员页搜索。

工具:webfetch(首选)或Playwright(备选)。FCRatings反爬不严格,curl也可能能用,但推荐webfetch。

球队页面URL格式:

https://fcratings.com/teams/{球队slug}

提取内容:球队列表页直接显示25人左右的OVR和六维(PAC/SHO/PAS/DRI/DEF/PHY),不需要进入球员个人页。

注意事项:

3.5.3 29项detailed数据获取方法

数据源:FCRatings.com球员个人页。

球员个人页URL格式:

https://fcratings.com/players/{球员slug}

注意事项:

3.5.4 名单和号码获取方法

数据源优先级:

  1. 俱乐部官网(最高权威)— 官方名单和号码最准确
  2. ESPN squad页面(次选)— 更新及时,号码准确
  3. 懂球帝转会新闻(验证)— 转会窗期间用于确认转会
  4. Transfermarkt(参考)— 号码更新有时滞后于官方官宣,而且被AWS WAF拦截,curl访问不了

注意事项:

3.5.5 积分榜和射手榜获取方法(2026-09-07更新为7联赛)

重要规则(2026-09-06确立,2026-09-07强化):积分榜和射手榜直接抄现成榜单,不要自己根据MATCHES比赛结果算。原因:MATCHES只有8支关注队的比赛,算出来不完整、容易错(乌龙球也算不明白),而且要翻所有比赛,很慢。抄不算,是铁律。

当前覆盖7个联赛:英超PL、西甲PD、德甲BL、法甲FL、意甲SA、葡超PO、欧冠CL。standings.js/scorers.js都按这7个key维护。

数据源(直接抄网页榜单):

抄取字段:积分榜=排名/场次/胜/平/负/进球gf/失球ga/净胜球gd/积分pts(对应standings.js字段);射手榜=排名/球员name/球队team/进球goals/助攻assists/出场played。

注意事项:

3.5.6 比赛结果和赛程获取方法

数据源:

注意事项:

3.5.7 desc(前瞻/后顾)获取和写作方法

核心原则(2026-09-06确立):禁止凭印象写任何事实性信息,必须先搜2-3个媒体报道融合提炼。AI训练数据有截止日期,2026年的转会、伤停、主帅信息可能不知道,凭印象写必然出错。

后顾(赛后总结)写作规范:

前瞻(赛前预告)写作规范:

搜索关键词格式:


4. 质量门禁与检查机制

核心原则:靠工具不靠自觉。更新了哪一级数据,就跑哪一级的检查;全部通过才能部署。

检查工具

工具检查什么运行方式
check_all.js结构/人数/ID唯一/资源引用/锁定状态/进球一致性node zuji_tools/check_all.js
validate_data.js球员数据字段齐全/枚举合法/数值范围/fc=abilitiesnode zuji_tools/validate_data.js
verify_data.js首页五方校验(比分↔进球轴/积分↔MATCHES/RANK↔积分/射手榜/desc)node zuji_tools/verify_data.js
change_detect.js变更检测(最近3天已赛/未来3天未赛/desc质量/更新建议)node zuji_tools/change_detect.js
deploy_site.sh一键上传全部文件到 COS/CDN+设置no-cache./scripts_ops/deploy_site.sh --cos-only

两道闸(务必分清)

回归测试(按变更类型触发)

改动必查
首页卡片/UI已赛能展开、未赛能收起、预约按钮、球队筛选、联赛切换
积分/射手榜切换、完整、不溢出、关注队金色高亮
player_common.js8个俱乐部队全部回归一遍(共用一份,一改全影响)
MATCHES比分比分=进球轴、积分交叉、API+懂球帝双源
名单/转会新球员字段完整、离队移除、HTML人数同步、双源验证

拟人视觉检查 v4(2026-09-08确立,人眼级全面检查)

为什么必须做:代码断言查不出"人眼一看就错"的问题——文字重叠、队名被时间盖住、百分比溢出框体、队徽国旗空白、颜色错配。用户原话:"你不是定位代码,你是检查的方法。如果真的是人看,一眼就看出来了。"检查必须像人眼一样看渲染后的画面(滚动着看,每一寸),而非只做代码断言。

工具:visual_check.py(Playwright渲染+几何检测+截图存证)

本日修复沉淀(2026-09-08,全部经visual_check验证0条)

问题根因修复规范(写进模板)
赛程收起行 队名被时间盖住/重叠.stack-time 居中left:50%,与长队名相交;宽卡片padding未计入.stack-team max-width:30%;.stack-time right:32%+去"周X"前缀(replace(/^周[天一二三四五六日]\s+/,''));队名字号11px
数据栏六项溢出框体(马竞56.2%)375px下6项挤压,24px数值超项宽≤520px媒体查询:数值14px、排名标签8px、gap:1px
"主场"球场名截断(16页).th-stadium nowrap+ellipsiswhite-space:normal + overflow-wrap:break-word + word-break:break-all
英文队名截断(Deportivo La…).th-name-en 11px超容器3px字号10px
首页顶部筛选行超宽3px10个队徽按钮+gap14超内容区.tf 20px + gap9px
队徽/国旗全空白(射手榜/积分榜/首页/球员页)crests.football-data.org / flagcdn 外链在用户手机端加载失败,显示alt文字挤占外链禁用,全部本地化到 data/img/crests/{id}.png、data/img/flags/{code}.png;新页引用队徽一律用 crestUrl() 走本地

新增静态资源铁律(2026-09-08教训:data/img未同步导致线上404)

球员归属强制校验机制(2026-09-06确立,解决AI印象与现实差距问题)

核心问题:AI训练数据有截止日期,2026年转会/主帅信息可能不知道,凭印象写导致事实错误。已犯错误:格拉利什(曼城→罗马)、恩佐(切尔西→利物浦?)、达尼洛(尤文→弗拉门戈,2025年1月就走了)、姆巴佩(巴黎→皇马)、卡塞米罗(曼联→迈阿密国际)等。AI的印象改不了,只能用方法弥补。

铁律(违反等于事故)

操作前检查清单(每次必走,不能跳)

操作类型必须先查什么禁止行为
写desc(前瞻/后顾)查数据库确认:球员归属、主帅、球队名单、伤停球员是否在队凭印象写"XX球员在XX队"、"XX主帅带队"
分配任务给协作伙伴查数据库确认:任务里的球员/球队在我们系统里存在,归属正确凭印象分配"查尤文的达尼洛"(尤文不在我们系统,达尼洛已转会)
审计协作伙伴交付包先过滤掉我们系统里不存在的球队/球员,只处理存在的看到交付包里有juventus.js就直接审计,不先确认我们有没有尤文页面
更新球员数据查数据库确认:球员当前在哪个球队,字段是否存在凭印象更新"姆巴佩在巴黎的数据"(实际已在皇马)
新增比赛/赛程查数据库确认:对阵双方球队在我们系统里存在,球员名单正确凭印象新增"巴黎vs皇马"(实际姆巴佩已在皇马,对阵关系变了)

转会确认名单(持续更新,操作前先扫一眼)

以下球员已确认转会,绝对不能再按原球队写:

球员原球队现球队转会时间确认来源
格拉利什曼城罗马2026年夏窗双源验证
姆巴佩巴黎圣日耳曼皇家马德里2024年夏窗官方宣布
达尼洛尤文图斯弗拉门戈2025年1月FBref/Transfermarkt
卡塞米罗曼联迈阿密国际2026年夏窗双源验证
摩根·罗杰斯阿斯顿维拉切尔西2026年夏窗双源验证
埃兹里·孔萨阿斯顿维拉阿森纳2026年夏窗双源验证

注意:这个名单只是"已确认的重大转会",不是全部。操作前还是必须查数据库确认,不能只看这个名单。

违规事故记录


5. desc前瞻与后顾规范(核心竞争力)

定位:观赛指南+看点提炼,不是流水账(用户会看集锦,过程不重复)。

写作铁律(2026-09-06确立)

已赛写后顾(补盲区)

只写时间轴和集锦看不到的东西:

常规进球不写(进球只进goals时间轴,集锦能看到)。

未赛写前瞻(提醒下一场看什么)

前瞻应该写什么(按优先级)

  1. 比赛重要性/背景:联赛位置影响、德比战、教练压力、杯赛晋级意义
  2. 近期状态走势:最近几场结果、主客场表现、进球失球趋势
  3. 战术对位:预期阵型、关键球员对位、比赛风格碰撞(控球vs反击、高压vs低位)
  4. 核心伤病影响:只提8支关注队的核心主力,且必须说明战术影响(如"萨利巴缺阵→后防出球和制空下降")
  5. 教练信号:赛前发布会透露的轮换、战术调整暗示
  6. 赛程因素:是否有欧战分心、舟车劳顿、连续客场
  7. 巴西球员相关变量(如有)

前瞻绝对不写什么

伤病信息的正确写法

不是"谁受伤了",而是"这个球员受伤对战术有什么影响"。

核心原则:前瞻是"提醒下一场看什么",不是"伤病名单播报"。读者想看的是这场比赛有什么看点、什么变量可能决定比赛,不是谁谁谁又伤了。

三次更新机制(2026-09-06确立,基于媒体发布时间规律)

后顾三次更新

次数时间点内容来源写什么
第一次比赛结束后1小时内直播吧/懂球帝即时战报+赛后采访初步后顾:比分、关键事件、意外变化(红牌/伤退/新援首秀)、主帅赛后即时采访要点
第二次比赛结束后6-12小时国内博主复盘(懂球帝专栏/直播吧战术板/虎扑评分)补充:战术转折、争议判罚分析、球员状态信号、关键数据
第三次比赛结束后24-48小时The Athletic/BBC/队报/图片报等深度分析提炼:轮换深意、数据背后的趋势、长期影响、下一轮前瞻

前瞻三次更新

次数时间点内容来源写什么
第一次新增比赛时(赛前7-14天)赛程公布+基本背景初步前瞻:比赛性质、排名背景、大致看点
第二次比赛前2-3天国内博主赛前观点(懂球帝/直播吧前瞻)补充:伤停传闻、预计首发、核心对位
第三次比赛前12-24小时最终首发确认+国外媒体赛前分析最终前瞻:确认伤停、首发预测、临场变量

前瞻段落骨架(2026-09-09 V8修订:90字压缩版)

每篇desc ≤90字,六要素压缩在一段内,不强制分段,信息密度优先:

① 看点钩子:这场为什么值得看,一句话具体信息("曼城若再平分差拉到5分"),禁"巅峰对决""焦点之战"。

② 背景数字:联赛位置/排名/分差/晋级意义,必须带数字。

③ 状态信号:最近走势一个趋势(连续不胜/主场强/进多丢多),不罗列战绩。

④ 战术对位:预期阵型/关键对位/风格碰撞一句话。

⑤ 伤停变量:只核心主力+影响,不列名单。

⑥ 信息量收尾:一个悬念或具体看点,禁"拭目以待"。字数硬上限90字,超了砍废话保事实。

AI味打散准则(2026-09-08新增,用户:一眼看穿AI文章已成公害)

禁用的AI腔(出现即返工):①排比/对仗句("不仅是实力的较量,更是意志的比拼");②总分总结构、每段首句都是主题句;③"值得注意的是""不可否认""综上所述""让我们拭目以待";④三个一组过度工整的并列;⑤空泛形容词(精彩绝伦/荡气回肠/技惊四座);⑥每篇固定"北京时间X月X日"开头;⑦完美总结式收尾(把全文复述一遍)。

人味写法(强制):①写具体(第几分钟、谁、什么数据、什么细节),具体本身就没AI味;②用引语(主帅发布会原话、球员赛后采访);③换视角(站在主队球迷/客队/中立角度看同一件事);④口语化连接("有意思的是""但问题在于""说到底");⑤留白不把话说满("这可能是""关键看");⑥长短句交替、短句收尾;⑦允许带一点点立场和情绪,不装客观播音腔。

写作流程(每篇必走):先搜2-3个媒体来源→提取事实与引语→按六段骨架填内容→自查AI腔清单→交给用户审。初稿只写骨架+事实,不追求一次成型;用户的修改意见是训练信号,每轮意见沉淀回本节。

巴西101分原则

同等内容给巴西考察球员多一分关注,不贴显性标签:

防重复机制


前瞻时效性强制规则(2026-09-08,治"初版躺平")

口水话黑名单(2026-09-08,出现即删)

伤停重复上报规则(2026-09-08)

6. 首页更新SOP

MATCHES字段

{team:"阿森纳", comp:"英超 第2轮", date:"2026-08-30 23:30",
 home:"阿斯顿维拉", away:"阿森纳",
 score:"", ended:false, goals:[["59'","萨卡","a"]],
 homeRank:5, awayRank:1, desc:"..."}

比赛列表45天检查更新机制(2026-09-06确立)

积分榜/射手榜更新规则(2026-09-06确立,重要)

核心原则:直接抄,不自己算。
禁止根据MATCHES数组中的比赛结果手动计算积分榜和射手榜。MATCHES只包含部分比赛(主要是8支关注队),自己算出来的积分榜不完整、容易出错。

比赛卡片六联赛配色(注意:这是首页比赛卡片的色条,不是积分榜;积分榜7联赛统一用teal渐变背景)

联赛色条卡片背景
英超 PL#F9A825 金黄#FFF8E1 浅黄
西甲 PD#2E7D32 绿#E8F5E9 浅绿
法甲 FL#0D2240 藏蓝#EBEEF5 浅蓝灰
欧冠 CL#1565C0 宝蓝#E3F2FD 浅蓝
德甲 BL#D20514 红#FFEBEE 浅红
国际赛 INTL#1B5E20 深绿#C8E6C9 浅绿

注:意甲SA、葡超PO目前只进积分榜/射手榜(7联赛),比赛卡片暂未设专属色,若后续这两个联赛出现比赛卡片再补色,不影响积分榜显示。


7. 部署SOP(2026-09-06架构重构后)

项目架构(数据与视图分离)

git版本控制(必须遵守)

标准部署流程(COS/CDN,2026-09-07起)

浏览器缓存问题解决(重要!2026-09-07更新)

历史部署平台(已废弃)

数据备份与恢复

版本号规则


8. UI已锁定设计(没要求别改坏)


9. 待办事项(按优先级,2026-09-06更新)

执行规则:做完一项划掉一项,绝对不重复列已完成事项;每次更新手册前先核对本清单。

P0 最高优先级(本周内完成)

P1 中优先级(本周内完成)

P2 低优先级(2-4周内完成)

P3 很低优先级(有空再弄)

已完成(不再重复列)

已否决不再做


10. 已知坑与教训

  1. 所有阵容页都滞后:Transfermarkt、Premier League官网、SPORT.es等6个网站验证滞后(格拉利什9/1租借埃弗顿,这些网站9/4还挂着他)。名单必须用转会新闻+俱乐部官网双源
  2. FBref查不到就返回0、且英超更新极慢:曼联8/30比赛到9/4还查不到;2026-09-07验证,26-27英超第3轮(9/6)全部打完,FBref联赛页积分榜仍全0、球队页阿森纳只显示1轮。基础数据(出场/进球/助攻)主源用FotMob,积分榜/射手榜直接抄不用FBref,场均per90主源用StatMuse,FBref只做xG/xA验证
  3. 转会窗截止日租借最容易漏:永久转会有官方公告不容易漏,租借(尤其是压哨)最容易漏。关窗后48小时内专门排查
  4. 批量抓取后必须抽样校验:罗马14人批量错误事件教训——批量抓取后不能直接入库,必须抽样校验
  5. 数据写入前必须加合法性校验:FBref返回0值事件教训——0值、空值、明显超出范围的数据禁止直接写入
  6. 转会更新必须同时处理转出球员:巴黎巴尔科拉错误残留事件教训——不能只加不删
  7. 变更检测必须第一步执行:不管检测到什么其他问题,都先把变更检测走完,再去处理其他问题
  8. API延迟:football-data API在比赛结束后30-90分钟才同步FINISHED状态,刚结束的比赛用懂球帝/直播吧交叉确认
  9. 比分不能靠进球列表算:之前比分根据进球列表计算,结果乌龙球算不明白(乌龙球算在对方头上,不是自己进的)。比分必须直接从联赛官网抄,不能根据进球列表算。进球列表只用来展示,不参与比分计算。乌龙球在进球列表里单独标注("乌"),不影响比分。
  10. 积分榜/射手榜不能靠算:之前根据比赛结果算积分榜和射手榜,需要找所有比赛,很慢,而且MATCHES只包含部分比赛(主要是8支关注队),算出来的积分榜不完整、容易出错。积分榜/射手榜必须直接抄数据源(球迷屋/新浪体育),不能自己算。
  11. 画蛇添足的计算要删掉:积分交叉验证(validate_standings.js)是画蛇添足——积分榜是抄来的,抄来的就是对的,不需要和比赛结果交叉验证,而且验证还需要找所有比赛,很慢。抄来的数据不需要验证,直接用
    批量抓取先抽查解析正确性再全量:2026-09-09血泪——parse_table 用"排名后600字符切段"解析,跨行截断导致名字/值错位("2025-26"/"0"/"2,141"等变成key),A组23队+seasonStats74队全部作废重抓。正确姿势:按 <tr> 逐行解析,NAME列固定第3列、指标值第4列,名字去尾部缩写(X. Y. 段),先抽查1队确认再全量。
    。

手册版本:v2.3 精简版(2026-09-07 逐字逐句校订)
v2.3本次校订:①在线地址/部署平台由surge.sh全面改为又拍云(deploy_upyun_sdk.py);②球队规模统一为31俱乐部+9国家队共40个球员页/数据文件;③数据源口径统一——积分榜/射手榜一律"直接抄现成榜单不自己算"(主源球迷屋/新浪/联赛官网,football-data API作程序化备选,禁用FBref抄英超),场均per90主源由FBref/FootyStats改为StatMuse(第12章),FootyStats旧方案3.5.1标废弃;④联赛数统一为7个(PL/PD/BL/FL/SA/PO/CL),删除"法甲德甲已删除"的错误说法;⑤StatMuse实际成果更正为26队737人、29项非门将+14项门将;⑥备份云端改为又拍云。
v2.2历史:从约19000字精简,删除历史试错记录、重复验证过程、已完成待办;保留执行规则、数据源映射、检查清单、更新流程。
完整历史记录:见 changelog.html

1.7 备份与diff机制(2026-09-05建立,2026-09-06升级全量备份)

目的:本地+云端双备份,每次数据更新留痕,出问题能精准定位到某次更新、某个字段,方便回滚和排查。避免出现云端数据丢失、本地无备份的情况。

双备份架构:

工具位置:

使用流程(每次更新/部署必走):

  1. 部署前全量备份:node tools/backup_full.js — 备份整个deploy_temp目录(含index.html、js、css、data、手册等全部89个文件),打包成tar.gz到backup/,自动清理30天以上旧备份
  2. 更新前数据备份:node tools/backup_data.js — 备份当前data目录到backup/时间戳/
  3. 更新数据:修改data/*.js文件
  4. 更新后对比:node tools/diff_update.js backup/时间戳 deploy_temp/data — 生成HTML变更报告到diff_reports/目录
  5. 查看报告:打开diff_reports/diff_时间戳.html,确认变更内容符合预期
  6. 部署前日期检查:node tools/check_dates.js — 扫描所有比赛日期,发现异常立即报警(未赛比赛日期已过去/已赛比赛日期在未来),有错误必须修正后才能部署
  7. 部署:确认无误后部署上线(云端同步更新)

全量备份说明:

报告内容:

注意事项:

11. 球队页面咪咕风格改造规范(2026-09-07 确定)

11.1 整体设计

11.2 Header规范

11.3 核心数据栏规范

11.4 联赛映射表

联赛代码球队
英超PL阿森纳、曼城、利物浦、切尔西、热刺、曼联、纽卡、维拉、布莱顿、水晶宫、布伦特福德、埃弗顿、诺丁汉森林、富勒姆、伯恩茅斯、桑德兰、利兹、伊普斯维奇、考文垂、赫尔城
西甲PD巴萨、皇马、马竞、贝蒂斯
德甲BL拜仁、多特
法甲FL巴黎
意甲SA国米、罗马
葡超PO波尔图
巴西国家队无特殊处理,显示"暂无联赛数据(后续将显示世预赛数据)"

11.5 队标ID对照表(football-data.org)

11.6 必须保留的元素


12. StatMuse 批量数据抓取方法(2026-09-06 新增)

12.1 数据源

网站:StatMuse.com

特点:自然语言查询,返回结构化JSON数据嵌入HTML中。支持批量获取球队所有球员的多项统计数据。

12.2 URL格式(关键!)

https://www.statmuse.com/fc/ask/most-{统计类型}-{球队slug}-player-{赛季}-season

示例:

12.3 可抓取的统计数据(早期验证12项,全量已达29项非门将+14项门将)

说明:下表是2026-09-06最早验证可行的12项;2026-09-06晚已由协作方全量抓取,实际每个球员拿到 29项非门将数据 + 14项门将专属数据(Per90口径),成果存于 statmuse_full_data.json(26队/737人,0失败)。完整字段以该文件和下表字段对照为准,下表URL关键词仍然适用。

统计类型URL关键词JSON字段名数据库字段说明
夺回球权most-possession-wonRECballRecoveries防守核心数据
进球most-goalsGgoals
助攻most-assistsAassists
射门most-shotsSHshots
射正most-shots-on-targetSOTshotsOnTarget
关键传球most-key-passesPASS-KEYkeyPasses注意字段名是PASS-KEY,不是KP
过人most-dribbles-completedDRIBdribbles注意字段名是DRIB,不是DRB
抢断most-tacklesTKLtackles
拦截most-interceptionsINTinterceptions
争顶成功most-aerial-duels-wonAER-WaerialDuelsWon注意字段名是AER-W,不是ADW
预期进球most-expected-goalsxGxG
预期助攻most-expected-assistsxAxA

12.4 球队slug对照表

球队StatMuse slug数据库文件名
阿森纳arsenalarsenal.js
曼城manchester-cityman_city.js
利物浦liverpoolliverpool.js
切尔西chelseachelsea.js
热刺tottenham-hotspurspurs.js
曼联manchester-unitedman_utd.js
纽卡斯尔newcastle-unitednewcastle.js
阿斯顿维拉aston-villaaston_villa.js
布莱顿brighton-&-hove-albionbrighton.js
水晶宫crystal-palacecrystal_palace.js
布伦特福德brentfordbrentford.js
埃弗顿evertoneverton.js
诺丁汉森林nottingham-forestnottingham_forest.js
富勒姆fulhamfulham.js
伯恩茅斯bournemouthbournemouth.js
桑德兰sunderlandsunderland.js
利兹联leeds-unitedleeds.js
皇马real-madridreal_madrid.js
巴萨barcelonabarcelona.js
马竞atletico-madridatletico.js
皇家贝蒂斯real-betisbetis.js
拜仁bayern-munichbayern.js
多特蒙德borussia-dortmunddortmund.js
巴黎圣日耳曼paris-saint-germainpsg.js
国际米兰interinter.js
罗马romaroma.js

12.5 抓取方法(Node.js脚本)

关键脚本:batch_all_stats.js(项目根目录)

步骤:

  1. 用Node.js的https模块直接请求URL(不需要浏览器,不需要webfetch)
  2. 设置User-Agent为Chrome浏览器
  3. HTML中的数据是JSON格式,用&quot;编码,需要先替换为普通引号
  4. 用正则匹配每个球员的数据块(从"NAME":[0,{"value":[0,"开始)
  5. 提取字段值:"字段名":[0,{"value":[0,值],"display":[0,"显示值"]}
  6. 计算Per 90:值 / (出场时间 / 90)
  7. 合并到数据库的advanced对象中

注意事项:

12.6 赛季支持

⚠️ 字段命名铁律(2026-09-07 血的教训):预期进球/预期助攻在不同批次脚本里出现过两套写法——全拼 expectedGoals/expectedAssists 和短名 xG/xA,而渲染层(ADV_POSITION_CONFIG、ADV_FIELD_LABELS、双排对齐)只认短名。曾导致 387 人次的 xG/xA 格子空白。规定:所有新抓取、新合并、派给协作方的数据,per90 一律用短名 xG/xA,禁止再写全拼。common.js 已加 normalizeAdv() 在渲染前兜底转换(短名优先、转后删全拼、用副本不污染原数据),但数据层仍必须统一,不能依赖兜底。同理字段单位、口径以第12章对照表为准,不得自造别名。

12.7 与其他数据源对比

数据源优点缺点
StatMuse批量获取、字段齐全、支持历史赛季、Node.js直接访问、无反爬ask聚合稳定覆盖五大联赛+巴黎/国米/罗马/AC米兰;不覆盖英冠(coventry/hull/ipswich)和葡超(porto),试各种slug都422,别纠缠
FootyStats数据详细、有advanced区块Cloudflare反爬、需webfetch、单球员页面
FBref数据最权威Cloudflare反爬、无法批量、英超更新滞后
FotMob界面友好默认显示当前赛季、API禁止访问

12.8 26-27更新流程(2026-09-07跑通,照此走)

  1. node fetch_2026_27.js 抓27队全部(约9分钟,可加队slug参数单队重抓),产出 statmuse_2026_27_raw.json
  2. node build_map_fingerprint.js 用25-26数值指纹反推重建英文→中文映射 name_map_auto.json(见12.9)
  3. node match_2026_27.js 三级匹配(auto本队/transferred转会/miss无名单),产出 match_report.json + need_review.json
  4. node merge_2026_27.js 把auto+transferred写入球员文件(旧值备份到per90_2526)
  5. miss的人走第14章三集合判断,真·新援打包补录(参考TASK-013)
  6. 统一刷新所有HTML的common.js/css版本号 ?v= 后,python3 deploy_2026_27.py 精准部署

12.9 26-27抓取的4个必踩坑 + 指纹反推映射法(2026-09-07血泪,务必照做)

URL模板:https://www.statmuse.com/fc/ask/{urlSlug}-{teamSlug}-player-2026-27-season,Node https.get直连,UA必须用Chrome120桌面UA。

指纹反推映射法(解决"英文→中文匹配率低"的关键,比人工建name_map高效得多):25-26全量数据(statmuse_full_data.json,英文名+per90数值)与现有球员文件(中文名+相同per90数值),用 ballRecoveries/keyPasses/tackles/dribbles/interceptions/aerialDuelsWon/crosses/clearances 这8个命名一致字段拼数值指纹,至少3个字段全等即判定同一人,自动重建英文→中文映射。25-26实测737人指纹配对536人(72.7%),叠加旧表后26-27自动匹配率从21.9%→78.1%。

译名全称/简称坑:name_map里常是全称"哈里·凯恩",球员文件里是简称"凯恩",精确相等会误判缺失。匹配函数要做 cnCore(取"·"后部分)+ 双向包含匹配,多人同时命中才标歧义人工确认(match_2026_27.js 的 findInRoster 已实现)。

13. 球员详情页场均数据显示规则(2026-09-06 确定)

13.1 整体设计

13.1b 双赛季同屏显示(2026-09-07 确定,最高优先级;2026-09-07晚改版为同格双值)

⚠️ 血的教训(2026-09-07):甲方早已明确「场均数据冬窗后才碰26-27、半年更一次」,但当时只被授权做列表页三个基础数,却擅自把全队per90从25-26整体覆盖成才打3轮的26-27并上线,属于越权。铁律:更改per90赛季口径、整批覆盖数据前,必须得到甲方明确授权;讨论方案阶段不得擅自上线。本次最终决策是不回滚、改为双赛季同屏保留。

13.2 各位置默认显示方案

中锋 ST/CF(默认8项)

注意:过人是现代全能中锋(罗纳尔多、亨利、哈兰德、伊萨克)的核心武器之一,必须放在位置相关,不能放展开看。

边锋 LW/RW/LM/RM(默认8项)

前腰 CAM/AM(默认8项)

中前卫 CM(默认8项)

后腰 CDM/DM(默认8项)

边后卫 LB/RB(默认8项)

中后卫 CB(默认8项)

注意:解围是中后卫四大核心维度之一(Gradient Sports数据确认),必须放在位置相关。

门将 GK(默认8项)

13.3 实现时间

等临时工全量数据(statmuse_full_data.json)抓回来后,合并到数据库,然后按照本规则实现详情页的颜色区分和展开功能。

14. 三个圆分类法(补数据前必须先做,2026-09-07 血的教训)

14.1 什么是三个圆分类法

在补全球员缺失数据之前,必须先做三个圆分类,把缺失球员按数据可得性分成五类,然后再派任务。不能盲目地一个一个查,否则会浪费大量时间和人力。

三个圆的定义:

14.2 为什么必须先做(血的教训)

2026-09-07的教训:之前补全88名缺失球员时,没有先做三个圆分类,直接派任务让师姐一个一个查,导致:

正确做法:先花10分钟做三个圆分类,把88人分成五类,然后按分类派任务,一次性做完,不用一轮一轮补。

14.3 五类分类标准

分类 定义 处理方式 优先级
1. 在小圆里 球员25-26赛季在你之前已经抓过的球队中 直接从已有数据文件(如statmuse_full_data.json)拿,必须找到,找不到就是名字匹配问题 最高(最快,零成本)
2. 在大圆里但不在小圆里 球员25-26赛季在数据源网站有数据的球队中,但你之前没抓这些队 重新去数据源网站抓这些球队的数据(一次抓整队,不是一个球员一个球员抓) 高(一次抓整队,效率高)
3. 不在大圆里 球员25-26赛季在数据源网站也没有数据的球队中 换其他数据源(如FBref),或确认确实没有数据后撇开 中
4. 替补门将/青年球员 替补门将、青年队球员、赛季无出场的球员 直接撇开,肯定没有per90数据,不用浪费时间 最低(直接跳过)
5. 不确定 不确定球员25-26赛季在哪支球队 先查清楚25-26赛季在哪队,然后按上述四类分类处理 先查再分类

14.4 操作步骤(补数据前必须按此走)

  1. 第一步:明确小圆范围 — 列出你之前已经抓过哪些球队的数据(如statmuse_full_data.json里有26队)
  2. 第二步:明确大圆范围 — 数据源网站(如StatMuse)覆盖哪些联赛哪些球队(可以测试几个典型球队确认)
  3. 第三步:列出缺失球员名单 — 从数据文件中筛选出per90为null的球员
  4. 第四步:逐个分类 — 基于足球知识,判断每个缺失球员25-26赛季在哪队,然后按五类分类
  5. 第五步:按分类派任务 — 不要混在一起派,按分类分别处理:

14.5 实际案例(2026-09-07,88人补全)

小圆:statmuse_full_data.json里的26支球队

大圆:StatMuse网站覆盖的所有球队(五大联赛+其他联赛)

球员圆:88名缺失per90数据的球员

分类结果:

分类人数处理方式
1. 在小圆里16人直接从statmuse_full_data.json拿,必须找到(马丁内斯、热苏斯、阿德耶米等)
2. 在大圆里但不在小圆里10人重新抓6支球队数据(沃尔夫斯堡、阿贾克斯、佛罗伦萨等)
3. 不在大圆里2人赛季无出场/FBref无此人,直接撇开
4. 替补门将25人直接撇开,肯定没有数据
5. 不确定35人先查25-26赛季在哪队,再分类处理

效果:分类后,16人直接从已有数据拿(零成本),25人直接撇开(不用管),只剩下10人需要重新抓球队数据+35人需要先查,工作量减少了一半以上,而且不用一轮一轮补。

14.6 注意事项

14.7 2026夏窗关键离队记录(2026-09-09登记)

第15章 师姐协作与新球队合并(2026-09-07)

15.1 协作机制(用户定的规矩)

15.2 新球队合并流程(2026-09-07已验证)

15.3 当前网站状态(2026-09-07)

第16章 合并校验关卡与协作红线(2026-09-07新增,防覆盖事故)

背景:2026-09-07合并师姐"新球队建设"包时发生覆盖事故——师姐旧队更新文件不带per90_2526导致41队25-26数据丢失;师姐基于旧底版common.js导致27队sm字段为空;师姐HTML退回旧h1导致Header消失。全部是"合并时没自动关卡"造成的。

16.1 合并校验关卡(合并任何交付包前后必跑)

16.2 协作红线(已发师姐,collab/caobao_协作规范_合并红线)

  1. 数据文件永远带per90_2526:师姐更新旧队数据只改per90,保留per90_2526;新队可无
  2. common.js必须带全TEAM_MAP的sm字段:sm为空说明底版旧,先要最新底版
  3. 球员页HTML禁止退回旧h1:必须保留<div class="team-header" id="teamHeader">;缺则只提取JS/CSS不采用HTML
  4. 合并前先跑校验关卡:validate_merge.py <zip> 全绿才合并
  5. 版本号统一:common.css/js?v=同一版本号

16.3 合并流程总纲(防覆盖五步)

  1. 备份+git提交当前状态(形成可回滚点)
  2. 跑validate_merge.py <交付zip>,有警告先看:sm空→补sm;缺teamHeader→不采用其HTML;缺2526→确认是否旧队更新(是→禁止整包覆盖)
  3. 提取式合并:只提取师姐要更新的部分(per90数据/新增函数/新增队),不整文件覆盖。旧队数据文件用"按名字合并per90"脚本,保留per90_2526
  4. 合并后跑validate_merge.py全绿
  5. 同步deploy_site+部署 COS/CDN+git提交

16.4 项目基建清单(师姐上帝视角误判的纠正)

第17章 协作行业标准与项目落地规范(2026-09-08新增,多人协作章程)

背景:团队从2人(草包+婉师姐)扩展为多人(+临时工+外部评审),用户要求"按行业标准来办"。本章用六项行业公认标准逐条核对现有做法:GitHub Flow(Git工作流)、Conventional Commits(提交规范)、SemVer(语义化版本)、Code Review(代码评审)、CI/CD(发布流程)、RACI(权责矩阵)+ 异步协作最佳实践。核对结论:对的坚持、错的改正、缺的补上。

17.1 六项标准核对总表

领域行业标准我们现状核对结论
沟通机制异步优先+文档化(低风险异步、高风险评审)collab目录+传话"发布了"+正式回复格式✅ 对,坚持(补:统一命名+回复时限)
Git工作流GitHub Flow:main永远可部署、小步提交、可回滚每日git提交+回滚点(8e9e626/3a98bea等)✅ 对,坚持(补:提交信息规范)
提交信息Conventional Commits:type(scope): desc中文长句(如"合并TASK-017赛程阵容Tab+版本号统一")❌ 改:从现在起用规范格式
版本号SemVer:MAJOR.MINOR.PATCH时间戳202609072300(缓存刷新参数)❌ 改:双轨制(见17.4)
代码评审PR模板+自查清单+及时反馈validate_merge.py自动关卡+CEO人工验收回复✅ 对,坚持(补:交付自查清单模板)
发布流程校验全绿→部署→回滚预案(触发/步骤/执行人)validate全绿→部署 COS/CDN→git回滚✅ 对,坚持(补:正式回滚预案)
任务分配RACI矩阵(一事一A,A唯一)草包统筹、师姐功能侧、临时工一次性、用户拍板✅ 方向对,正式化RACI(见17.5)

17.2 沟通机制(坚持+补漏)

17.3 Git提交信息规范(改)

行业标准:Conventional Commits(Angular/Vue/React等主流项目采用)。

落地格式(简化版):

feat(球员页): 新增阵容/赛程Tab切换
fix(首页): 修复手机返回空白(bfcache)
docs(手册): 第17章协作标准
chore(部署): 部署v2300
data(球员): 补全曼城25-26场均数据

17.4 版本号双轨制(改)

17.5 RACI权责矩阵(正式化)

任务/角色用户(甲方)草包(CEO)师姐(功能侧)临时工(数据侧)外部评审
需求决策ACIII
任务分配与验收ARIII
数据侧执行IRIR(分派时)I
功能侧执行IR(统筹)R(执行)II
部署上线IRIII
质量评审IAR(自查)R(自查)C

A=最终负责(唯一) R=执行 C=咨询 I=知情。核心:用户是唯一A(最终拍板);草包是部署/验收的A+R;师姐是功能执行的R;临时工是数据执行的R;外部评审只做C(提供意见不决策)。

17.6 发布流程与回滚预案(补全)

标准发布流程(每步必须):

  1. 合并前:跑 validate_merge.py <交付zip> 全绿(否则退回)
  2. 合并后:跑 validate_merge.py 全绿
  3. 同步deploy_site → 部署 COS/CDN(记录文件数/失败数)
  4. 线上验证(chromium无头抽查关键页面)
  5. git提交(Conventional Commits格式)
  6. changelog.html更新SemVer版本号

回滚预案(三件事写死):

17.7 交付自查清单(补,发给所有协作方)

任何交付包必须随附交付说明,包含以下五段(缺一段验收时退回补交):

【TASK-XXX 交付说明】
一、改动内容:改了哪些文件、各改了什么(逐条)
二、验证结果:怎么验证的、测了什么、结果如何(写明浏览器/尺寸)
三、自查清单:
  [ ] 数据文件带per90_2526(旧队更新时)
  [ ] common.js含全部关键函数+sm字段非空
  [ ] HTML含id="teamHeader"(球员页)
  [ ] 版本号统一
  [ ] 语法检查通过(node --check / chromium实测)
四、待确认问题:需要草包侧决策/确认的事项
五、数据说明:数据来源、口径、与上次的差异

17.8 基线制度(治本:彻底解决"协作方基于旧底版交付")

事故复盘(2026-09-08):师姐TASK-017/016/019b三次交付均基于旧底版(缺goTo/缺Tab/sm空),草包每次"提取式打补丁"重复劳动。更深层:TASK-017合并时用 git stash push 备份,把含Tab的common.js存进stash后工作区被重置,导致Tab版本从未进入git历史、从未上线——备份用git commit,绝不用git stash(commit可追溯,stash会吞修改)。

行业标准对应:GitHub Flow的"单一事实来源+开工前拉最新+CI自动拦截"。落地为基线制度:

  1. 发任务包必带基线:草包发任务包时,包内附 baseline/ 目录(最新common.js/index.html/模板)+ BASELINE.json(版本号+文件SHA256+关键函数指纹),用 python3 make_baseline.py 生成。协作方必须基于包内baseline修改,禁止用自己本地旧版。
  2. 交付必随附BASELINE.json:从基线复制不改动。合并前 validate_merge.py <zip> 自动对比:交付的common.js/index.html若缺基线关键函数(renderTeamHeader/renderSeasonBlock/openPlayerModal/loadTeamStats/goTo/goBack/initViewTabs/renderSchedule等)→ 硬错误退回,机器拦截,不靠人工发现。
  3. 关键函数指纹清单(BASELINE.json维护):common.js 8项(含Tab),index.html 5项。任何交付缺一项即判"基于旧底版"。
  4. 交付包文件名规范:<角色>_<类型>_<主题>_<日期>.ext(caobao_task_/wan_delivery_/caobao_reply_/caobao_note_)。

使用流程:

# 草包发任务前
python3 make_baseline.py                    # 生成基线(版本+指纹)
zip 任务包.zip 任务说明.txt baseline/ 相关文件  # baseline内含BASELINE.json

# 合并交付包前(必须)
python3 validate_merge.py 交付包.zip         # 【7】基线一致性检查自动拦截旧底版

17.9 授权边界与直接发布规则(2026-09-08,分工细化)

分工原则:草包负责决策/商量/大环境(统筹+验收+部署),师姐负责小检查/小改动执行。用户可直接向师姐派小任务。

A类(师姐可直接发布)——小改动:

B类(禁止直接发布,必须发草包验收合并):

工具包:deploy_single.py(单文件发布,含Content-Type映射+禁止名单)、validate_merge.py、make_baseline.py、BASELINE.json 已打包发师姐(collab/caobao_task_工作包_授权边界与直接发布)。

回滚责任仍在草包:师姐直接发布出错→草包用git/旧版回滚,不影响B类流程。

17.10 发布/回滚命令固化(2026-09-08,一条命令完成标准发布)

问题:此前"手动校验→手动部署→手动记版本",环节多易漏(曾发生没校验就发布、Tab版本被stash吞)。行业标准:发布流程固化成可执行命令,校验内嵌,不通过自动停止。

标准发布(一条命令):

python3 release.py "改动摘要"           # 默认PATCH(bug修复)
python3 release.py "改动摘要" --minor   # MINOR(新功能)
python3 release.py "改动摘要" --major   # MAJOR(不兼容变更)

自动完成4步:①validate_merge.py全绿(红字禁止继续)②部署 COS/CDN ③git commit+打SemVer tag ④changelog.html记录。任何一步失败即停止,不产生半成品。

一键回滚(执行人:草包唯一):

python3 rollback.py            # 回滚到上一个tag
python3 rollback.py v1.4.0     # 回滚到指定版本
python3 rollback.py <commit>   # 回滚到指定提交

自动完成:checkout目标版本→校验全绿→部署。未提交的新工作不受影响。

SemVer规则(已通过release.py强制):MAJOR=不兼容变更 / MINOR=新功能 / PATCH=bug修复。当前 v1.4.0。每次发布自动打tag+更新changelog,版本永远可追溯。

回滚预案三件事(17.6已定义,现在可执行):触发条件=validate报错/线上异常;操作=python3 rollback.py;执行人=草包。

17.12 产品测试流程(2026-09-08,QA角色正式上岗)

铁律:写代码的人不测自己的代码。用户已明确不再当第一道测试(此前一直是用户发现错误,成本极高)。

测试三级流程:

  1. 草包自查(发布前必做):validate_merge.py全绿 + chromium headless抽查关键页(首页/球员页/Tab/手机宽度)+ 数据文件与页面引用核对。自查不过不发布。
  2. 师姐QA测试(TASK-020起):按测试清单逐项实测(首页8项/球员页9项/国家队/数据一致性,共20项),问题分级P0致命/P1严重/P2轻微,P0/P1不修复不许报通过。报告五段式(环境/总览/问题清单含复现步骤/通过项/建议)。
  3. 用户终验:只看最终成果,按验收清单划勾。用户发现问题→退回草包+师姐,查流程哪一环漏了(自查还是QA),不重复修。

RACI更新:师姐兼任QA(R:功能执行+测试执行),草包(A:验收/部署),用户(A:唯一拍板/终验)。

责任链:用户发现错误时,先查"自查漏了还是QA漏了",写进对应环节的检查清单,不允许同一类错误第二次到用户手里。

17.13 批量改动防呆(2026-09-08,颜色事故教训)

事故:TASK-017批量套用阿森纳模板生成62页,--team-color变量未按队替换,30个豪门页全变阿森纳红。代码检查(validate/chromium抓DOM)全部通过,因为代码结构没问题——只有人眼能发现"颜色不对"。

教训:

  1. 批量套用模板后,必须抽≥5队肉眼验证变量值确实不同(不是只看代码)
  2. 凡含"按队不同"的变量(颜色/队名/队标/数据),批量后必须逐队diff检查变量值
  3. 测试清单增加"人眼视角"项:每个球队页颜色/Header/队标是否跟队走
  4. 用户是最终验收人:用户报的视觉问题优先于所有代码级检查

批量后必查命令:

# 检查是否全站同一个颜色(应多色)
grep -l -- "--team-color: *#C41E3A" *_players.html | wc -l   # 应远小于页面总数
grep -o -- "--team-color: *[^;]*" *_players.html | sort | uniq -c  # 看颜色分布

17.14 AI视觉质检(2026-09-08,产品检测员升级)

为什么升级:用户指出"代码层面检查看不到颜色不对/元素挤压/超出边界/图标不显示"——TASK-020测试(Playwright抓DOM+查函数)通过了所有代码检查,但30个球队页全是阿森纳红色,代码检查完全没发现。行业标准:视觉回归测试+Vision Model QA(截图→AI看图→结构化断言),代码断言测不了"样子对不对"。

检测员职责:像用户一样打开网站、用眼睛看、逐寸逐按钮检查(手机375px为主+桌面1440px)。每页从上到下逐区域看图,每个按钮真的点。

逐寸检查清单(每页通用):颜色跟队走 / 队标图标无裂图 / 无挤压重叠错位 / 无溢出被切 / 间距一致 / 文字可读(深底浅字)/ 空态区分"无数据正常"与"应该有没有"。球员页:Header→数据栏6项→Tab→列表→详情弹窗(三色规则/双赛季同格/✕能关/返回)。

视觉基线(草包侧):

python3 /tmp/visual_shot.py          # Playwright全站截图(线上URL,手机+桌面,等networkidle)
python3 visual_diff.py                # 改版后对比基线,列出视觉变化页,AI分类(有意/无意)

基线目录 /home/user/deploy_site_shots/{mobile,desktop}/(68页×2尺寸)。改版后diff >0.5%像素即需人工/AI确认变化是否有意。

铁律:检测结论必须"人眼看着对",不许"代码看起来对"。用户报的视觉问题优先于所有代码级检查。

第18章 AI全盘战略(2026-09-08,白皮书v1.0)

一句话:足记不只是"网站+AI工具",而是让AI成为产品的心脏——数据活、质检AI首检、保护物理级、错误自动吸收、内容人机分层、体验拟人化、协作规则化。

七大系统:①数据神经系统(Schema+来源标注+交叉验证+异常检测)②质检免疫系统(L1机器→L2视觉→L3探索→L4师姐→L5用户)③安全防护(部署前快照+指纹校验+自动回滚+凭证管理+恢复演练)④自我进化(错误→代码级防再犯规则,不靠记性)⑤内容引擎(DESC护城河+AI周边素材/速览/故事)⑥体验系统(拟人化走查/个性化/仪式感/语音/问答)⑦协作操作系统(任务自动路由+决策自动化)。

铁律:每个教训必须变成"机器拦",不是"人记";重复决策自动化,人只管例外;检测结论必须"人眼看着对"。

完整版:docs/AI战略白皮书_v1_2026-09-08.md(collab: caobao_note_AI战略白皮书_v1_全盘AI规划_2026-09-08.md)

17.15 部署防呆三铁律(2026-09-08,血的教训)

教训一:rsync污染——`rsync -a --delete ./ /home/user/deploy_site/` 把项目根的 node_modules/task*/worker*/zip/py 全部同步进部署目录,线上被传了1588个文件(原本只有134个)。铁律:deploy_site 只能由部署脚本(deploy_site.sh)维护,禁止rsync整个项目根;往部署目录同步必须用白名单式复制(只拷 *.html + data/)。

教训二:清理白名单——线上清理垃圾文件时,白名单漏了 `*_players.html`,62个球员页被误删(幸好本地完整,重部署恢复)。铁律:线上删除前必须列出完整白名单(*_players.html + index/manual/changelog + data/ + collab/),先dry-run打印清单确认再删。

教训三:又拍云SDK目录判断——getlist 返回 type='F' 是文件夹(不是'folder'),删目录要先递归删内容再删目录。写清理脚本时先验证 type 取值。

正确部署流程:改文件(项目根)→ validate_merge.py 全绿 → 用 deploy_site.sh(只认 deploy_site)→ curl 抽查线上 200 → visual_shot.py --new + visual_diff.py 看变化分类 → git commit。

本章一句话总结:协作的行业标准核心是"异步文档化沟通 + 一事一A + 校验关卡 + 可回滚"——我们已有骨架(collab/validate/每日git),补上命名统一、提交规范、SemVer、回滚预案、自查清单五块,即可按行业标准运转,多人加入不乱套。

第19章 检查体系升级:验收标准清单+错误自动吸收(2026-09-08新增,血的教训)

触发背景:用户连续报出射手榜无国旗、按钮无描边、球衣配色丢失、列表卡片无赛季数据——这些我设的检查全没拦住。根因分析:

根因一:视觉diff只做"变化检测",不做"对错检测"——visual_diff 对比的是基线截图;基线=TASK-021修复后状态,基线里就没有国旗/描边/卡片数据,diff自然报"无变化"。基线固化错误=错误永远发现不了。

根因二:检查清单只查负面现象,不查正面验收——旧清单查"裂图/溢出/重叠",不查"射手榜必须有国旗、按钮必须有描边"这类产品定义。

根因三:产品定义散在聊天里,没固化——用户确认过的规则(球衣配色、双赛季同格、8色、列表页三数据)没变成可逐条勾选的机器清单。

升级方案(L3对错检测层):新增《产品验收标准清单》PRODUCT_ACCEPTANCE.md(collab: caobao_note_产品验收标准清单_2026-09-08.md),A-F六类条目全部固化用户确认过的产品定义。规则:

① 每次全站测试必须逐条对照该清单;② 清单比视觉diff权威,"看起来没坏"不算过,清单条目不满足=问题;③ 基线≠权威,清单=权威,基线缺项要补基线;④ 错误自动吸收:每次用户报错→先问"这为什么没拦住"→升级清单/检查工具→再改bug,不许先修后忘;⑤ 发现清单没覆盖的新产品定义→立即补清单。

检查体系四层(升级后):L1代码校验(validate_merge.py)→ L2视觉diff(visual_diff.py,变化检测)→ L3产品定义对照(PRODUCT_ACCEPTANCE.md,对错检测) → L4人眼(师姐TASK-026全量130页次)+ L5用户终验。

铁律:用户报的每个错,第一反应必须是"升级检查体系",第二才是改bug。改完bug必须把该错误写进验收清单,否则下次还是漏。

第20章 行业标准落地:Design Tokens + 视觉回归基线管理(2026-09-08新增,查标准抄来的)

来源:不探索,查行业标准(Design Tokens 2014年Salesforce提出,全球设计系统标配;视觉回归测试为前端CI标准)。用户原话:"肯定有行业标准,你去抄嘛,探索个毛线"。

Design Tokens铁律:所有主题色走 var(--team-color)/var(--team-watermark-color),禁止裸写死(裸写死=违反单一事实来源,改一处坏一处)。三层:primitives(基础色值)→semantic(--team-color语义层)→component(组件层)。合规检查工具:python3 check_hardcoded_colors.py .(部署/测试前必跑,全库裸写死=0才放行)。

本次实战抓到的两个真bug:①62页详情弹窗评分均值ratingAvg裸写死color:#C41E3A(阿森纳模板残留24处)→已改var(--team-color);②球衣渐变第二段裸写死#EF0107:linear-gradient(180deg, var(--team-watermark-color,#EF0107) 0%, #EF0107 100%)——球衣"上半段跟队色、下半段永远阿森纳红"(皇马白球衣变白→红渐变)→已改双token。这两个都是"画好了又变"的代码级真凶。

视觉回归基线管理(行业标准):①基线快照必须进git版本控制(禁只存本地目录);②只有"有意的、用户/设计批准的"UI变化才更新基线;③基线来自"确认正确的需求",不来自"当前现状"——现状拍照=固化错误;④基线生成环境=测试环境(测线上URL,禁止测本地臆想版);⑤差异=回归缺陷,先审后更新。

组件集中原则:同样的样式(弹窗rating/卡片/Header)必须集中在common.css,禁止逐页复制62份——复制62份=改1处要改62处,漏1个就"变了"(62页#f8f8f8/#888/#333同类样式逐页复制,待收敛)。

第21章 发布门禁(release_gate.py,2026-09-08新增,行业CI/CD适配静态站实际)

行业标准:CI/CD流水线在合并前自动跑测试门禁。我们无CI服务器(静态站+又拍云+师姐协作),适配为本地发布门禁脚本:python3 release_gate.py,5关全绿才允许合并/部署。

五关:①validate_merge全绿(数据+代码+基线7关)②Design Tokens合规(check_hardcoded_colors全绿)③页面结构完整(62页teamHeader/ts-goals/common.js/goBack)④数据一致(62文件≥15人+seasonStats存在)⑤git工作区干净。

红灯=预期拦截也记录:门4红灯≠禁止前进,是"待办清单"(如seasonStats=TASK-024进行中),部署前确认红灯项有明确负责人在做即可。

17.16 流水线缓冲规则(2026-09-08用户提议后固化)

问题:旧流程"师姐做A→交付→草包验证合并(15-20分钟)→师姐干等→发结果→做B"串行阻塞,师姐交付后空转,任务排队积压(025/026曾长期排队),全量覆盖推进慢。

规则(流水线缓冲,参考生产管理):①师姐手上常备≥2个任务(交付前就已拿到下一个);②交付-验证异步化:她交付→立即做手上下一个,草包异步验证→验证结果发collab→她有错才修,不阻塞主流水;③草包验证必须脚本化提速(发布门禁+自动抽查),目标10分钟内闭环;④任务包一次多批派发(如027+025+026一起排队),师姐按编号顺序执行;⑤版本基线:她每次交付前确认基于线上最新版(TASK-022教训:测旧版=白测)。

19.7 数据合理性验证(2026-09-08新增,红牌数据事故后固化)

事故:皇马红牌显示1.75/7张,西甲官网实际=0张(4轮黄牌8、红牌0);切尔西2.67/8张同样离谱。StatMuse球队红牌字段不可靠,已全库置空(77处),待英超/西甲官方源逐队核实后补,宁缺毋滥。

铁律:①任何per90类数据入库前做合理性检查:红牌per90>0.5、单场>2张、出场数>赛程轮次×2 等必须人工核实;②新数据源首次使用前,用已知球队(如皇马红牌=0)交叉验证;③per90字段语义固定=25-26上赛季数据,26-27本赛季场均冬窗后统一补充,禁止拿旧数据冒充新赛季(弹窗26-27列无数据显示"-",不fallback)。

第22章 数据治理:per90统一基准(2026-09-08新增,赛季混合事故后固化)

事故:TASK-025扫描发现per90字段赛季混合无标记——同一队内拉亚per90.minutes=270(26-27的3场)与萨利巴=2614(25-26整季)并存,数据语义被破坏。根因:per90曾在多轮任务中被部分覆盖(StatMuse 26-27赛季初数据混入25-26基准)。

治理方案(已执行,TASK-025B):①per90统一=25-26上赛季基准(数据源:statmuse_full_data.json 26队全量英文名匹配530人 + per90_2526备份412人,两源皆无=置空不编818人);②per90Season字段全库统一标"2025-26"(杜绝无标记混放);③26-27本赛季场均冬窗后统一更新(用户拍板,禁止赛季初小样本提前补——已证实1分钟传360球伪值);④零分母治理:minutes缺失/0带场均值的置空;⑤门将字段单独核查补齐。

新铁律:①per90语义固定=25-26上赛季,26-27数据只存seasonStats(apps/goals/assists/cleanSheets),冬窗后整体换新;②任何per90改动必须同步per90Season标记;③字段短名铁律(手册12.6):expectedGoals/expectedAssists全拼一律xG/xA(全库654处已清零);④从StatMuse全量复制数据时禁止带"门将模板值"(arsenal 3人advanced曾整段被拉亚模板覆盖,已用全量正确值修复);⑤新数据入库先做跨源交叉验证(19.7)。

第23章 检查体系2.0:拟人检查+行业标准(2026-09-08新增,用户灵魂拷问"你到底检查了没有"后固化)

背景:用户连问"AI检查到底行不行""你是不是没好好检查",并用两张截图证明代码级检查抓不到的视觉问题(拜仁队名时间黏连/巴黎时间缺前缀/利物浦队徽爆框/国旗缺失)。结论:代码检查(L1-L3)拦数据与结构,拦不住"人眼级排版与交互"。

拟人检查三查法(《视觉检查操作方法》collab存档):①截图查:手机414+桌面1280双宽度chromium headless真渲染截图(不受缓存干扰);②DOM查:getComputedStyle查主题色/球衣渐变真实样式(截图看不出的用这个);③交互查:JS真点每个可点元素(切Tab/开弹窗/验证跳转目标)。

检查经验库(盖楼式防漏,docs/检查经验库_人眼发现.md):每次用户/拟人发现漏网问题→立即追加为"必查项"→下次检查必须验证。覆盖面只增不减,历史漏网(球衣染错色/全队变红/按钮无描边/弹窗同值冒充/长队名黏连/队徽爆框/国旗缺失/按钮行为不对…)全部进库。

行业标准融入(ISTQB/黑盒测试查证):①四级测试:组件(JSON合法)→集成(页面↔数据)→系统(师姐全站测试)→验收(用户终验);②用例设计四法:场景法(用户主流程走通)、边界值(0出场/末位排名/空数据/超长队名/OVR极值)、错误猜测法(=检查经验库)、回归(改动后全站复测);③兼容性:手机375+桌面1280必测;④缺陷管理:一事一报/客观描述/跟踪到底。

铁律:检查动作全部脚本化/清单化可分配,草包不闷头全看——归纳方法→派师姐执行→草包验收,效率2/3师姐、1/3草包。

23.1 检测能力矩阵(2026-09-08,甲方验收标尺:看检测能力不看网站样子)

甲方定调:验收标准=工具能不能自己发现所有问题并修复,而非产品形态。检测能力分四层,逐层加厚:

L1数据层(全量):JSON合法/字段口径/缺失/零分母/赛季混合——validate_merge.py+自动化断言。盲区:值本身对错(需官方源人工核实,如红牌)。

L2结构层(全量):页面完整性/引用残留/链接/硬编码颜色——断言脚本+check_hardcoded_colors.py。盲区:排版视觉。

L3视觉层(人眼级):破图/溢出/颜色/间距/遮挡——Playwright手机414+桌面1280双宽度截图+DOM复核。盲区:截图看不出但人眼难受的细节。

L4交互层(全量):每个按钮真点/Tab/弹窗/跳转——JS交互自动化。盲区:设计合理性判断(需甲方球商)。

漏检进化机制(盖楼式,已生效):每次甲方/拟人发现漏网→根因分析(为什么没查到)→补进检查经验库必查项→下次必查。覆盖面只增不减,检测能力随轮次加厚。

效率目标:问题从发现到修复上线闭环≤2小时;执行完工作立即巡检,不等定时。

17.17 collab自动巡检+休眠唤醒协议(2026-09-08新增,去人工信使)

问题:草包与师姐经又拍云collab异步交换文件,无通知机制,此前全靠用户传话"发布了",用户被迫当人肉信使。

双向自动轮询(已上线):草包侧定时任务「collab交付自动巡检」(每30分钟):跑 poll_collab.py 查collab新 wan_delivery_* → 自动下载→验证→合并→门禁→部署→git→汇报。师姐侧同构(每30分钟查 caobao_task_* 自动开工)。补充(2026-09-08脱手测试):草包每次执行完工作(发任务包/部署/改数据/更新手册)后,立即手动跑一次 poll_collab.py 检查师姐新交付,不等30分钟定时;师姐同理(每次交付完立即查新任务)。目标是全自动闭环、用户完全脱手。

休眠/唤醒协议:①用户1小时无交流=离线:巡检触发时读 /tmp/collab_inbox/active.txt 时间戳(草包每回复更新),超3600秒→停本任务+传 caobao_note_休眠 通知→师姐见文件自停;②用户回来发消息=自动唤醒:恢复任务+传 caobao_note_唤醒 通知→师姐自恢复;③消耗优化:活跃期30分钟、休眠期零消耗,用户手动通知两边兜底。

铁律:草包每轮回复顺手更新active.txt(收到用户消息的第一时间写当前时间戳,不攒不拖);休眠/唤醒通知文件命名 caobao_note_休眠_日期.txt / caobao_note_唤醒_日期.txt,师姐轮询按优先级处理(休眠>唤醒>任务包>说明)。
防御式判定(2026-09-08教训修正):active.txt 缺失或读取失败 → 一律视为用户活跃,禁止判离线。休眠的唯一依据是「文件存在且确实超过3600秒」。宁可多跑一次巡检,绝不因文件缺失误休眠——用户全程在聊天却被判定离线导致师姐休眠,就是这个漏洞(15:15误休眠事故)。巡检任务query已同步此逻辑。

17.18 协作文件命名规范(2026-09-08定死,唯一版本,无变体)

历史教训:师姐交付曾用 wan_delivery_* / wan_TASK026_截图* / 交付N_* 三种风格顺手命名,导致巡检脚本两次漏检。现定死四类命名,所有协作方必须严格使用,禁止任何变体:

① 师姐交付:wan_delivery_任务号_内容简述_日期.zip(示例 wan_delivery_TASK026FIX_图标与返回按钮修复_2026-09-08.zip)——内容简述用"修复/数据/报告"等词,中间产物截图单独打 wan_delivery_任务号_截图_日期.zip。

② 草包派任务:caobao_task_任务号_内容简述_日期.zip。

③ 草包通知/决策:caobao_note_类型_日期.txt(类型=休眠/唤醒/决策/说明)。

④ 禁止:不带delivery/task/note前缀的裸命名(如"交付1")、中文无后缀(交付3_TASK017)、时间戳缺失。

商业化方向已交底(2026-09-08):项目已进入商业化准备阶段,026终测通过后输出《商业化就绪度清单》。


==== 12.10 seasonStats 快抓法
========== 12.10 seasonStats 快抓法 ==========
12.10 seasonStats(出场/进球/助攻/零封)快抓法(2026-09-09 优化,每周刷新照此走)

背景:出场/进球/助攻/零封为一级数据,每周必刷。2026-09-09 教训:串行抓取会卡死(48队×2页串行+超时挂起,15队后停摆),必须用并发。

12.10.1 URL(关键!一页拿全)

12.10.2 速度(实测)

12.10.3 解析四坑(同12.9,务必照做)

12.10.4 匹配写回(关键:号码桥用 26-27 名册)

12.10.5 源覆盖边界