2012-05-16 10 views
13

目標:特定の要素(例:li)からテキストを抽出しながら、さまざまな混在タグを無視します。つまり、第1レベルの子供を平坦化し、平坦化された各子供の連結テキストを別々に返します。HTML XPath:複数のタグが混在したテキストの抽出?

例:

<div id="mw-content-text"><h2><span class="mw-headline" >CIA</span></h2> 
    <ol> 
    <li>Central <a href="/Intelligence_Agency.html">Intelligence Agency</a>.</li> 
    <li>Culinary <a href="/Institute.html">Institute</a> of <a href="/America.html">America</a>.</li> 
    </ol> 

    </Div> 

目的のテキスト:

  • 中央情報局周囲のアンカータグは、単純な検索を防ぐことを除いて

アメリカの

  • カリナリーインスティテュート。

    個別のliタグを返すために、我々は簡単に使用:

    //div[contains(@id,"mw-content-text")]/ol/li 
    

    をそれはまた、直接の子であるテキストだけの要素を、アンカータグを囲むなどと

    //div[contains(@id,"mw-content-text")]/ol/li/text() 
    

    戻り含み

    自己と子孫のテキスト要素を探すのは論理的だと思われる

    //div[contains(@id,"mw-content-text")]/ol/li[descendant-or-self::text] 
    

    しかし、それはまったく何も返しません!

    提案がありますか?私はPythonを使用していますので、後処理のために他のモジュールを使用することができます。

    (Iは、XPath 1.0に準拠しているようだScrapy HtmlXPathSelectorを使用しています)

  • +0

    役に立つことがあります:http://stackoverflow.com/questions/4378502/xpath-return-all-non-blank-text-nodes-not-descendant-of-a-style-or-script/6303276 – warvariuc

    答えて

    24

    あなたはほぼそこにいました。に小さな問題があります:

    //div[contains(@id,"mw-content-text")]/ol/li[descendant-or-self::text] 
    

    修正式はです:

    //div[contains(@id,"mw-content-text")]/ol/li[descendant-or-self::text()] 
    

    しかし、すべてのテキスト・ノードのちょうど希望連結を生産する単純な式があります指定下li

    +0

    '@ id ='の代わりに 'contains'が使われている特定の理由はありますか、あるいはOPが' contains'を使って質問したからですか? – Kiril

    +0

    @リリック、この答えで私は彼が望むことを彼のコードを得るのを助けます - 彼は正確にその 'id'属性で' div'を選択したいのか、 'id'属性指定された文字列を含む彼が前者を意味する可能性は高いですが、回答者は可能な限り推測を避けるべきです。 –

    2

    文字列の連結はトリッキーです。ここでlxmlを使用して迅速な解決策です:

    >>> from lxml import etree 
    >>> doc = etree.HTML("""<div id="mw-content-text"><h2><span class="mw-headline" >CIA</span></h2> 
    ...  <ol> 
    ...  <li>Central <a href="/Intelligence_Agency.html">Intelligence Agency</a>.</li> 
    ...  <li>Culinary <a href="/Institute.html">Institute</a> of <a href="/America.html">America</a>.</li> 
    ...  </ol> 
    ... 
    ...  </Div>""") 
    >>> for element in doc.xpath('//div[@id="mw-content-text"]/ol/li'): 
    ... print "".join(element.xpath('descendant-or-self::text()')) 
    ... 
    Central Intelligence Agency. 
    Culinary Institute of America. 
    

    //は、例えば、HTMLフラグメントとそうする潜在的なパフォーマンスの低下/意図しない実行し、可能な避けるべきであるが、困難を持っていることに注意してください。私は以下のが正しい結果を返すだろうと思う

    5

    //div[contains(@id,"mw-content-text")]/ol/li//text() 
    

    )は(テキストの前にダブルスラッシュに注意してください。つまり、li以下の任意のレベルのテキストノードを返す必要があります。

    +0

    これはです良いアイデアですが、どのような文脈もなく、すべてのテキスト要素を返します。 Firefoxの 'XPath Checker'で確認しています。 1:Central 2:情報機関 3:。 4:料理 5:研究所 6: 7:アメリカ 8:。 どのテキストがどのリリーから来たのかわからない... – ChaimKut

    +0

    各行にピリオドが付いていて(その間にピリオドのある行がない場合(Dr.、Mr.など))、連結することができますすべてのテキストをその期間まで持ち、各期間== liの終わりと仮定します。 – rishimaharaj

    関連する問題