首页
/ Crawl4AI 自适应爬虫实战:统计与嵌入双策略、参数调优与知识库持久化

Crawl4AI 自适应爬虫实战:统计与嵌入双策略、参数调优与知识库持久化

2026-09-04 23:56:55作者:廉彬冶Miranda

本文基于 Crawl4AI 仓库中 docs/examples/adaptive_crawling/ 目录下的完整示例集,系统讲解 Adaptive Crawling(自适应抓取)的两种核心策略(statistical / embedding)的使用方法、全部可调参数与默认值、策略选型依据、状态持久化与断点续爬、自定义评分策略,以及知识库的 JSONL 导出/导入/合并,并结合 crawl4ai/adaptive_crawler.py 源码印证各参数的底层实现,帮助读者从“会调用 digest()”进阶到“会调参、会定制、会复用知识库”。

一、什么是自适应抓取

Crawl4AI 的自适应爬虫(AdaptiveCrawler)解决的核心问题是:抓取多少页面才算“够”,以及如何用最少的页面拿到最相关的信息。它不是一次性的单页抓取,也不是无边界的深度爬虫,而是一个带“信息觅食(information foraging)”机制的循环:

  1. 从起始 URL 出发,抓取页面并沉淀到内部知识库(knowledge base);
  2. 对每个候选链接按“预期信息增益”打分排序,每页只跟进 Top-K 链接;
  3. 每爬一批页面就重算一个 0~1 的置信度(confidence),融合覆盖率、一致性与饱和曲线;
  4. 置信度达到阈值、增益低于最小阈值或触发不相关判定后立即停止。

这套机制的数学框架见仓库根目录的 PROGRESSIVE_CRAWLING.md,官方核心文档见 docs/md_v2/core/adaptive-crawling.md,API 参考见 docs/md_v2/api/digest.md

从源码结构看(crawl4ai/adaptive_crawler.py),整个模块由四部分构成:

组件 位置 职责
CrawlState crawl4ai/adaptive_crawler.py#L27-L150 追踪已爬 URL、知识库、待爬链接、词频/文档频率、嵌入向量与语义缺口,并支持 save()/load() 持久化
AdaptiveConfig crawl4ai/adaptive_crawler.py#L153-L274 所有可调参数的 dataclass,内置 validate() 校验权重和等约束
CrawlStrategy(ABC) crawl4ai/adaptive_crawler.py#L277-L298 抽象策略基类,定义 calculate_confidence / rank_links / should_stop / update_state 四个钩子
StatisticalStrategy / EmbeddingStrategy crawl4ai/adaptive_crawler.py#L301#L615 两套内置策略的具体实现
AdaptiveCrawler crawl4ai/adaptive_crawler.py#L1292 对外入口:digest() 主循环、print_stats()export/import_knowledge_base()get_relevant_content()

示例目录(docs/examples/adaptive_crawling/)共覆盖 7 个官方示例加 1 个补充示例:

示例文件 演示内容
basic_usage.py 最简单的自适应抓取:默认统计策略、查看统计、获取最相关内容
embedding_strategy.py 嵌入策略:查询扩展、无关查询检测、语义缺口分析
embedding_vs_statistical.py 两种策略在同一组查询上的正面对比(页数、耗时、置信度)
embedding_configuration.py 嵌入策略的 6 种典型调参方案 + 参数调整指南
advanced_configuration.py 置信度阈值调优、状态持久化/断点续爬、链接选择策略、进度监控
custom_strategies.py 自定义评分策略(API 文档、学术论文、混合策略、性能优化)
export_import_kb.py 知识库 JSONL 导出、分析、导入续爬、跨项目合并
llm_config_example.py LLMConfig 对象(而非 dict)配置 OpenAI 嵌入

二、快速上手:统计策略(默认)

安装 Crawl4AI 后,最小可用示例如下(完整代码见 basic_usage.py):

python docs/examples/adaptive_crawling/basic_usage.py
import asyncio
from crawl4ai import AsyncWebCrawler, AdaptiveCrawler

