使用 Pruning 和 BM25 来适配 Markdown
Fit Markdown 是页面 Markdown 的专门过滤版本,专注于最相关的内容。默认情况下,Crawl4AI 会将整个 HTML 转换为宽泛的 raw_markdown。使用 Fit Markdown,我们会应用内容过滤算法(例如 Pruning 或 BM25)来移除或排序低价值部分(例如重复的侧边栏、浅显的文本块或不相关的内容),从而留下简洁的文本“核心”。
1.“Fit Markdown”的工作原理
1.1content_filter
在CrawlerRunConfig
,您可以指定content_filter
决定在最终生成 Markdown 之前如何修剪或排序内容。过滤器的逻辑会在 HTML→Markdown 过程之前或过程中应用,从而产生:
- (未过滤)
- (过滤版或“适合”版)
- (相应的 HTML 代码片段
fit_markdown
)
1.2 常用过滤器
1. PruningContentFilter – 根据文本密度、链接密度和标签重要性对每个节点进行评分,丢弃低于阈值的节点。2. BM25ContentFilter – 使用 BM25 排名关注文本相关性,尤其适用于特定的用户查询(例如“机器学习”或“食品营养”)。
2. PruningContentFilter
修剪会根据文本密度、链接密度和标签重要性丢弃不太相关的节点。这是一种基于启发式的方法——如果某些部分显得过于“单薄”或过于“垃圾”,就会被修剪掉。
2.1 使用示例
import asyncio
from crawl4ai import AsyncWebCrawler, CrawlerRunConfig
from crawl4ai.content_filter_strategy import PruningContentFilter
from crawl4ai.markdown_generation_strategy import DefaultMarkdownGenerator
async def main():
# Step 1: Create a pruning filter
prune_filter = PruningContentFilter(
# Lower → more content retained, higher → more content pruned
threshold=0.45,
# "fixed" or "dynamic"
threshold_type="dynamic",
# Ignore nodes with <5 words
min_word_threshold=5
)
# Step 2: Insert it into a Markdown Generator
md_generator = DefaultMarkdownGenerator(content_filter=prune_filter)
# Step 3: Pass it to CrawlerRunConfig
config = CrawlerRunConfig(
markdown_generator=md_generator
)
async with AsyncWebCrawler() as crawler:
result = await crawler.arun(
url="https://news.ycombinator.com",
config=config
)
if result.success:
# 'fit_markdown' is your pruned content, focusing on "denser" text
print("Raw Markdown length:", len(result.markdown.raw_markdown))
print("Fit Markdown length:", len(result.markdown.fit_markdown))
else:
print("Error:", result.error_message)
if __name__ == "__main__":
asyncio.run(main())
2.2 关键参数
- (int):如果一个块中的单词数少于此数,则会被修剪。
- (字符串):
- → 每个节点必须超过
threshold
(0–1)。 - → 节点评分根据标签类型、文本/链接密度等进行调整。
- (浮点数,默认值~0.48):基准或“锚点”截止值。
算法因素:
- 文本密度——鼓励文本与整体内容的比例更高的块。
- 链接密度——惩罚大部分是链接的部分。
- 标签重要性——例如
<article>
或者<p>
可能比<div>
。 - 结构上下文——如果节点嵌套很深或位于可疑的侧边栏中,则它可能会被降低优先级。
3. BM25内容过滤器
BM25 是一种经典的文本排名算法,常用于搜索引擎。如果您有用户查询或依赖页面元数据来推导查询,BM25 可以识别哪些文本块与该查询最匹配。
3.1 使用示例
import asyncio
from crawl4ai import AsyncWebCrawler, CrawlerRunConfig
from crawl4ai.content_filter_strategy import BM25ContentFilter
from crawl4ai.markdown_generation_strategy import DefaultMarkdownGenerator
async def main():
# 1) A BM25 filter with a user query
bm25_filter = BM25ContentFilter(
user_query="startup fundraising tips",
# Adjust for stricter or looser results
bm25_threshold=1.2
)
# 2) Insert into a Markdown Generator
md_generator = DefaultMarkdownGenerator(content_filter=bm25_filter)
# 3) Pass to crawler config
config = CrawlerRunConfig(
markdown_generator=md_generator
)
async with AsyncWebCrawler() as crawler:
result = await crawler.arun(
url="https://news.ycombinator.com",
config=config
)
if result.success:
print("Fit Markdown (BM25 query-based):")
print(result.markdown.fit_markdown)
else:
print("Error:", result.error_message)
if __name__ == "__main__":
asyncio.run(main())
3.2 参数
- (str,可选):例如
"machine learning"
。如果为空,过滤器会尝试从页面元数据中收集查询。 - (浮点数,默认 1.0):
- 更高→块数更少但相关性更高。
- 更低→更具包容性。
在更高级的情况下,您可能会看到类似以下参数language
,case_sensitive
, 或者priority_tags
改进文本的标记或加权方式。
4. 访问“Fit”输出
抓取后,您的“合适”内容位于result.markdown.fit_markdown
。
如果内容过滤器是 BM25,您可能会看到额外的逻辑或引用fit_markdown
突出显示相关片段。如果是修剪,文本通常会被很好地清理,但不一定与查询匹配。
5. 代码模式回顾
5.1 修剪
prune_filter = PruningContentFilter(
threshold=0.5,
threshold_type="fixed",
min_word_threshold=10
)
md_generator = DefaultMarkdownGenerator(content_filter=prune_filter)
config = CrawlerRunConfig(markdown_generator=md_generator)
5.2 BM25
bm25_filter = BM25ContentFilter(
user_query="health benefits fruit",
bm25_threshold=1.2
)
md_generator = DefaultMarkdownGenerator(content_filter=bm25_filter)
config = CrawlerRunConfig(markdown_generator=md_generator)
6. 结合“word_count_threshold”和排除项
请记住,您还可以指定:
config = CrawlerRunConfig(
word_count_threshold=10,
excluded_tags=["nav", "footer", "header"],
exclude_external_links=True,
markdown_generator=DefaultMarkdownGenerator(
content_filter=PruningContentFilter(threshold=0.5)
)
)
因此,发生多级过滤:
- 爬虫的
excluded_tags
首先从 HTML 中删除。 - 内容过滤器(修剪、BM25 或自定义)会修剪或排列剩余的文本块。
- 最终“适合”的内容是在
result.markdown.fit_markdown
。
7.自定义过滤器
如果您需要不同的方法(例如专门的 ML 模型或特定于站点的启发式方法),您可以创建一个继承自RelevantContentFilter
并实施filter_content(html)
.然后将其注入到你的 markdown 生成器中:
from crawl4ai.content_filter_strategy import RelevantContentFilter
class MyCustomFilter(RelevantContentFilter):
def filter_content(self, html, min_word_threshold=None):
# parse HTML, implement custom logic
return [block for block in ... if ... some condition...]
步骤:
- 子类
RelevantContentFilter
。 - 实施
filter_content(...)
。 - 使用它在你的
DefaultMarkdownGenerator(content_filter=MyCustomFilter(...))
。
8. 最后的想法
Fit Markdown 对于以下方面至关重要:
- 摘要:从杂乱的页面中快速获取重要文本。
- 搜索:与 BM25 结合生成与查询相关的内容。
- AI 管道:过滤掉样板,以便基于 LLM 的提取或摘要在更密集的文本上运行。
要点: - PruningContentFilter:如果您只想要“最充实”的文本而不需要用户查询,那么它非常适合。 - BM25ContentFilter:非常适合基于查询的提取或搜索。 - 结合excluded_tags
,exclude_external_links
,word_count_threshold
完善最终的“合适”文本。- Fit markdown 最终result.markdown.fit_markdown
; 最终result.markdown.fit_markdown
在未来的版本中。
借助这些工具,您可以专注于真正重要的文本,忽略垃圾内容或样板内容,并为您的 AI 或数据管道生成简洁、相关的“合适 Markdown”。祝您修剪和搜索愉快!
- 最后更新时间:2025-01-01