从标头中获取兄弟姐妹,直到非语义表中的下一个标题

时间:2012-12-28 19:07:52

标签: xpath scrapy

使用Scrapy我想解析一个包含非语义表的网页。我正在寻找的是“打印每一个兄弟,直到你遇到以下元素”-XPath-query。

<table>
    <tr>
        <th>Title</th>
        <th>Name</th>
        <th>Comment</th>
        <th>Note</th>
    </tr>
    <tr style="background-color:#CCDDEF;">
        <td colspan="4"> <b>HEADER1</b></td>
    </tr>
    <tr>
        <td>Title1.1</td>
        <td>-</td>
        <td>Info1.1</td>
        <td></td>
    </tr>
    <tr style="background-color:#CCDDEF;">
        <td colspan="4"> <b>HEADER2</b></td>
    </tr>
    <tr>
        <td>Title2.1</td>
        <td>Name2.1</td>
        <td></td>
        <td></td>
    </tr>
    <tr>
        <td>Title2.2</td>
        <td>Name2.2</td>
        <td>Info2.2</td>
        <td></td>
    </tr>
    <tr style="background-color:#CCDDEF;">
        <td colspan="4"> <b>HEADER3</b></td>
    </tr>
    <tr>
        <td>Title3.1</td>
        <td>Name3.1</td>
        <td></td>
        <td></td>
    </tr>
</table>

我想将每个标题下的每个标题,名称,注释和注释分组。我尝试过使用各种XPath(following-siblingpreceding-siblingcount的变体),但我得到的一切都没有,或者每个tr都不是标题。

我目前正在使用//tr[@style]//tr[td[@colspan="4"]]收件人。

以下是我的Scrapy-spider中的parse-function(它打印标题和所有tr不是标题):

def parse(self, response):
    hxs = HtmlXPathSelector(response)
    sites = hxs.select('//*[@id="content-text"]//tr[td[@colspan="4"]]')
    for site in sites:
        print site.select('./td/b/text()').extract()
        print site.select('./following-sibling::tr[not(td[@colspan])]')

1 个答案:

答案 0 :(得分:2)

此XPath表达式

/*/tr[@style or td[@colspan='4']][1]/following-sibling::tr
       [count(. | /*/tr[@style or td[@colspan='4']][2]/preceding-sibling::tr)
       =
        count(/*/tr[@style or td[@colspan='4']][2]/preceding-sibling::tr)
       ]

选择第一个和第二个标题之间的所有tr元素

<tr>
   <td>Title1.1</td>
   <td>-</td>
   <td>Info1.1</td>
   <td/>
</tr>

要选择位于第K个和第(K + 1)个标头之间的所有tr元素,只需将上述表达式1替换为K(数字)和{{ 1}} 2(数字)。

基于XSLT的验证

K+1

在提供的XML文档上应用此转换时:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/">
     <xsl:copy-of select=
     "/*/tr[@style or td[@colspan='4']][1]/following-sibling::tr
             [count(. | /*/tr[@style or td[@colspan='4']][2]/preceding-sibling::tr)
             =
              count(/*/tr[@style or td[@colspan='4']][2]/preceding-sibling::tr)
             ]
     "/>
 </xsl:template>
</xsl:stylesheet>

评估Xpath表达式并将选定的节点复制到输出中:

<table>
    <tr>
        <th>Title</th>
        <th>Name</th>
        <th>Comment</th>
        <th>Note</th>
    </tr>
    <tr style="background-color:#CCDDEF;">
        <td colspan="4">
            <b>HEADER1</b>
        </td>
    </tr>
    <tr>
        <td>Title1.1</td>
        <td>-</td>
        <td>Info1.1</td>
        <td></td>
    </tr>
    <tr style="background-color:#CCDDEF;">
        <td colspan="4">
            <b>HEADER2</b>
        </td>
    </tr>
    <tr>
        <td>Title2.1</td>
        <td>Name2.1</td>
        <td></td>
        <td></td>
    </tr>
    <tr>
        <td>Title2.2</td>
        <td>Name2.2</td>
        <td>Info2.2</td>
        <td></td>
    </tr>
    <tr style="background-color:#CCDDEF;">
        <td colspan="4">
            <b>HEADER3</b>
        </td>
    </tr>
    <tr>
        <td>Title3.1</td>
        <td>Name3.1</td>
        <td></td>
        <td></td>
    </tr>
</table>

<强>解释

这是Kayessian(在Michael Kay博士之后)节点集交集公式的简单应用:

<tr>
   <td>Title1.1</td>
   <td>-</td>
   <td>Info1.1</td>
   <td/>
</tr>

在这个特例中,我们用$ns1[count(.|$ns2) = count($ns2)] 代替:

$ns1

我们将/*/tr[@style or td[@colspan='4']][1]/following-sibling::tr 替换为:

$ns2