BrowseCrawler
概述
BrowseCrawler 用 BFS 队列遍历整棵 AddressSpace 子树, 双重保护 (max_depth + max_nodes)。
API
| 成员 | 类别 | 读写 | 说明 |
|---|---|---|---|
| BrowseCrawler(ua, max_depth, max_nodes, filter) | 构造 | — | 构造 |
| CrawlAsync(root, progress) | 方法 | 读 | 返回 std::future<CrawlResult> |
| CrawlResult.all_nodes | 字段 | 读 | std::vector<CrawlNode> |
| CrawlResult.children_by_parent | 字段 | 读 | std::map<string, vector<string>> |
| CrawlResult.elapsed | 字段 | 读 | 总耗时 (std::chrono::duration) |
代码示例
#include <darra/opcua.h>
using namespace darra::opcua;
DarraOpcUa ua("opc.tcp://localhost:4840");
ua.Connect();
// 1) 爬整棵 ObjectsFolder
BrowseCrawler crawler(ua, /*max_depth=*/8, /*max_nodes=*/50000);
auto progress = [](int count, const std::string& nid) {
std::cout << "\r已抓 " << count << " 个, 当前 " << nid << std::flush;
};
auto fut = crawler.CrawlAsync(WellKnownNodes::ObjectsFolder, progress);
auto result = fut.get();
std::cout << "\n共 " << result.all_nodes.size() << " 节点, 耗时 "
<< std::chrono::duration_cast<std::chrono::milliseconds>(result.elapsed).count()
<< " ms\n";
// 2) 仅 Variable 节点
BrowseCrawler c2(ua, 10, 100000, NodeClass::Variable);
auto r2 = c2.CrawlAsync("ns=2;s=Boilers").get();
for (auto& n : r2.all_nodes)
std::cout << " " << n.browse_name << " (" << n.node_id << ")\n";
性能
| 节点规模 | 耗时 |
|---|---|
| 1,000 | ~0.5s |
| 10,000 | ~5s |
| 50,000 | ~25s |
最佳实践
- 限定 root, 不要从 i=84 (Root) 开始
- 用 nodeClassFilter 节省内存
- 启动时一次性爬
跨语言对照
| C# | Python | Java | C++ | Rust | C |
|---|---|---|---|---|---|
| BrowseCrawler | BrowseCrawler | BrowseCrawler | BrowseCrawler | BrowseCrawler | DarraUa_BrowseCrawler_* |