async def main():
    # 初始化底层爬虫
    async with AsyncWebCrawler(verbose=True) as crawler:
        # 默认使用 statistical 策略,无需传 config
        adaptive = AdaptiveCrawler(crawler)

        # 可选:改用嵌入策略
        # from crawl4ai import AdaptiveConfig
        # config = AdaptiveConfig(strategy="embedding")
        # adaptive = AdaptiveCrawler(crawler, config)

        # 开始自适应抓取
        result = await adaptive.digest(
            start_url="https://docs.python.org/3/library/asyncio.html",
            query="async await context managers coroutines"
        )

        # 1) 打印抓取统计
        adaptive.print_stats(detailed=False)

        # 2) 获取最相关页面(top_k 控制数量)
        for i, page in enumerate(adaptive.get_relevant_content(top_k=5), 1):
            print(f"{i}. {page['url']}  score={page['score']:.2%}")

        # 3) 信息充分性判断
        print(f"Final Confidence: {adaptive.confidence:.2%}")
        print(f"Total Pages Crawled: {len(result.crawled_urls)}")
        print(f"Knowledge Base Size: {len(adaptive.state.knowledge_base)} documents")

        if adaptive.confidence >= 0.8:
            print("High confidence - can answer detailed questions")
        elif adaptive.confidence >= 0.6:
            print("Moderate confidence - can answer basic questions")
        else:
            print("Low confidence - need more information")

asyncio.run(main())

