Project Workflow

CC Category 项目运作流程

为 Google Content Categories v2 的 1091 个网站分类,通过深度搜索引擎挖掘找到每个分类最具代表性的 20 个域名。不是搜"谁在写文章",而是搜"文章里推荐了谁"。

1,091 叶子分类
27 顶级分类
21,239 总 sites
13,352 独立域名
9 迭代轮次
01 / Core Insight

两层搜索架构

直接提取搜索结果页的域名,拿到的是"写评测文章的网站"。深入文章内容后,才能拿到真正属于该分类的网站。

搜索层

SERP API 返回的搜索结果域名 — 这些是"讨论者"

pcmag.com   similarweb.com
techradar.com   g2.com
写评测的站,不是分类本身 ✗

深入层

从文章内容中提取被推荐的域名 — 这些是"被讨论者"

crunchyroll.com   funimation.com
myanimelist.net   vrv.co
真正的分类代表网站 ✓
02 / Algorithm

单分类深度搜索流程

每个分类经过 query 生成、SERP 搜索、文章抓取、域名提取、7 层过滤、交叉排名,最终输出 Top 20 域名。

分类输入
/Arts & Entertainment/Online Video/Anime & Manga
Query 生成器 category_to_queries()
根据分类类型生成 3 个查询变体。Finance 子树用比较站语义,通用类目用 "best X websites / top X sites / popular X platforms"
3 queries
Q1 SERP API
50 results
concurrent_pagination
Q2 SERP API
50 results
concurrent_pagination
Q3 SERP API
50 results
concurrent_pagination
~150 URLs
URL 去重 + 选 Top 12 MAX_ARTICLES=12
合并 3 个 query 的搜索结果,去重后按排名选前 12 篇文章 URL。SOURCE_DOMAINS 直接过滤掉评测站。
12 URLs
并发抓取文章 HTML 12 concurrent
HTTP GET 抓取文章全文 HTML,BeautifulSoup 解析。超时 10s 跳过。
HTML
域名提取 read_article()
从文章内容的 <a href> 中提取外链域名,记录每个域名被哪些文章引用。
raw domains
7 层过滤管道 is_target_domain(d, vertical, category)
精确黑名单 → SOURCE 黑名单 → 归一化 → TLD 校验 → JS 片段正则 → CDN/Infra 模式 → GOV 垂直白名单 → R8 上下文感知 NOISE
clean domains
交叉排名
Source 文章域名:被 ≥2 篇不同文章引用才保留(自我推荐去重)
非 Source 域名:被 ≥1 篇文章引用即保留
按引用频次降序排列
输出 Top 20 域名
写入 progress.json,定期同步飞书文档
Key Insight

R6 的教训:真正的瓶颈往往是参数级别的。SERP 从 10→50、文章从 8→12,什么算法都没改就完美收敛了。改算法之前先问:是不是数据喂少了?

03 / Filter Pipeline

7 层过滤管道

每一层只解决一类噪音,后加的层不改前面的逻辑。出了问题能精确定位是哪一层的锅。

L1 NOISE_DOMAINS 精确黑名单
搜索引擎、社交平台、CDN、广告追踪、短链、跨垂直通用品牌
tumblr.com · chatgpt.com · statista.com · eepurl.com
L2 SOURCE_DOMAINS 角色排除
评测/榜单类站 — "写文章的人"不是"答案"
pcmag.com · similarweb.com · techradar.com · condenast.com
L3 normalize_domain 归一化
lowercase + 剥 www. 前缀,保证同一实体不因表达不同而重复计入
www.Netflix.COM → netflix.com
L4 VALID_TLDS 校验
500+ TLD 白名单,拦截被 BeautifulSoup 误抽的非域名字符串
profile.firstname.substr → .substr 不是合法 TLD → 拦截
L5 JS_FRAGMENT_RE 代码片段
正则识别 JS 模板代码中的变量访问路径
profile.email · config.host · user.name
L6 CDN / Infra 模式
基础设施域名通配:数字前缀(static1. / img2.)、云托管后缀、CDN 子域
*.netlify.app · *.s3.amazonaws.com · cdn.example.com
L7 GOV 垂直白名单 + R8 上下文感知
gov/edu 域名默认全挡,按垂直放行(如 nih.gov 只在 Health/Science 出现)。R8 新增 97 个跨垂直噪音,但 /Other 子叶豁免。
nih.gov + Health → 放行    nih.gov + Finance → 拦截
Design Principle

噪音不是实体的固有属性,是实体与上下文的关系。同一个 cnn.com 在 /News/Other 是信号,在 /Programming 是噪音。黑名单要感知上下文。

