Crawl4LLM 大规模实战:从 10k 种子爬到 2000 万文档的经验与教训 📅 2026/8/21 15:36:08 Crawl4LLM 大规模实战从 10k 种子爬到 2000 万文档的经验与教训【免费下载链接】Crawl4LLMOfficial repository for Craw4LLM: Efficient Web Crawling for LLM Pretraining项目地址: https://gitcode.com/gh_mirrors/cr/Crawl4LLMCrawl4LLM 是一个面向 LLM 预训练的高效网页爬虫工具出自同名论文《Crawl4LLM: Efficient Web Crawling for LLM Pretraining》。它的目标朴素却硬核只给 10k 个种子文档就能从 ClueWeb22 语料库中定向爬取 2000 万篇高质量文档为预训练提供干净的数据来源。这篇文章会带你完整走一遍大规模爬取实战流程并分享那些踩过的坑和总结出的经验教训。Crawl4LLM 到底解决了什么问题大模型预训练需要海量文本而网络是最大的文本矿场。但「能爬到」和「值得爬」是两回事——随机爬取会带回大量广告、模板页和低质内容。Crawl4LLM 的思路是用质量评分器给每个候选文档打分再用优先级队列保证每次都扩展最高质量的页面让爬取预算花在刀刃上。整体架构从 10k 种子到 2000 万文档的核心流程整个系统可以拆成四层理解它们你就能看懂后续所有配置模块职责对应文件数据访问层读取 ClueWeb22 的正文、出链、入链corpus_interface.py评分层给文档打质量分长度、fastText、入链数等document_rater.py爬取调度层维护优先级队列与 visited 集合crawler.py入口与工具参数解析、主循环、日志与可视化crawl.py、utils.py、wandb_logger.py爬取本质是一个带质量优先级的 BFS种子入队 → 每次弹出评分最高的 10k 篇 → 记录结果 → 找出它们的出链 → 给新文档打分入队 → 直到爬满 2000 万篇。主循环逻辑在crawl.py的main()中crawl.py#L171-L269代码非常直白pop_from_queue、find_outinks、get_scores_for_docs、put_into_queue四个动作循环往复。第一步准备 10k 种子文档种子质量决定爬取起点。项目自带的seed.txt恰好有 10000 行每行是一个 ClueWeb22 文档 ID例如clueweb22-en0041-36-03476 clueweb22-en0015-72-05075代码会从种子中随机采样num_selected_docs_per_iter篇作为初始队列crawl.py#L213-L226所以种子数量必须不少于每轮选择数。如果你想自定义领域比如只要科技类内容替换这个文件即可。第二步关键配置解读——2000 万文档怎么爬爬取完全由 YAML 配置驱动官方示例就是「10k 种子爬 20M 文档」的实战配置README 中 Crawl4LLM 一节。逐项拆解配置项示例值含义seed_docs_fileseed.txt10k 种子文档文件max_num_docs20000000目标爬取总量 2000 万num_selected_docs_per_iter10000每轮弹出文档数num_workers16并行进程数selection_methoddclm_fasttext_score最终排序依据orderdesc降序优先高质量save_state_every正数定期保存断点wandbtrue开启实验监控其中selection_method决定优先级队列的排序键而DocumentAnnotation.set_compare_method在corpus_interface.py中实现corpus_interface.py#L18-L34desc模式下分数越高的文档越先被弹出扩展。这就是「好文档会带出更多好文档」的核心机制。第三步质量评分器的选型rating_methods支持多评分器并行打分最终排名由selection_method指定的那个决定。项目内置四类length文档长度直接取len(doc.text)简单但有效document_rater.py#L76-L87fasttext_scoreDCLM fastText 质量分加载 DCLM 的 fastText 分类器把文本预测为「高质量/低质量」返回高质量概率document_rater.py#L160-L219。官方推荐用它做主排序random_score随机基线用于对比实验inlink_count入链数统计指向该文档的链接数近似网页权威度document_rater.py#L90-L128。实战经验fastText 评分需要读取文档正文这意味着每轮都要拉取大量文档内容IO 压力远大于只看链接的基线。如果机器内存吃紧可以用max_num_in_mem_docs默认 100 万把打分过程分片处理防止一次性载入过多文档crawler.py#L141-L164。第四步从爬取到预训练数据的完整链路爬完后文档 ID 会按轮次写入output_dir每轮一个iter_N.docids.txt。接下来用fetch_docs.py把 ID 换回正文python fetch_docs.py --input_dir 文档ID目录 --output_dir 正文目录 --num_workers 16它会逐行读取 ID通过ClueWeb22Api.get_clean_text取出正文并写成 JSONLfetch_docs.py#L12-L27之后就能喂给 DCLM 等框架做预训练与评测。想看单篇文档长什么样用access_data.py即可快速调试access_data.py#L14-L25。大规模爬取的经验与教训1. SSD 是硬性要求别用机械盘硬扛README 里特意用 IMPORTANT 标注ClueWeb22 数据必须放 SSD。每轮要随机访问海量 gzip 文件机械盘随机寻道会直接把吞吐拖垮。这是最容易忽略、也最致命的性能瓶颈。2. 务必开启断点续爬2000 万文档不是一晚上能跑完的。设置save_state_every: 400爬虫会定期把优先级队列和 visited 集合序列化到state_NNNNNN.pklcrawler.py#L171-L178崩溃后通过--resume_from_state恢复init_or_resume_state甚至会检测评分器是否变化、必要时重算队列分数crawler.py#L180-L213。不设断点 随时重来。3. 用 wandb 盯住扩展率开启wandb: true后每轮会记录total_outlinks、expansion_ratio、unvisited_ratio等指标crawler.py#L104-L112。当扩展率骤降时说明高质量页面快爬完了此时可以考虑调低max_num_docs或换评分策略避免把预算浪费在垃圾链接上。4. 先用rate模式做小规模验证crawl.py支持rate模式crawl.py#L206-L208配合utils.py的eval_and_plot可以对种子文档跑各评分器输出评分相关性热力图utils.py#L25-L89提前确认不同评分器是否「英雄所见略同」再决定最终排序策略。5. 多进程数量要贴合机器num_workers: 16是官方示例但不是越大越好。find_outinks和get_scores_for_docs都用multiprocessing.Pool并行crawler.py#L83-L90、L121-L128进程数超过 CPU 核数反而增加调度开销fastText 评分还会在每个 worker 里各加载一份模型内存占用按进程数翻倍。写在最后Crawl4LLM 用不到几个 Python 文件就完成了「质量引导的大规模爬取」这个看似复杂的任务10k 种子 → 质量评分 → 优先级扩展 → 2000 万文档。它的核心思想值得所有做预训练数据工程的团队借鉴——爬虫的终点不是「量」而是「质量」。如果你的目标是自建高质量预训练语料从这份代码出发把种子换成你的领域页面、把评分器换成你的质量模型就是一条非常清晰的实战路径。【免费下载链接】Crawl4LLMOfficial repository for Craw4LLM: Efficient Web Crawling for LLM Pretraining项目地址: https://gitcode.com/gh_mirrors/cr/Crawl4LLM创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考