关键 API 与源码对应关系:

  • AdaptiveCrawler(crawler, config=None):第二参数可选,不传即用源码中的默认 AdaptiveConfig
  • await adaptive.digest(start_url, query):主入口(crawl4ai/adaptive_crawler.py#L1330),内部按“预取起始页 → 链接预览打分 → 批量抓取 → 更新状态 → 判断停止”循环推进,返回携带 crawled_urlsexpanded_queriessemantic_gapskb_embeddingsmetrics 等字段的结果对象;
  • adaptive.confidence / adaptive.is_sufficient / adaptive.coverage_stats:均为属性(#L1531-L1570),分别返回当前置信度、是否达到 confidence_threshold、以及覆盖/一致/饱和三项明细;
  • adaptive.state:即 CrawlState,可直接读取 knowledge_basecrawled_urls 等内部状态。

统计策略的置信度公式。源码中 StatisticalStrategy.calculate_confidence 将置信度定义为三项加权(crawl4ai/adaptive_crawler.py#L309-L326):

confidence = 0.4 × coverage + 0.3 × consistency + 0.3 × saturation

其中 coverage 衡量查询词在知识库中的覆盖程度,consistency 衡量跨文档一致性,saturation 基于 new_terms_history 判断“新词发现速度是否衰减”(即信息增益趋于饱和)。链接排序则使用 BM25 相关实现(bm25_k1=1.2bm25_b=0.75,见 #L304-L307),相关性/新颖性/权威性权重默认 0.5/0.3/0.2。整个策略不依赖 LLM 与嵌入模型,因此快且零外部依赖——这也是 README 把它作为默认策略的原因。

三、嵌入策略:语义理解、查询扩展与无关查询检测

当查询是概念性、模糊性表述(如 “concurrent programming patterns”)而非精确 API 名时,统计策略的关键词匹配会失准。嵌入策略把查询和页面都映射到向量空间,用相似度而非词面命中来判断相关性。完整示例见 embedding_strategy.py

import asyncio, os
from crawl4ai import AsyncWebCrawler, AdaptiveCrawler, AdaptiveConfig

async def main():
    config = AdaptiveConfig(
        strategy="embedding",                          # 切换到嵌入策略
        embedding_model="sentence-transformers/all-MiniLM-L6-v2",  # 默认本地模型
        n_query_variations=10,      # 查询语义扩展数量
        max_pages=15,
        top_k_links=3,
        min_gain_threshold=0.05,
        embedding_k_exp=3.0,                        # 越高要求相似度越严
        embedding_min_confidence_threshold=0.1,     # 低于该值判定“完全不相关”即停
        embedding_validation_min_score=0.4,         # 验证收敛的最低分数
    )

    # 可选:改用 OpenAI 嵌入(需要环境变量)
    if os.getenv('OPENAI_API_KEY'):
        config.embedding_llm_config = {
            'provider': 'openai/text-embedding-3-small',
            'api_token': os.getenv('OPENAI_API_KEY')
        }

    async with AsyncWebCrawler(verbose=True) as crawler:
        adaptive = AdaptiveCrawler(crawler, config)

        # TEST 1: 语义查询理解(查询被扩展成 n_query_variations 个变体)
        result = await adaptive.digest(
            start_url="https://docs.python.org/3/library/asyncio.html",
            query="concurrent programming event-driven architecture"
        )
        print(f"Original query expanded to {len(result.expanded_queries)} variations")

        # TEST 2: 无关查询检测——在 asyncio 文档上问“怎么做巧克力曲奇”
        adaptive = AdaptiveCrawler(crawler, config)   # 每个查询用全新实例
        result = await adaptive.digest(
            start_url="https://docs.python.org/3/library/asyncio.html",
            query="how to bake chocolate chip cookies"
        )
        if result.metrics.get('is_irrelevant', False):
            print(f"Stopped after just {len(result.crawled_urls)} pages")
            print(f"Reason: {result.metrics.get('stopped_reason', 'unknown')}")

        # TEST 3: 语义缺口分析
        adaptive = AdaptiveCrawler(crawler, config)
        result = await adaptive.digest(
            start_url="https://realpython.com",
            query="python decorators advanced patterns"
        )
        print(f"Semantic gaps: {len(result.semantic_gaps)}")
        print(f"KB embeddings shape: {result.kb_embeddings.shape if result.kb_embeddings is not None else 'None'}")
        print(f"avg_best_similarity: {result.metrics.get('avg_best_similarity', 0):.3f}")
        print(f"coverage_score: {result.metrics.get('coverage_score', 0):.3f}")
        print(f"validation_confidence: {result.metrics.get('validation_confidence', 0):.2%}")

asyncio.run(main())

运行 python docs/examples/adaptive_crawling/embedding_strategy.py 即可复现。三个演示分别验证嵌入策略的三大能力:

  1. 查询扩展map_query_semantic_space() 会生成 n_query_variations 个语义变体(crawl4ai/adaptive_crawler.py#L726),用一组点表示查询的“语义空间”,而不是只依赖原始句子;
  2. 无关查询检测:若最佳相似度低于 embedding_min_confidence_threshold(默认 0.1),策略判定查询与站点内容不相关并提前停止,result.metrics['is_irrelevant'] 置为 True,避免把预算浪费在注定无果的抓取上;
  3. 语义缺口(semantic gaps)find_coverage_gaps() 基于查询点集与知识库嵌入的距离矩阵,找出“查询想要但知识库还没有”的区域(#L841),并可用 alpha shape 计算覆盖包络(compute_coverage_shape#L804)。

嵌入模型来源有两条路径:

  • 本地模型:默认 embedding_model="sentence-transformers/all-MiniLM-L6-v2"(见 AdaptiveConfig 定义,#L180),需要安装 sentence-transformers
  • API 模型:通过 embedding_llm_config 传入 dict 或 LLMConfig 对象,如 'provider': 'openai/text-embedding-3-small'。仓库中还提供了一个使用 LLMConfig 对象的完整写法 llm_config_example.py
from crawl4ai import LLMConfig

openai_llm_config = LLMConfig(
    provider='openai/text-embedding-3-small',
    api_token=os.getenv('OPENAI_API_KEY'),
    temperature=0.7,
    max_tokens=2000
)
config = AdaptiveConfig(
    strategy="embedding",
    max_pages=10,
    embedding_llm_config=openai_llm_config,   # 支持 LLMConfig 实例
    embedding_k_exp=4.0,
    n_query_variations=12
)

四、策略选型:统计 vs 嵌入的正面对比

embedding_vs_statistical.py 用同一组 AdaptiveConfigmax_pages=20, top_k_links=3, min_gain_threshold=0.05)在三类查询上分别跑两种策略,并输出页数、耗时、置信度、词面覆盖率与语义缺口数的量化对比:

test_cases = [
    {   # 精确技术词:统计策略的主场
        'url': 'https://docs.python.org/3/library/asyncio.html',
        'query': 'asyncio.create_task event_loop.run_until_complete'
    },
    {   # 概念性查询:需要语义理解
        'url': 'https://docs.python.org/3/library/asyncio.html',
        'query': 'concurrent programming patterns'
    },
    {   # 模糊查询
        'url': 'https://realpython.com',
        'query': 'python performance optimization'
    },
]

对比维度包括:crawled_urls 数量差异(谁用更少页面达标)、耗时倍率、置信度差值,以及嵌入策略特有的 expanded_queries 数量与 semantic_gaps 数量;统计策略还可检查 result.term_frequencies 计算“查询词命中率”。

官方 README 给出的选型速查表(与示例脚本结尾打印的结论一致):

使用统计策略(默认)的场景

  • 抓取对象是技术文档、结构良好的站点;
  • 查询包含具体术语或代码(函数名、API 名);
  • 速度优先,预算敏感;
  • 环境无 LLM/嵌入 API 访问条件(纯本地、零额外依赖)。

使用嵌入策略的场景

  • 查询是概念性或模糊表述(如 “performance optimization”);
  • 需要超越精确匹配的语义理解;
  • 需要自动识别无关内容并尽早止损;
  • 内容来源多样、措辞与查询词汇差异大。

运行 python docs/examples/adaptive_crawling/embedding_vs_statistical.py 即可在你的目标站点上复现这类 A/B 对比,把“选哪种策略”从经验判断变成数据判断。

五、参数调优指南:嵌入策略的 6 种典型配置

embedding_configuration.py 给出了面向不同目标的 6 组配置,全部参数均可在 AdaptiveConfig 中找到(定义与校验逻辑见 crawl4ai/adaptive_crawler.py#L153-L256):

# 1. 严格覆盖(研究/学术场景):宁可多爬,也要覆盖全面
config_strict = AdaptiveConfig(
    strategy="embedding",
    max_pages=20,
    embedding_k_exp=5.0,                 # 默认 1.0,越高相似度要求越严
    embedding_coverage_radius=0.15,      # 默认 0.2,越小“已覆盖”判定越严
    embedding_validation_min_score=0.6,  # 默认 0.3,验证门槛提高
    n_query_variations=15,               # 默认 10,更多变体提升覆盖
)

# 2. 快速探索(Quick Overview):放宽一切阈值,尽快收敛
config_fast = AdaptiveConfig(
    strategy="embedding",
    max_pages=10,
    top_k_links=5,                        # 每页跟进更多链接
    embedding_k_exp=1.0,                  # 低 k 更宽容
    embedding_min_relative_improvement=0.05,  # 低于默认 0.1,更早停止
    embedding_quality_min_confidence=0.5,    # 降低对外展示置信度的下限
    embedding_quality_max_confidence=0.85,
    n_query_variations=5,                  # 减少变体提速
)

# 3. 无关查询检测优先:激进地尽早停下
config_irrelevance = AdaptiveConfig(
    strategy="embedding",
    max_pages=5,
    embedding_min_confidence_threshold=0.2,   # 高于默认 0.1,更敏感的无关判定
    embedding_k_exp=5.0,
    embedding_min_relative_improvement=0.15,  # 改进缓慢即停
)

# 4. 高质量知识库:重去重、重验证
config_quality = AdaptiveConfig(
    strategy="embedding",
    max_pages=30,
    embedding_overlap_threshold=0.75,       # 低于默认 0.85,更激进去重
    embedding_validation_min_score=0.5,
    embedding_quality_scale_factor=1.0,     # 线性质量映射
    embedding_k_exp=3.0,
    embedding_nearest_weight=0.8,          # 更聚焦最佳匹配
    embedding_top_k_weight=0.2,            # 与上一项之和必须为 1(validate 强制)
)

# 5. OpenAI 嵌入:模型质量更高,可配合更严参数
config_openai = AdaptiveConfig(
    strategy="embedding",
    max_pages=10,
    embedding_llm_config={
        'provider': 'openai/text-embedding-3-small',
        'api_token': os.getenv('OPENAI_API_KEY')
    },
    embedding_k_exp=4.0,
    n_query_variations=12
)

每组配置跑完后脚本打印 Pages crawled / Final confidence / Stopped reason,若命中无关判定还会打印 ⚠️ Query detected as irrelevant!

关键参数速查表(示例文件注释 + AdaptiveConfig 源码默认值合并;注意示例注释中个别“默认值”以源码 dataclass 为准):

参数 源码默认值 调大/调小的效果
embedding_k_exp 1.0(#L196 指数衰减因子,相似度映射为 score = exp(-k_exp × distance)。1~2 更宽容、收敛更快;4~5 更严格、精确度更高
embedding_coverage_radius 0.2 查询点被判定“已覆盖”的距离半径;0.1~0.15 要求更近匹配,0.25~0.3 接受更宽泛匹配
n_query_variations 10 查询语义变体数量;5~7 快但覆盖弱,15~20 覆盖好但更慢
embedding_min_confidence_threshold 0.1 无关判定阈值;0.15~0.2 激进止损,0.05 则几乎不判无关
embedding_validation_min_score 0.3 收敛验证门槛;0.5~0.6 要求强验证,0.2 允许更早停
embedding_min_relative_improvement 0.1 每批最小相对改进,越小越“耐心”,越大越早停
embedding_overlap_threshold 0.85 与知识库相似度过高的链接会被降权去重;调低更激进
embedding_nearest_weight / embedding_top_k_weight 0.7 / 0.3 混合打分权重(最近邻 vs Top-K 均值),validate() 强制两者之和为 1
embedding_quality_min/max_confidence / scale_factor 0.7 / 0.95 / 0.833 内部控制分到“用户可见置信度”的映射,只影响展示口径
link_preview_timeout 5.0 秒 链接预览抓取超时,影响打分质量与速度的平衡

调参经验(来自示例脚本末尾的 Parameter Tuning Guide):

  • 研究类任务:高 k_exp、更多变体、严格验证;
  • 探索类任务:低 k_exp、少变体、放松阈值;
  • 质量优先:重点调 overlap_threshold 与验证分数;
  • 速度优先:减少变体数、提高 min_relative_improvement

六、高级配置:阈值、断点续爬与链接选择策略

advanced_configuration.py 演示了四个进阶主题,对两种策略均适用(其参数来自 AdaptiveConfig 的通用部分,#L153-L177)。

6.1 置信度阈值三档配置

confidence_threshold 决定“何时认为信息足够”,默认 0.7;min_gain_threshold 控制“继续爬取的最低信息增益”,默认 0.1:

# 高精度(穷尽式抓取):高置信度要求 + 放宽增益门槛
high_precision_config = AdaptiveConfig(
    confidence_threshold=0.9,
    max_pages=50,
    top_k_links=5,
    min_gain_threshold=0.02      # 增益再低也继续,直到置信度拉满
)

# 均衡(默认场景)
balanced_config = AdaptiveConfig(
    confidence_threshold=0.7,
    max_pages=20,
    top_k_links=3,
    min_gain_threshold=0.05
)

# 快速探索:低置信度即可 + 严格页数上限
quick_config = AdaptiveConfig(
    confidence_threshold=0.5,
    max_pages=10,
    top_k_links=2,
    min_gain_threshold=0.1
)

对比运行时可同时观察 len(result.crawled_urls)adaptive.confidenceadaptive.coverage_stats['coverage'] 三个指标,验证“阈值—页数—置信度”之间的权衡关系。

6.2 状态持久化与断点续爬

AdaptiveConfig 内置 save_state / state_path 两项持久化参数(默认 save_state=False)。底层由 CrawlState.save()/load() 实现 JSON 序列化,包括词频表、待爬链接、以及嵌入向量(numpy 数组转 list 存储,#L53-L110)。示例流程是“先以 max_pages=5 人为模拟中断,再用 resume_from 从存档继续”:

state_file = "crawl_state_demo.json"

# 第一阶段:受限页面数,模拟中断
interrupt_config = AdaptiveConfig(
    confidence_threshold=0.8,
    max_pages=5,
    save_state=True,
    state_path=state_file
)
adaptive = AdaptiveCrawler(crawler, config=interrupt_config)
result1 = await adaptive.digest(
    start_url="https://docs.python.org/3/",
    query="exception handling try except finally"
)

# 第二阶段:从存档恢复,提高页数上限继续爬
resume_config = AdaptiveConfig(
    confidence_threshold=0.8,
    max_pages=20,
    save_state=True,
    state_path=state_file
)
adaptive2 = AdaptiveCrawler(crawler, config=resume_config)
result2 = await adaptive2.digest(
    start_url="https://docs.python.org/3/",
    query="exception handling try except finally",
    resume_from=state_file          # 关键参数:加载已爬 URL 与知识库
)

digest()resume_from 参数在 crawl4ai/adaptive_crawler.py#L1330 的签名中,加载后会跳过 crawled_urls 中已存在的链接,直接基于既有知识库继续增益计算。相关测试可参考 tests/adaptive/test_adaptive_crawler.py

6.3 链接选择策略:保守 vs 激进

top_k_links(每页跟进链接数)与 min_gain_threshold 的组合刻画了爬虫的“分支风格”:

conservative_config = AdaptiveConfig(
    confidence_threshold=0.7,
    max_pages=15,
    top_k_links=1,                  # 每页只跟最优链接 → 深而窄
    min_gain_threshold=0.15         # 高增益门槛
)

aggressive_config = AdaptiveConfig(
    confidence_threshold=0.7,
    max_pages=15,
    top_k_links=10,                 # 每页跟 10 个链接 → 宽而浅
    min_gain_threshold=0.01
)

脚本会统计两种模式下的总页数、唯一域名数、最大深度,以及 new_terms_history 的饱和趋势(新词发现数递减即趋于饱和),帮助你按站点结构选择分支策略。

6.4 进度监控与知识导出

result = await adaptive.digest(
    start_url="https://httpbin.org",
    query="http methods headers"
)
adaptive.print_stats(detailed=True)                    # 完整统计
adaptive.export_knowledge_base("knowledge_export_demo.jsonl")  # 导出 JSONL

print_stats(detailed=True) 输出覆盖/一致/饱和明细与历史曲线(实现见 #L1570);export_knowledge_base() 将知识库逐行写为 JSONL(#L1781)。

七、自定义策略:领域评分与混合打分

内置策略是通用实现;针对特定领域(API 文档、学术论文等),可以按 custom_strategies.py 的思路写领域评分类。该示例定义了三个层次的定制方式:

7.1 链接级评分:API 文档策略

from crawl4ai.adaptive_crawler import CrawlState, Link

class APIDocumentationStrategy:
    def __init__(self):
        self.api_keywords = {'endpoint', 'request', 'response', 'parameter',
                             'authentication', 'header', 'curl', 'python', ...}
        self.valuable_patterns = [r'/api/', r'/reference/', r'/endpoints?/', ...]
        self.avoid_patterns = [r'/blog/', r'/news/', r'/about/', ...]

    def score_link(self, link: Link, query: str, state: CrawlState) -> float:
        score = 1.0
        url = link.href.lower()
        if any(re.search(p, url) for p in self.valuable_patterns):
            score *= 2.0                    # API 路径加权
        if any(re.search(p, url) for p in self.avoid_patterns):
            score *= 0.1                    # 博客/新闻降权
        if link.text:
            kw_count = sum(1 for kw in self.api_keywords
                           if kw in link.text.lower())
            score *= (1 + kw_count * 0.2)    # 锚文本关键词加成
        depth = url.count('/') - 2
        if depth <= 3:    score *= 1.5       # 浅层 URL 多为概览页
        elif depth > 6:   score *= 0.5
        return score

接入方式是 monkey-patch AdaptiveCrawler._rank_links

original_rank_links = adaptive._rank_links

def custom_rank_links(links, query, state):
    scored = [(link, api_strategy.score_link(link, query, state)) for link in links]
    scored.sort(key=lambda x: x[1], reverse=True)
    return [link for link, _ in scored[:config.top_k_links]]

adaptive._rank_links = custom_rank_links

策略类还提供 calculate_api_coverage(),基于正则(GET /curl -params: 等模式)统计知识库中 endpoint/example/parameter 三类内容的覆盖率,得到领域化的“知识完备度”指标。

7.2 内容级评分与混合策略

ResearchPaperStrategy.calculate_academic_relevance() 演示了内容级打分:学术关键词命中、引用密度([1](Author 2024)doi: 模式)、查询词与摘要/结论区段的共现,最终得分截断在 2.0。HybridStrategy 则展示如何按权重组合多个策略(API 0.7 + 研究 0.3),对 get_relevant_content(top_k=5) 返回的每篇文档做加权评分。

7.3 性能优化策略

PerformanceOptimizedStrategy 演示了两个实用技巧:域名级限额(单域超过 5 页即跳过)与域名移动平均评分(低于 0.3 的域不再访问),并输出 pages/sec 与“每页置信度贡献”(confidence / pages)两个效率指标,用于评估策略的实际吞吐。

需要说明的是:CrawlStrategy 抽象基类(calculate_confidence / rank_links / should_stop / update_state#L277-L298)是策略扩展的“正规”入口,示例采用 patch 方式是为了演示轻量定制;若需长期维护的自定义策略,从源码结构看更稳妥的做法是继承 CrawlStrategy 并覆盖四个钩子方法。

八、知识库的导出、分析与跨项目合并

export_import_kb.py 展示了知识库作为可复用资产的完整生命周期,分四个阶段:

阶段 1:构建知识库

对同一 AdaptiveCrawler 实例连续调用两次 digest()(不同起始页、不同查询),知识在 state.knowledge_base 中累积:

adaptive = AdaptiveCrawler(crawler)
await adaptive.digest(start_url="https://httpbin.org",
                      query="http methods headers status codes")
await adaptive.digest(start_url="https://httpbin.org/anything",
                      query="rest api json response request")
adaptive.export_knowledge_base("web_tech_knowledge.jsonl")

阶段 2:离线分析 JSONL

导出文件为 JSONL,每行一篇文档,包含 urlcontent(markdown)、linksquerymetadata 等字段(序列化逻辑见 AdaptiveCrawler._crawl_result_to_export_dictcrawl4ai/adaptive_crawler.py#L1808)。可用标准 JSON 解析直接做统计:

documents = [json.loads(line) for line in open(kb_path)]
# 统计总字符数、平均每文档长度、按域名分布

阶段 3:导入续爬

在新实例上 import_knowledge_base() 后,已导入的 URL 自动进入 crawled_urls(后续 digest 会跳过),知识库文档参与增益计算:

adaptive = AdaptiveCrawler(crawler)
await adaptive.import_knowledge_base("web_tech_knowledge.jsonl")
print(f"Imported {len(adaptive.state.knowledge_base)} documents")

# 用新查询继续扩展
await adaptive.digest(
    start_url="https://httpbin.org/status/200",
    query="error handling retry timeout"
)
adaptive.export_knowledge_base("web_tech_knowledge_extended.jsonl")

阶段 4:跨项目合并

两个独立项目分别导出各自的知识库后,在第三个实例上依次 import_knowledge_base(project_a_kb)import_knowledge_base(project_b_kb),即可得到合并知识库并再次导出,实现知识资产的共享与复用。示例的 finally 块统一清理了生成的 .jsonl 文件。

九、环境要求与延伸阅读

按示例目录 README 的 Requirements 一节,运行环境要求为:

  • 已安装 Crawl4AI(AsyncWebCrawler 依赖 Playwright,首次使用需安装浏览器);
  • 嵌入策略 + 本地模型:需要 sentence-transformers
  • 嵌入策略 + OpenAI:设置 OPENAI_API_KEY 环境变量。

全部示例均可直接运行:

python docs/examples/adaptive_crawling/basic_usage.py
python docs/examples/adaptive_crawling/embedding_strategy.py
python docs/examples/adaptive_crawling/embedding_vs_statistical.py

延伸阅读与验证资源:

十、小结

场景 推荐策略 关键参数
技术文档 + 精确术语 + 速度优先 statistical(默认,零额外依赖) confidence_thresholdmin_gain_thresholdtop_k_links
概念性/模糊查询、需语义理解 embedding + 本地 sentence-transformers n_query_variationsembedding_k_expembedding_coverage_radius
需自动止损无关查询 embedding embedding_min_confidence_threshold 调高至 0.15~0.2
研究级完备知识库 embedding + 严格验证 k_exp、高 validation_min_score、低 overlap_threshold
任务中断/预算恢复 任意 + 持久化 save_state=Truestate_pathdigest(resume_from=...)
领域定制(API/学术站点) 自定义评分 继承 CrawlStrategy 或 patch _rank_links

自适应抓取的价值在于把“爬多少、往哪爬、何时停”从人工经验变成可配置、可量化、可恢复的算法决策:统计策略以 BM25 词频模型保证速度与零依赖,嵌入策略以向量空间覆盖与缺口分析换取语义鲁棒性,而 AdaptiveConfig 中每一项阈值都能在源码的 validate() 约束下被精确控制。掌握本文的示例路径与参数表后,你可以直接在自己的目标站点上复现对比实验,并按第九节的资源继续深入。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.79 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
988
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384