考虑以下html
<div id="relevantID">
<div class="column left">
<h1> Section-Header-1 </h1>
<ul>
<li>item1a</li>
<li>item1b</li>
<li>item1c</li>
<li>item1d</li>
</ul>
</div>
<div class="column">
<ul> <!-- Pay attention here -->
<li>item1e</li>
<li>item1f</li>
</ul>
<h1> Section-Header-2 </h1>
<ul>
<li>item2a</li>
<li>item2b</li>
<li>item2c</li>
<li>item2d</li>
</ul>
</div>
<div class="column right">
<h1> Section-Header-3 </h1>
<ul>
<li>item3a</li>
<li>item3b</li>
<li>item3c</li>
<li>item3d</li>
</ul>
</div>
</div>
我的目标是为每个Section标题提取项目。然而,不方便的是,网页的设计者决定将数据分成三列,添加一个额外的div(具有类column right
等)。
我目前的提取方法是使用xpath
对于节标题,我使用xpath(获取具有给定id的div的所有h1
元素)
//div[@id="relevantID"]//h1
上面的返回h1
个元素的列表,循环遍历我应用附加选择器的每个元素,对于每个匹配的h1元素,查找下一个ul
节点并检索其所有li
节点
following-sibling::ul//li
但是由于设计师的美学,我在HTML文件中标记的一个特定情况下失败了。项目分为两个不同的column
div。
我可以通过完全删除column
div来绕过这个问题,但我不认为修改html以使选择器匹配被认为是好的(我还没有看到它需要我到目前为止浏览的例子中的任何地方)。
提取已经格式化的数据的好方法是什么?完整的解决方案不是必需的,提示/提示将做。谢谢!
答案 0 :(得分:1)
这些列确实阻碍了following-sibling::
和preceding-sibling::
的使用,但如果列至少使列表项保持正确,则可以使用following::
和preceding::
轴文件订单。 (在你的例子中确实如此。)
以下XPath将选择“Section-Header-1”li
之后和“Section-Header-2”h1
之前的所有h1
项,无论列如何文档顺序中的标题:
//div[@id='relevantID']//li[normalize-space(preceding::h1) = 'Section-Header-1'
and normalize-space(following::h1) = 'Section-Header-2']
具体来说,它从您的示例HTML中选择以下项目:
<li>item1a</li>
<li>item1b</li>
<li>item1c</li>
<li>item1d</li>
<li>item1e</li>
<li>item1f</li>
答案 1 :(得分:1)
您可以合并following-sibling
和preceding-sibling
,以便在li
之前的div
中获取可能的h2
元素,并使用union运算符|
。作为第二个h2
的示例:
((//div[@id="relevantID"]//h1)[2]/preceding-sibling::ul//li) |
((//div[@id="relevantID"]//h1)[2]/following-sibling::ul//li)
结果:
<li>item1e</li>
<li>item1f</li>
<li>item2a</li>
<li>item2b</li>
<li>item2c</li>
<li>item2d</li>
由于您已使用h1
选择所有//div[@id="relevantID"]//h1
并使用li
作为第二步检索每个h1
的所有following-sibling::ul//li
项,因此您可以将其与following-sibling::ul//li | preceding-sibling::ul//li
合并。