04 / Methodology

迭代收敛协议

永远不要第一次就跑全量。先采样 50 跨垂直暴露问题,迭代收敛后再上全量 1091。

PHASE 1

分层采样

27 个垂直各至少 1 个 + 加压脏域名高发类目(Health/Finance/Shopping),生成 sample50.txt

PHASE 2

小批量跑批

用 deep_worker.py --list sample50.txt 跑 50 个分类,存入 progress.json

PHASE 3

自动检测

noise_candidates.py 8 信号打分,输出 Red/Yellow/Green 嫌疑报告

PHASE 6

重置重跑 Sample

50 个分类全部重置为 pending,用新 filter 重新跑一遍,对比收敛指标

PHASE 5

回归测试

用新 filter 过旧数据,统计挡了什么、误伤了什么。确认"所有被挡均为合规清扫"

PHASE 4

人工决策 + 修 Filter

对嫌疑报告逐条拍板(A 挡/B 保留/C 改算法),修改后跑单元测试

收敛判定

avg ≥ 19 / min ≥ 10 / 满 20 率 ≥ 90% / 0 域名分类 = 0 / noise_candidates 嫌疑无新增?

未收敛

回到 Phase 3 继续迭代
(R1→R7.5 共迭代 8 轮)

已收敛

上全量 1091
全量跑完后再做一次 noise 检测进入下一轮

Safety Protocol

任何算法改动必须先在 3-5 个代表性分类 micro-bench(含 niche 类目)。候选数下降 >50% 立即回滚。但注意:micro-bench 单次抽样不能完全代表 production,SERP 方差 ±20% 是常态。

05 / Advanced

跨版本最优拼接 — Smart Merge

不选版本,选最优结果。对每个分类取历史 5 个版本里的最优,但加污染率检查。

5 个历史 progress.json 备份
R7.5 baseline / R8 一次 / R8 二次 / R9 v1 / R9 v2
对每个分类取历史最优 count per-item best
比较 current 与所有历史版本,找到 count 最大的那个版本的 sites 列表
污染率检查 quality gate
历史最优的 sites 列表里,有多少会被当前最严 NOISE 规则挡掉?
≤20% Accept
清洗后回退(剔除 NOISE sites,保留干净部分)
31 cats accepted
>20% Reject
保留 current 版本(宁缺毋滥,不引入脏数据)
5 cats rejected
06 / Evolution

9 轮迭代收敛轨迹

从 R1 的单分类验证到 R9 的全量交付,每一轮解决一类问题,逐步收敛。

R1

初版 NOISE 单分类

从 Selenium+Startpage 切到内部 SERP,扩第一批噪音黑名单,normalize_domain 上线

R2

NOISE 第二轮 + 子域归并 9 cats

扩 INFRA_SUFFIX_PATTERNS(20 个云存储/静态托管后缀),回归旧 done 分类全部重置

R3

压测工具上线 tooling

sample_50.py 分层采样 + noise_candidates.py 自动检测器 + deep_worker --list 参数

R4

50 分类压测 + Bug 三连修 50 cats

修 www. 归一化 bug、JS 代码片段误抽 bug、GOV 垂直白名单机制上线

956sites
19.1avg
44/50≥18
R5

Webby 污染 + stem 通配 + Finance query 50 cats

NOISE_DOMAIN_PATTERNS 上线(glamour/vogue stem 通配),FINANCE_COMPARE_LEAVES 金融 query 重写

946sites
18.9avg
48done
R6

治本算法灾难 + 全面回滚 DISASTER

引入"n_citing≥2"算法(要求被 ≥2 篇文章引用),90% 域名天然只被 1 篇引用 → 数据崩盘。完全回滚到 R5。

200sites
4.0avg
14= 0
R7

完美收敛:SERP 翻页 + MAX_ARTICLES 升 PERFECT

找到真正瓶颈:SERP 10→50 + MAX_ARTICLES 8→12。不改算法,参数调优。

993sites
19.9avg
50/50done
R7.5

噪音一次性清扫 → 上全量 1091 cats

47 个跨垂直噪音清扫后上全量 1091。4h1min 跑完,1067 done + 21,132 sites。

R8

全量级 NOISE + /Other 豁免 context-aware

新增 97 个 NOISE 域 + 2 个 stem。引入上下文感知过滤:/Other 子叶豁免 R8 NOISE,避免误伤兜底类目。

21,140sites
1066done
R9

VERTICAL_WHITELIST + Smart Merge FINAL

加性白名单策略治理 4 个硬骨头。Smart Merge 跨版本拼接历史最优 + 污染率检查。

21,239sites
1072done
13,352unique domains