2016-04-10 11 views
2

私は、scrapを使用してbbcodeフォーラムをスクラップするPythonコードをいくつか持っていますが、引用文からテキストを除く投稿のテキストを与えるXpath式が必要です。 HTMLは次のようになります。XPathとScrapy/lxmlを使用した特定の子ノードの除外

<td class="postbody"> 
    hi this is a response 
    <div class="bbc-block"> 
     <blockquote> 
     blah blah blah here's a quote 
     <br> 
     </blockquote> 
    </div> 
    <br> 
    and now I'm responding to what I quoted 
</td> 
<td class="postbody"> 
    <div class="bbc-block"> 
     <blockquote> 
     and now I'm responding to what I quoted 
     <br> 
     </blockquote> 
    </div> 
    <br> 
    wow what a great response 
</td> 

これは、各投稿ごとに何度も表示されます。私は最終的に欲しいのは除外BLOCKQUOTEこれらのtdの各ノードのためだけのテキストです:

  1. やあ、これは、応答の\ nは、今、私は私が
  2. すごい何大きな反響を引用したものに対応しています次のよう

ザ・Pythonコードは、私はこれらのブロックを抽出する必要がある - それは私がlxml.html.text_contentを使用することを見つけ出すことができる唯一の方法だったので、最初に私は、lxmlの者のHtmlElementクラスにscrapyのHtmlResponseからそれを変換しました()メソッド:

import lxml.html as ht 

def posts_from_response(self, response): 
    dom = ht.fromstring(response.body) 
    posts = dom.xpath('//td[@class="postbody"]') 
    posts_text = [p.text_content() for p in posts] 
    return posts_text 

私は数日のために広くソリューションを探し、そして

さまざまな方法でそれに追加
'//td[@class="postbody"][not(@class="bbc-block")]' 

のダースのバリエーションについて試みたが、何もそのグループに私が欲しいものを正確に私を得ないしましたが欲しいです。

1.これを単一の文で取得する方法、または2. postsリストで2番目のXpathセレクタを実行してbbcブロックノードを除外する方法はありますか?

答えて

1

は、tryの直接の子であるテキストだけを取得するには:

//*[@class='postbody']/text() 

TD内のすべてのテキスト要素を取得しますが、「クラスBBC-ブロックでのdiv内のテキストを無視するには:

//td//text()[not(ancestor::*[@class='bbc-block'])]" 
+0

ありがとうございます! ! 2番目のステートメントは機能しました(わずかな構文変更にもかかわらず)。最初のxpath()呼び出しに.extract()を追加してから、Unicodeの結果を繰り返してHtmlElementオブジェクトを作成し、そのステートメントをそれらに適用しました。 – stuart

関連する問題