跳到主要内容

BrowseCrawler — 整树离线爬取

概述

IDE / HMI 联机时常需要把 AddressSpace 子树拉到本地。BrowseCrawler 用 BFS 队列遍历, 双重保护 (maxDepth + maxNodes)。

API

成员类别读写说明
new BrowseCrawler(ua, maxDepth, maxNodes, nodeClassFilter)构造构造
crawlAsync(rootNodeId, progress)方法返回 CompletableFuture<CrawlResult>
CrawlResult.allNodes属性扁平节点列表
CrawlResult.childrenByParent属性父子关系 Map
CrawlResult.elapsed属性总耗时 (Duration)

代码示例

import com.darra.opcua.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;

try (DarraOpcUa ua = new DarraOpcUa("opc.tcp://localhost:4840")) {
ua.connect();

// 1) 爬整棵 ObjectsFolder
BrowseCrawler crawler = new BrowseCrawler(ua, 8, 50_000, NodeClass.Unspecified);

BiConsumer<Integer, String> progress = (count, nid) ->
System.out.printf("\r已抓 %d 个, 当前 %s", count, nid);

CompletableFuture<CrawlResult> fut = crawler.crawlAsync(
WellKnownNodes.OBJECTS_FOLDER, progress);
CrawlResult result = fut.get();

System.out.printf("%n共 %d 节点, 耗时 %.1fs%n",
result.allNodes.size(), result.elapsed.toMillis() / 1000.0);

// 2) 仅 Variable 节点
BrowseCrawler c2 = new BrowseCrawler(ua, 10, 100_000, NodeClass.Variable);
CrawlResult r2 = c2.crawlAsync("ns=2;s=Boilers", null).get();
for (CrawlNode n : r2.allNodes)
System.out.println(" " + n.browseName + " (" + n.nodeId + ")");

// 3) 取消支持
CompletableFuture<CrawlResult> fut3 = crawler.crawlAsync("i=85", null);
cancelButton.addActionListener(e -> fut3.cancel(true));
}

性能

节点规模耗时
1,000~0.5s
10,000~5s
50,000~25s

最佳实践

  • 限定 root, 不要从 i=84 (Root) 开始
  • 用 nodeClassFilter 节省内存
  • 启动时一次性爬, 后续从本地查
  • 给用户"取消"按钮

跨语言对照

C#PythonJavaC++RustC
BrowseCrawlerBrowseCrawlerBrowseCrawlerBrowseCrawlerBrowseCrawlerDarraUa_BrowseCrawler_*

下一步