ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Crawl4AI 0.4.0 版本解析:PruningContentFilter 无监督内容过滤与 User-Agent 生成器实战

Crawl4AI 0.4.0 版本解析:PruningContentFilter 无监督内容过滤与 User-Agent 生成器实战 Crawl4AI 0.4.0 版本解析PruningContentFilter 无监督内容过滤与 User-Agent 生成器实战【免费下载链接】crawl4ai Crawl4AI: Open-source LLM Friendly Web Crawler Scraper. Dont be shy, join here: https://discord.gg/jP8KfhDhyN项目地址: https://gitcode.com/GitHub_Trending/craw/crawl4aiCrawl4AI 0.4.02024 年 12 月 1 日发布是内容抽取能力的一次重要升级它引入了基于 HTML 节点评分的无监督过滤策略PruningContentFilter增强了面向查询的有监督过滤器BM25ContentFilter并新增了可定制、可随机的 User-Agent 生成器。读完本文你可以掌握两种内容过滤器的适用场景与参数配置、PruningContentFilter的评分剪枝原理以及通过BrowserConfig的user_agent_mode实现请求指纹多样化的方法。一、0.4.0 版本总览根据 0.4.0 发布说明该版本的关键亮点包括PruningContentFilter新增的无监督内容过滤策略基于文本密度、链接密度等指标对 HTML 节点进行评分和剪枝自动保留页面中最有价值的内容部分User-Agent 生成器新增 User-Agent 生成工具解决兼容性问题支持可定制的 UA 字符串默认对每个请求随机化 UA 以增加多样性线程安全增强为多线程/多协程并行处理环境增加了更完善的线程锁机制保证多任务运行的一致性和稳定性过滤策略矩阵完善用户可同时使用PruningContentFilter无监督抽取和BM25ContentFilter基于用户查询的有监督过滤且BM25ContentFilter增强了处理页面标题、meta 标签和描述的能力使文本块分类与聚类更有效文档与测试同步更新示例和教程更新以推广两种过滤器的配合使用并新增PruningContentFilter单元测试、扩展BM25ContentFilter的边界用例覆盖。发布说明同时指出PruningContentFilter在当时仍处于实验性开发阶段欢迎用户反馈以继续完善。需要说明的是当前仓库版本为 0.9.0见 crawl4ai/version.py以下所有实现细节均基于当前代码库核实0.4.0 引入的核心类在当前版本中依然可用。二、内容过滤架构RelevantContentFilter 基类在 crawl4ai/content_filter_strategy.py 中三种过滤策略共享同一个抽象基类RelevantContentFilter它定义了页面过滤的公共基础保留与排除标签集基类__init__第 50-111 行included_tagsarticle、main、section、div、列表结构ul/ol/li、文本内容p/span/blockquote/pre/code、标题h1-h6、表格、语义元素figure、details等excluded_tagsnav、footer、header、aside、script、style、form、iframe、noscript——这些标签会被直接剔除negative_patterns正则nav|footer|header|sidebar|ads|comment|promo|advert|social|share用于识别 class 或 id 中带有这些语义的容器如classsidebar、idcomments。查询回退机制extract_page_query第 125-159 行如果调用方未提供user_query过滤器会按顺序回退——先取title再取第一个h1文本然后读取meta[namekeywords]与meta[namedescription]若仍为空则取正文中第一个超过 50 字符的p段落的前 150 字符。这个机制正是 0.4.0 中增强 BM25 对页面标题、meta 标签和描述的处理的具体落地。文本块提取extract_text_chunks第 161-271 行采用基于deque的手写深度优先遍历将行内标签a、span、em等视为不切断文本流的节点遇到块级元素边界时把累积文本刷成一个(序号, 文本, header/content 类型, 元素)四元组并可按min_word_threshold过滤过短的块。这套提取 → 评分 → 过滤 → 清洗的流水线是理解两个核心过滤器的共同前提。三、PruningContentFilter无监督评分剪枝PruningContentFiltercrawl4ai/content_filter_strategy.py不需要任何用户查询适合我只想要正文不需要搜索意图的场景。其构造函数参数如下参数类型默认值说明user_querystrNone保留参数该过滤器不依赖查询min_word_thresholdintNone节点文本单词数低于该值时强制剪除构造内提前返回分数 -1.0threshold_typestrfixed阈值类型fixed固定阈值 /dynamic动态阈值thresholdfloat0.48固定阈值或动态阈值的基础值3.1 五维复合评分_compute_composite_score第 737-772 行对每个节点计算加权复合分数五个指标及权重metric_weights为text_density权重 0.4文本长度 / 标签总长度encode_contents得到的 HTML 串长度。文本占比越高说明节点内容密度越大link_density权重 0.21 - 直接子级 a 链接文本长度 / 节点文本长度。链接占比越低的节点得分越高专门压制导航、链接堆砌区tag_weight权重 0.2标签语义权重表tag_weights第 617-632 行如article: 1.5、h1: 1.2、p: 1.0、div: 0.5、span: 0.3class_id_weight权重 0.1_compute_class_id_weight第 774-785 行检查节点的 class 和 id若命中negative_patternssidebar、ads、comments 等则扣 0.5 分最低截断为 0text_length权重 0.1log(文本长度 1)对长文做对数平滑避免超长节点主导评分。最终分数为各启用指标的加权和除以权重之和归一化到与阈值可直接比较的量纲。若设置了min_word_threshold且节点词数不足直接返回 -1.0 保证被移除。3.2 fixed 与 dynamic 两种阈值模式_prune_tree第 685-735 行从body开始递归剪枝fixed 模式score threshold默认 0.48即node.decompose()整个子树移除dynamic 模式在基础阈值上做三次微调——语义重要标签tag_importance表中article: 1.5、h1: 1.4等权重 1阈值乘以 0.8更宽容文本占比text_ratio 0.4再乘以 0.9链接占比link_ratio 0.6则乘以 1.2更严格。也就是说重要标签更难被剪、纯文本节点更被保留、链接密集区更容易被剪。节点不达标时整棵子树被decompose()达标则递归处理子节点最终返回body下所有含文本的顶层子元素 HTML 串列表。过滤前先执行_remove_comments和_remove_unwanted_tags按excluded_tags拆解nav/footer/script等。3.3 单元测试覆盖tests/async/test_content_filter_prune.py 对该过滤器做了系统性验证test_basic_pruningmin_word_threshold5下高质量长段落保留classsidebar与classsocial-share的内容被剪除test_min_word_threshold短摘要与短评论被过滤长段落保留test_threshold_typesfixed 与 dynamic 模式对同一 HTML 产出不同结果集test_link_density_impactdynamic模式下含 4 个链接的div classlinks区块被压制链接密集区被剪枝test_threshold_levels参数化验证阈值单调性——阈值 0.3 时最多保留 4 个块0.48默认时 2 个0.7 时 1 个可用于按页面噪声程度调参还包含空输入、畸形 HTML未闭合标签、性能 0.1 秒与输出一致性多次运行结果相同用例。四、BM25ContentFilter查询驱动的有监督过滤BM25ContentFiltercrawl4ai/content_filter_strategy.py与无监督的剪枝策略互补它把用户查询当作相关性信号。构造参数参数类型默认值说明user_querystrNone查询词缺省时走extract_page_query回退链title → h1 → meta → 首段bm25_thresholdfloat1.0加权后 BM25 分数低于该值的块被丢弃languagestrenglishsnowballstemmer 词干提取语言use_stemmingboolTrue是否对语料与查询做词干提取核心流程filter_content第 440-538 行用 lxml 解析 HTML缺失body时自动包裹提取查询user_query优先否则页面元数据回退复用基类的extract_text_chunks得到有序文本块分词 → 词干提取 →clean_tokens去停用词构建rank_bm25.BM25Okapi并计算每个块的分数标签权重调整第 425-437 行priority_tagsh1: 5.0、title: 4.0、h2: 4.0、h3: 3.0、strong/blockquote/code: 2.0、b/em/pre/th: 1.5即adjusted_score score * tag_weight让标题和强调内容在相关性接近时优先保留按bm25_threshold过滤、按原文档顺序排序保持阅读顺序而非分数序、按文本去重最后用基类clean_element输出清洗后的 HTML 块。0.4.0 中对页面标题、meta 标签、描述的增强正体现在第 125-159 行的extract_page_query回退链上即使用户不传查询过滤器也能用页面自身的语义信号完成自我相关性判断。选型建议与发布说明及 README.md 的示例一致无明确查询意图、只想拿到干净正文用于喂给 LLM →PruningContentFilter更快、零依赖查询有明确信息需求如这个产品支持哪些支付方式→BM25ContentFilter(user_query...)或进一步使用LLMContentFilter。五、User-Agent 生成器0.4.0 新增的 User-Agent 生成器实现于 crawl4ai/user_agent_generator.py提供三类生成器5.1 ValidUAGenerator基于流行度统计的合法 UAValidUAGenerator第 68-87 行基于fake_useragent库生成真实出现过的 UA 字符串generate方法支持约束参数from crawl4ai.user_agent_generator import ValidUAGenerator gen ValidUAGenerator() # 默认Chrome/Firefox/Edge Windows/Mac OS X 桌面端随机取一个 ua gen.generate() # 定制只取 Firefox最低版本 110 ua gen.generate(browsers[Firefox], os[Windows], min_version110.0)参数还包括platforms如[desktop]与fallback拉取数据失败时返回的兜底 UA默认为一个 Linux Chrome 116 的 UA。5.2 OnlineUAGenerator实时抓取最常见 UAOnlineUAGenerator第 89-139 行在初始化时请求公开的用户代理统计站点解析 JSON 得到带真实占比pct的 UA 列表随后可按pct_threshold占比阈值、browsers、os、platforms过滤并返回首条记录{ua: ..., pct: ...}。适合需要与真实流量分布一致的场景。注意该生成器依赖外部网络可用。5.3 UserAgentGenerator组件化拼装与 Client HintsUserAgentGenerator第 143-414 行把 UA 拆成可约束的组件桌面/移动平台字符串Windows 10 64/32 位、macOS、Linux、Android 品牌机型、iOS 等、浏览器组合栈1-3 段浏览器/渲染引擎标识、以及 Chrome/Edge/Safari/Firefox 的版本列表。generate方法接受from crawl4ai.user_agent_generator import UserAgentGenerator gen UserAgentGenerator() ua gen.generate(device_typedesktop, os_typewindows, browser_typechrome, num_browsers3) print(ua) # Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 # (KHTML, like Gecko) Chrome/118.0.5993.117 ...其中device_typedesktop/mobile、os_typewindows、macos、linux、android、ios、device_brand如iphone、pixel、browser_typechrome/edge/safari/firefox、num_browsers1-3控制浏览器标识段数。generate_with_client_hints第 344-348 行会额外解析 UA 并生成与之匹配的Sec-CH-UA请求头值如Chromium;v118, Google Chrome;v118, Not_A Brand;v8使 UA 与 Client Hints 保持一致这对通过现代浏览指纹一致性检查尤为关键。5.4 与 BrowserConfig 集成每请求随机 UA框架层在 crawl4ai/async_configs.py 中为BrowserConfig暴露了user_agent_mode与user_agent_generator_config两个参数第 755-757 行的文档说明user_agent_moderandom时启用随机化user_agent_generator_config用于透传给生成器的约束。默认行为即发布说明所述——每次请求随机化 UA增加多样性同时允许用户定制。实际调用链见 crawl4ai/async_crawler_strategy.py# 在每次运行中若用户未显式传 user_agent # 且 config.magic 或 user_agent_mode random 时 user_agent ValidUAGenerator().generate( **(config.user_agent_generator_config or {}) )命令行侧同样支持该能力crawl4ai/cli.py 的示例即crwl https://example.com -b headlesstrue,viewport_width1280,user_agent_moderandom六、多线程/并发环境下的锁机制0.4.0 的另一项改进是为并行处理环境增加更好的线程锁。从源码结构看这一能力体现在多个关键组件的锁设计上例如 crawl4ai/browser_manager.pyBrowserManager使用类级懒初始化锁_get_lock第 596-605 行并在锁上记录所属事件循环_lock_loop当检测到事件循环切换时重建锁避免跨 loop 复用asyncio.Lock的经典陷阱全局页面锁_get_global_lock第 691-698 行保护页面级共享资源实例级_contexts_lock、_page_lock、_pending_cleanup_lock第 736-756 行分别保护上下文池、页面获取与清理流程LRU 上下文淘汰方法_evict_lru_context_locked第 1435 行附近明确标注必须在持有_contexts_lock时调用从源码结构看属于典型的锁内临界区约定。此外 crawl4ai/async_database.py 中pool_lock/init_lock保护连接池获取与初始化crawl4ai/async_webcrawler.py 第 157 行提供了thread_safe选项self._lock asyncio.Lock() if thread_safe else None在共享爬虫实例时串行化arun调用。这些锁共同保证了多协程、多任务并行抓取时状态的一致性与稳定性。七、实战示例使用 PruningContentFilter 抽取干净正文README.md 给出了 0.4.0 推广的两种过滤器用法可直接运行适用前提已安装当前版本 Crawl4AI 并执行过crawl4ai-setup浏览器安装import asyncio from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig, CacheMode from crawl4ai.content_filter_strategy import PruningContentFilter, BM25ContentFilter from crawl4ai.markdown_generation_strategy import DefaultMarkdownGenerator async def main(): browser_config BrowserConfig( headlessTrue, verboseTrue, user_agent_moderandom, # 0.4.0 起每请求随机 UA user_agent_generator_config{}, # 可传 browsers/os/min_version 等约束 ) run_config CrawlerRunConfig( cache_modeCacheMode.ENABLED, markdown_generatorDefaultMarkdownGenerator( content_filterPruningContentFilter( threshold0.48, threshold_typefixed, min_word_threshold0, ) ), # 换成查询驱动过滤 # markdown_generatorDefaultMarkdownGenerator( # content_filterBM25ContentFilter( # user_queryWHEN_WE_FOCUS_BASED_ON_A_USER_QUERY, # bm25_threshold1.0, # ) # ), ) async with AsyncWebCrawler(configbrowser_config) as crawler: result await crawler.arun( urlhttps://docs.micronaut.io/4.9.9/guide/, configrun_config, ) print(len(result.markdown.raw_markdown)) print(len(result.markdown.fit_markdown)) # 过滤后的干净长度 if __name__ __main__: asyncio.run(main())CLI 同样内建了这两种过滤器crawl4ai/cli.py 支持通过过滤配置文件或--output markdown-fit选择策略——type: bm25时构建BM25ContentFilter可配query、threshold默认 1.0、use_stemmingtype: pruning时构建PruningContentFilter默认threshold0.48并在内部为markdown-fit输出默认采用 pruning 配置。调参经验源自单测中的阈值梯度验证页面导航/广告噪声多时提高threshold如 0.7 只保留最高价值块正文稀疏或结构复杂时降低如 0.3短标签按钮、时间戳多时给min_word_threshold设 5~10 的地板值。八、变更文件清单与实验性声明按发布说明0.4.0 的变更落点为crawl4ai/content_filter_strategy.py加入基于评分的剪枝算法PruningContentFilterREADME.md补充PruningContentFilter用法当前仓库对应 README-first.md 中的示例保留同一写法tests/async/test_content_filter_prune.py覆盖多种剪枝场景、阈值梯度、畸形 HTML 与性能断言tests/async/test_content_filter_bm25.py扩展 BM25 的边界用例含畸形 HTML 输入。发布说明还保留了明确的边界提醒PruningContentFilter当时处于实验性开发阶段。其默认阈值 0.48 与五维权重表都是启发式常量面对非常规页面结构如单列流式布局、大量嵌套span时可能过度剪枝或保留噪声建议按上文调参梯度在真实目标页面上验证后再固化配置。九、小结0.4.0 为 Crawl4AI 补齐了无需查询意图的高质量正文抽取PruningContentFilter 的密度/链接/标签/语义四重评分、查询驱动的精准过滤BM25 页面元数据回退 标签权重、请求指纹多样化三种 UA 生成器 user_agent_moderandom Client Hints 一致性与并发稳定性浏览器管理器多级锁、thread_safe选项四个能力维度。在当前 0.9.0 代码库中这些类与参数均保持可用本文给出的参数表、源码位置与测试路径可直接作为二次开发和调参的索引。【免费下载链接】crawl4ai Crawl4AI: Open-source LLM Friendly Web Crawler Scraper. Dont be shy, join here: https://discord.gg/jP8KfhDhyN项目地址: https://gitcode.com/GitHub_Trending/craw/crawl4ai创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表