2016-07-05 6 views
0

ScrapyのXPathセレクタの使用プレーンテキストまたは書式設定されたHTMLコンテンツを含むdiv要素のテキストコンテンツを平坦化しようとしています。ここでは2つの例を示します。特定のノードを除いたXPathの平坦化されたテキスト

<div> 
    <div itemprop="content"> 
     Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
     <br> 
     Donec fringilla est eu euismod varius. 
    </div> 

    <div itemprop="content"> 
     <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> 
     <p>Donec fringilla est eu euismod varius.</p> 
     <p class="quote"> 
      <span>Quote</span> 
      <a href="#">Exclude me</a> 
      <ul> 
       <li>Exclude me</li> 
       <li>Exclude me</li> 
      </ul> 
     </p> 
     <blockquote>Cras facilisis suscipit euismod.</blockquote> 
    </div> 
</div> 

今の目標は、それだけで、それを次ための視覚的な手掛かりとなって平らにテキストで<p class="quote">Quote</p>を省略することです。最初の例の性質のために、選択したdivの直接の子としてすなわち、テキスト、次のように私はルックスを作ってみた解決策:

//div[@itemprop="content"]/descendant-or-self::*[not(self::script)]/text()[normalize-space()] 

は、これは3つのことを実現:

  1. は除外します<script>ノードを私の結果に含めたくないからです。
  2. テキストを含まないノードを除外します。
  3. トップレベルdivの直筆の子供を含む(descendant-or-self経由)。 <div itemprop="content">が期待される出力のようなリストであるノード上で

    //div[@itemprop="content"]/descendant-or-self::*[not(self::script) and not(@class="quote")]/text()[normalize-space()] 
    
    //div[@itemprop="content"]/descendant-or-self::*[not(self::script)]/text()[normalize-space() and not(ancestor::*[@class="quote"])] 
    

    反復処理:

は、残念ながら後者が<p class="quote">Quote</p>を引き起こしているような追加を除くフィルタ、のにもかかわらず、含まれるように私には思えます。

['Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec fringilla est eu euismod varius.', 
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec fringilla est eu euismod varius. Cras facilisis suscipit euismod.'] 

単一のXPathセレクタでこの問題を解決する方法はありますか?

+1

'// divの[@にitemprop = "コンテンツ"]あなたのサンプル入力で私のために働いた/ descendant-or-self :: * [not(self :: script)ではなく(@ class = "quote")]/text()[normalize-space()] '何を手に入れていますか?出力として何を期待していますか? (あなたはこれらの答えで質問を更新できます) –

+0

こんにちはポール、それを指摘してくれてありがとう!私の入力例は問題を正しく表していませんでした。私が除外したいノードには、私が除外しなければならない追加の子供がいます。例を与えるために、私は -childと '' '

' ''にリストを追加しましたが、ここではどのような形の子でも構いません。 – oschlueter

答えて

0

ので、それを書き、属性を持つアイテムを指すように:self::*[@class="quote"]

//div[@itemprop="content"]/descendant-or-self::*[not(self::script or self::*[@class="quote"])]/text()[normalize-space()] 
+0

それを指摘してくれてありがとう、残念ながらそれはそれをカットしていないようです。ここに私の観察があります:// div [@ itemprop = "content"]/descendant-or-self :: * [@ class = "quote"]は、除外したいものを正しく選択します。/div [@ itemprop = "content"]/descendant-or-self :: * [not(@ class = "quote")]でも引用符を含むテキスト全体が選択されます。 – oschlueter

+0

結果を見る: '// div [@ itemprop =" content "] /子孫:: * [not(@ class =" quote ")]'。'descendant-or-self'に質問すると' div [@ itemprop = "content"] 'whickに' Quote'が含まれています – splash58

+0

'save descendant-or-self'軸に'/tex() ' – splash58

0

はここ(lxml経由)サポートをscrapy EXSLT's set operationsを使用して方法です。

XPathを少し変更する必要があるかもしれませんが、アイデアは親要素の下にあるすべてのテキストノードを選択し、それらのテキストノードをその親の子孫要素の下にも除外します。

注:私はあなたの入力ビットbecause <p> can't contain <ul>を変更しなければならなかったし、それが(ボンネットの下にデフォルトでscrapyで使用)lxmlに問題を引き起こしていた

>>> import scrapy 
>>> t = r'''<div> 
...  <div itemprop="content"> 
...   Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
...   <br> 
...   Donec fringilla est eu euismod varius. 
...  </div> 
... 
...  <div itemprop="content"> 
...   <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> 
...   <p>Donec fringilla est eu euismod varius.</p> 
...   <div class="quote"> 
...    <ul> 
...     <li>Exclude me</li> 
...     <li>Exclude me</li> 
...    </ul> 
...    <span>Quote</span> 
...    <a href="#test">Exclude me</a> 
...   </div> 
...   <blockquote>Cras facilisis suscipit euismod.</blockquote> 
...  </div> 
... </div>''' 
>>> selector = scrapy.Selector(text=t, type='html') 
>>> pprint(selector.xpath(''' 
       set:difference(
        //div[@itemprop="content"]//text(), 
        //div[@class="quote"]//text()) 
      ''').extract()) 
['\n' 
'  Lorem ipsum dolor sit amet, consectetur adipiscing elit. \n' 
'  ', 
'\n  Donec fringilla est eu euismod varius.\n ', 
'\n  ', 
'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', 
'\n  ', 
'Donec fringilla est eu euismod varius.', 
'\n  ', 
'\n  ', 
'Cras facilisis suscipit euismod.', 
'\n '] 
>>> 
関連する問題