- 后端
- AI 应用
- NLP
【免费下载链接】xberg
Polyglot document intelligence with a Rust core: extract text, metadata, images, tables, and structured data from 106 formats across 140 file extensions, plus code intelligence for 371 languages. Fifteen bindings, with CLI, REST API, and MCP server.
本篇指南围绕 xberg 项目 Dart 绑定中的 URL 爬取(crawl)提取能力展开,讲解如何通过mode: "crawl"配置让提取引擎从种子 URL 出发自动发现并跟随页面内链接,将多个网页的内容一次性抽取为结构化结果。读完本文,你将掌握 xberg Dart 侧extract的完整调用流程、url.crawl爬虫策略参数的语义与默认值,以及底层 Rust 引擎对爬取模式的分流处理与结果汇总机制,可以直接在真实项目中复现可用的链接跟随式提取方案。
一次"跟随链接"的提取:从示例片段看完整流程
仓库中 docs-site/src/snippets-generated/dart/url/url_crawl_linked_pages.md 是 alef 自动生成并用于类型检查与端到端验证的 Dart 示例片段,完整演示了 crawl 模式的最小可运行写法:
import 'dart:io'; import 'package:xberg/xberg.dart'; import 'package:xberg/src/xberg_bridge_generated/frb_generated.dart' show RustLib; Future<void> main() async { await RustLib.init(); try { final input = await createExtractInputFromJson(json: '{"kind":"uri","uri":"https://example.com"}'); final config = await createExtractionConfigFromJson(json: '{"url":{"crawl":{"max_depth":1,"max_pages":4,"respect_robots_txt":false},"mode":"crawl"}}'); final result = await XbergBridge.extract(input, config: config); stdout.writeln(result.summary.pagesCrawled); stdout.writeln(result.results[1].content); } finally { RustLib.dispose(); } }这段代码包含四个关键步骤,每一步都与 Rust 核心侧的 API 一一对应:
- 初始化原生运行时:
await RustLib.init()加载由 flutter_rust_bridge 生成的原生库;示例末尾的finally块中RustLib.dispose()保证退出时释放资源。相关绑定生成代码位于 packages/dart/lib/src/xberg_bridge_generated/frb_generated.dart。 - 构造输入:
createExtractInputFromJson以 JSON 字符串形式声明输入为{"kind":"uri","uri":"..."},即对指定 URL 发起 HTTP(S) 提取;实际使用中也可换用kind: "bytes"直接传入字节流。 - 构造配置:
createExtractionConfigFromJson是本篇的核心,JSON 中url.mode设为"crawl",并在url.crawl下给出爬虫策略(最大深度 1、最多 4 页、忽略 robots.txt)。 - 执行提取:
XbergBridge.extract(input, config: config)返回结果对象,其中summary.pagesCrawled是被爬取页面总数,results[1].content是第二个被跟随页面的正文内容。
在 e2e/dart/test/url_test.dart 中可以看到与示例片段对应的端到端测试,它对两个断言做了严格校验:summary.pagesCrawled >= 2(种子页 + 至少一个链接页)且results[1].content包含链接页的正文特征文本'About crawl target'。
url 提取的三种模式:auto、document 与 crawl
crawl 模式并非独立功能,而是 xberg URL 提取配置中的一种模式选择。在 crates/xberg/src/core/config/extraction/types.rs 中定义了枚举UrlExtractionMode:
auto(默认):先抓取 HTTP(S) 资源,再按内容类型分类处理——HTML 走页面管线,二进制/文档则作为文档下载提取。默认配置下未显式指定mode时即为此值。document:把种子 URI 当作单个远程文档或页面处理,只提取这一个资源本身。crawl:从种子 URI 出发执行爬取,将发现的所有页面/文档作为批量结果返回——即本示例使用的模式。
对应的结构体UrlExtractionConfig(types.rs)除了mode之外还包含:
document_url_pattern:对文档型链接的正则过滤;max_document_urls_per_result:每个提取结果最多跟随的文档链接数(默认 100);max_total_urls:整个提取调用累计跟随的 URL 上限(默认 1000);allow_local_file_inputs/allow_file_uris:是否允许本地文件系统路径与file://输入。
crawl 配置项逐个拆解:max_depth、max_pages 与 respect_robots_txt
示例配置{"max_depth":1,"max_pages":4,"respect_robots_txt":false}只是爬虫策略的一部分。xberg 通过依赖的 crawlberg 爬虫引擎的CrawlConfig透传全套参数,其 xberg 默认值在 types.rs 的default_xberg_crawl_config()中定义:
| 配置项 | 示例值 | xberg 默认值 | 含义 |
|---|---|---|---|
max_depth | 1 | 1 | 从种子页算起的最大跟随深度,1表示只跟随种子页的直接链接 |
max_pages | 4 | 100 | 整个爬取过程最多抓取的页面总数上限 |
max_concurrent | 未设置 | 10 | 并发抓取的最大连接数 |
respect_robots_txt | false | true | 是否遵守目标站点的 robots.txt 规则(示例为本地 mock 服务器而关闭) |
soft_http_errors | 未设置 | true | 是否将 HTTP 错误页作为软错误继续处理而非中断 |
stay_on_domain | 未设置 | true | 是否停留在种子域名内 |
allow_subdomains | 未设置 | true | 是否允许跟随种子域名的子域 |
document_url_depth | 未设置 | 1 | 对文档型链接的递归跟随深度 |
示例片段显式给出max_depth、max_pages、respect_robots_txt三个参数,其余则回落默认值。从配置 JSON 的层级可以看出,所有爬虫参数都嵌套在url.crawl之下,与url.mode平级。
底层原理:crawl 模式如何被 Rust 引擎执行
模式分流:scrape 与 crawl 两条路径
在 crates/xberg/src/engine/extract_impl.rs 的extract_remote_uri中,config.url.mode决定了底层引擎的调用方式:
match config.url.mode { UrlExtractionMode::Auto | UrlExtractionMode::Document => { let scrape = engine.scrape(uri).await.map_err(map_crawl_error)?; output_from_scrape(scrape, config, index).await } UrlExtractionMode::Crawl => { let crawl = engine.crawl(uri).await.map_err(map_crawl_error)?; output_from_crawl(crawl, config, index).await } }即:auto/document走scrape(抓取单页/单文档),crawl走crawl(跟随链接爬取)。两种路径共用同一个CrawlEngine构建入口,区别仅在于后续处理函数不同。
引擎复用:按配置指纹缓存 CrawlEngine
批量提取多个 URL 时,crates/xberg/src/engine/crawl_handle.rs 中的CrawlHandleMemo会把整个批次共享同一份爬虫配置的 URL 路由到一个crawlberg::CrawlEngine,复用其缓存、限速器与中间件链。复用与否通过crawl_fingerprint判断:将CrawlConfig序列化为规范 JSON 字节后取哈希作为稳定指纹(crawl_handle.rs中crawl_fingerprint),指纹一致直接克隆缓存的引擎,不一致则重新校验并构建。这样既避免了重复构建开销,也保证了不同配置之间不会错误复用。
结果汇总:pages_crawled 与页面顺序
output_from_crawl(extract_impl.rs)接收crawlberg::CrawlResult,将crawl.pages.len()写入summary.pages_crawled,随后对每个页面调用result_from_crawl_page生成独立结果条目。值得注意的是:每个页面的结果中还会注入crawl_depth元数据(见 extract_impl.rs),便于下游区分页面在爬取树中的层级。merge_crawl_summary则负责汇总最终 URL、重定向计数与去重后的规范化 URL 列表(crawl_final_urls、crawl_redirect_count、crawl_unique_normalized_urls)。
这解释了示例中断言为何是results[1].content:索引 0 是种子页面(/),索引 1 是由种子页<a href="/about">链接发现并跟随的/about页面,二者在 mock 服务器的响应中都被声明为text/html,因此走 HTML 页面提取管线。
端到端验证:mock 服务器如何支撑"跟随链接"
示例断言不是凭空设定的。fixture fixtures/url/url_crawl_linked_pages.json 中定义了对应的 mock 服务器行为:
GET /返回 200,HTML 正文为<h1>Root Crawl Page</h1>并带有指向/about的链接;GET /about返回 200,HTML 正文为<h1>About crawl target</h1><p>Linked page body.</p>;- 输入为
{"kind":"uri","uri":"$mock_url"},其中$mock_url由测试运行器替换为 mock 服务器地址; - 断言为
summary.pages_crawled >= 2(两个页面均被抓取)且results[1].content包含"About crawl target"。
e2e 测试 url_test.dart 在setUpAll中设置CRAWLBERG_ALLOW_PRIVATE_NETWORK=true环境变量,允许爬虫引擎访问本地 mock 服务器,再通过_fixtureUrl("url_crawl_linked_pages")将 fixture 的$mock_url占位符替换为实际测试地址。若本地没有可用的 SUT(被测服务),测试会回退到共享的 mock 服务器辅助函数(startMockServer)。
从示例到生产:将 crawl 模式接入 Dart 应用
综合以上内容,在真实 Dart 应用中启用链接跟随式提取的最小改动如下:
- 确认项目已引入 xberg Dart 包并执行原生库初始化(
RustLib.init()); - 用
createExtractInputFromJson构造uri类型输入; - 用
createExtractionConfigFromJson声明url.mode: "crawl",按站点规模设置max_depth与max_pages(注意默认respect_robots_txt: true,公网站点通常建议保留该默认值以避免合规风险); - 调用
XbergBridge.extract后,遍历result.results读取各页面content,用result.summary.pagesCrawled观察实际抓取规模,用crawl_depth元数据判断页面层级。
需要说明的适用前提:crawl 提取依赖url-ingestionfeature(在 crates/xberg/Cargo.toml 中定义为url-ingestion = ["url-config-types", "crawlberg/native-runtime"]),并且要求 Tokio 运行时、不支持 wasm32 目标(对应代码均以#[cfg(all(feature = "url-ingestion", feature = "tokio-runtime", not(target_arch = "wasm32")))]条件编译)。若目标平台关闭该 feature,URI 提取会返回UnsupportedFormat错误,提示需要启用url-ingestion(见 extract_impl.rs)。
除了本示例的 crawl 模式,同一套url.crawl配置还支持两种相邻场景,可在 e2e/dart/test/url_test.dart 中对照参考:url_gzip_encoded_document验证 gzip 编码的远程文档提取,url_recursive_document_urls则在mode: "document"下通过follow_document_urls: true与document_url_depth递归跟随结果中发现的文档链接——两者与 crawl 模式共同构成了 xberg 完整的 URL 提取能力矩阵。
- 后端
- AI 应用
- NLP
【免费下载链接】xberg
Polyglot document intelligence with a Rust core: extract text, metadata, images, tables, and structured data from 106 formats across 140 file extensions, plus code intelligence for 371 languages. Fifteen bindings, with CLI, REST API, and MCP server.
相关推荐
xberg URL 爬取模式实战:用 C 提取链接页面与多页站点内容
xberg URL 爬取模式实战:用 C 提取链接页面与多页站点内容 导读 xberg 的 URL 提取(URL ingestion)能力不止于"抓取单个远程文
后端AI 应用NLPXberg Dart 绑定实战:用 `url.mode: "document"` 从网页 URL 提取 HTML 页面内容
Xberg Dart 绑定实战:用 url.mode: "document" 从网页 URL 提取 HTML 页面内容 本篇指南围绕 Xberg 的 Dart
后端AI 应用NLP使用 Dart 绑定通过 Xberg extractBatch 批量抽取 URI 文档
使用 Dart 绑定通过 Xberg extractBatch 批量抽取 URI 文档 导读 本指南围绕 Xberg 为 Dart/Flutter 提供的高层
后端AI 应用NLP
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考