如何通过XPath定位指定标题元素的最近表格
合并投资明细表表格抓取方案
需求说明
- 目标:抓取所有标题包含合并投资明细表(英文原称:Consolidated Schedule of Investments)的表格
- 核心难点:不同页面中,目标表格与标题的相对位置差异极大——表格可能是标题的兄弟元素、祖先容器,或是标题的后代元素
已实现的标题定位XPath
已可精准定位目标标题的XPath代码:
//span[contains(translate(., 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), 'CONSOLIDATED SCHEDULE OF INVESTMENTS')]
定位最近表格的XPath方案
通用兼容方案(XPath 1.0支持)
以下XPath会覆盖所有可能的位置关系,优先匹配距离标题最近的表格:
//span[contains(translate(., 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), 'CONSOLIDATED SCHEDULE OF INVESTMENTS')]/following::table[1] | //span[contains(translate(., 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), 'CONSOLIDATED SCHEDULE OF INVESTMENTS')]/ancestor::table[1] | //span[contains(translate(., 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), 'CONSOLIDATED SCHEDULE OF INVESTMENTS')]/preceding::table[1]
执行逻辑:
- 先查找标题之后的第一个表格(最常见的情况)
- 若未找到,查找包含标题的最近祖先表格(标题在表格内部的情况)
- 最后查找标题之前的第一个表格(标题在表格之后的特殊情况)
精准距离匹配方案(XPath 2.0+支持)
如果使用支持XPath 2.0及以上的解析工具,可通过计算层级距离直接定位最近的表格:
//table[ let $title := //span[contains(translate(., 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), 'CONSOLIDATED SCHEDULE OF INVESTMENTS')] return min( count($title/ancestor::table[. = current()]/ancestor::*) + 1, count(current()/ancestor::table[. = $title/ancestor::table[1]]/ancestor::*) + 1, count($title/following::table[. = current()]/preceding::*) + 1, count(current()/preceding::table[. = $title/preceding::table[1]]/following::*) + 1 ) = 1 ]
分页面适配方案
若通用方案仍有遗漏,可针对不同页面结构补充分支:
- 当标题是表格的子元素:
//span[...]/ancestor::table[1] - 当标题是表格的前序兄弟:
//span[...]/following-sibling::table[1] - 当标题与表格同属一个父容器:
//span[...]/parent::*/following-sibling::table[1]
内容的提问来源于stack exchange,提问作者Mohamed Grich
相关产品推荐
相关产品推荐

