2

Scrapyを使用して、非常に意味のないテーブルを含む Web ページを解析したいと思います。私が探しているのは、「次の要素に一致するまで、次のすべての兄弟を印刷する」-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>

各ヘッダーの下にすべてのタイトル、名前、コメント、およびメモをグループ化したいと思います。following-siblingさまざまな XPath ( 、preceding-siblingおよびのバリエーションcount) を試してみましたが、何も得られないかtr、ヘッダーではないすべてまたはすべてが得られます。

//tr[@style]現在、またはでヘッダーを取得してい//tr[td[@colspan="4"]]ます。

以下は、私の Scrapy-spider の解析関数です (ヘッダーと、ヘッダーtrではないすべての 's を出力します)。

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])]')
4

1 に答える 1

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)
       ]

tr1番目と2番目のヘッダーの間にあるすべての要素を選択します。

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

trK番目と(K + 1)番目のヘッダーの間にあるすべての要素を選択するには、上記の式1K(数値)と2(数値)に置き換えるだけK+1です。

XSLTベースの検証

<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>

この変換が提供されたXMLドキュメントに適用される場合:

<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式が評価され、選択したノードが出力にコピーされます。

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

説明

これは、ノードセットの共通部分に対するKayessian(Dr. Michael Kayの後)式の単純なアプリケーションです。

$ns1[count(.|$ns2) = count($ns2)]

この特定のケースでは、次のように置き換え$ns1ます。

/*/tr[@style or td[@colspan='4']][1]/following-sibling::tr

そして、次のように置き換え$ns2ます。

/*/tr[@style or td[@colspan='4']][2]/preceding-sibling::tr
于 2012-12-28T20:02:31.013 に答える