C#自定义HTML爬虫遍历函数问题:修复路径查询逻辑
修复带索引的类XPath路径查询逻辑
问题核心
你的Traverse函数缺少对路径节点中索引筛选规则的处理——p[1]这类节点需要先在当前层级收集所有匹配p标签的元素,再按1-based索引选取对应项,而非直接匹配第一个遇到的元素。
具体修复方案
1. 新增路径节点拆分辅助函数
先把带索引的路径节点拆成标签名和索引值,比如p[1]拆为p和1:
private static void SplitPathNode(string nodeStr, out string tagName, out int? index) { tagName = nodeStr; index = null; var bracketStart = nodeStr.IndexOf('['); if (bracketStart != -1 && nodeStr.EndsWith("]")) { tagName = nodeStr.Substring(0, bracketStart).Trim(); if (int.TryParse(nodeStr.Substring(bracketStart + 1, nodeStr.Length - bracketStart - 2), out int idx)) { index = idx; } } }
2. 修改Traverse函数逻辑
在遍历过程中先收集同层级的所有匹配标签,再根据索引筛选:
private static List<HtmlNode> Traverse(List<HtmlNode> currentNodes, List<string> pathSegments, int segmentIndex) { if (segmentIndex >= pathSegments.Count) return currentNodes; var currentSegment = pathSegments[segmentIndex]; SplitPathNode(currentSegment, out string targetTag, out int? targetIndex); var matchedNodes = new List<HtmlNode>(); foreach (var node in currentNodes) { // 先收集当前节点下所有匹配标签的子节点 var sameTagChildren = new List<HtmlNode>(); foreach (var child in node.Children) { if (child.TagName.Equals(targetTag, StringComparison.OrdinalIgnoreCase)) sameTagChildren.Add(child); } if (targetIndex.HasValue) { // 处理1-based索引,转成List的0-based索引 if (targetIndex.Value > 0 && targetIndex.Value <= sameTagChildren.Count) matchedNodes.Add(sameTagChildren[targetIndex.Value - 1]); } else { // 无索引时添加所有匹配节点 matchedNodes.AddRange(sameTagChildren); } } // 递归处理下一段路径 return Traverse(matchedNodes, pathSegments, segmentIndex + 1); }
3. 路径预处理补充
如果你的路径解析逻辑还没处理//开头的情况,需要在分割路径时把//转为空段,然后在Traverse的起始逻辑中处理:当当前段为空时,收集所有层级的匹配节点(而非仅直接子节点)。
关键细节
- 索引兼容性:XPath索引是1-based,必须转成List的0-based索引才能正确取值。
- 边界校验:必须判断索引是否在匹配节点的数量范围内,避免越界异常。
- 标签大小写:HTML标签不区分大小写,匹配时要使用不区分大小写的比较。
内容的提问来源于stack exchange,提问作者Ivan
相关产品推荐
相关产品推荐

