从列表中提取分割不同div的内容

时间:2014-11-29 19:22:35

标签: xpath web-scraping lxml

考虑以下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以使选择器匹配被认为是好的(我还没有看到它需要我到目前为止浏览的例子中的任何地方)。

提取已经格式化的数据的好方法是什么?完整的解决方案不是必需的,提示/提示将做。谢谢!

2 个答案:

答案 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-siblingpreceding-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合并。