2011-01-22 9 views
10

xpath経由でhtmlをいくつか破棄してから、それをetreeに変換しました。これに似た何か:lxml.etree、element.textは要素からテキスト全体を返しません

<td> text1 <a> link </a> text2 </td> 

が、私はelement.textを呼んで、私はテキスト1(私は放火犯で私のクエリをチェックするときには、そこにする必要があり、要素のテキストが強調表示され、両方の前にテキストを取得しますそして

+0

これはこれを行うための1つの方法です(小さなPythonスクレイププロセッサのコードスニペット)。これがlxmlのバグなら驚くでしょうか? element.tag場合== "TD" – user522034

+0

はここにコードスニペットです \t \t \t \t \tトピック= (element.text +子供[0] .tail)他 \t \t \t \t: \t \t \t \t \tトピック= eleme nt。テキスト()\t \t \t \t print( "\ tTopic:\ t \ t%s"%topic) – user522034

+0

::(子供)lenの場合> \t \t \t \t子供= element.getchildren() \t \t \t \t 0: – user522034

答えて

15

使用element.xpath("string()")またはlxml.etree.tostring(element, method="text") ...埋め込まれたアンカー要素の後に - 。the documentationを参照してください

+0

toString(element、method = "text")はほとんど機能しますが、埋め込みアンカー要素のテキストも返します。ほしくない。 – user522034

+0

element.text + child.tailはうまくいきますが、私はそれが欲しい方法でelement.textを使いたいと思っています:) – user522034

+0

element.xpath( "string()")は* .tostring()と同じ結果を返します。アンカー要素のテキストを返さないxpath( "text()")を試しましたが、2つの文字列のリストを返します。しかし、いくつかのものを指摘してくれてありがとう。 – user522034

5

私にlxmlのバグのように見えますが、あなたはドキュメントを読めば、設計に応じて、私はこのようにそれを解決してきました。 :

def node_text(node): 
    if node.text: 
     result = node.text 
    else: 
     result = '' 
    for child in node: 
     if child.tail is not None: 
      result += child.tail 
    return result 
+1

これはバグではありません。実際には、XML要素を構築する際に、サブ要素間にテキストを挿入する機能です。http://stackoverflow.com/q/38520331/694360 – mmj

+0

ありがとうございます。私はそれが便利だと思いますが、 '.text'が完全なテキストを返すだけで、他の適切に名前を付けられたプロパティが最初のサブ要素までの部分だけを含んでいれば、もっと明確になります。 'node.head'はどうですか?これはまた、まずstackoverflowすることなく、次にchild.tailになることを手掛かりにします。 –

1
def get_text_recursive(node): 
    return (node.text or '') + ''.join(map(get_text_recursive, node)) + (node.tail or '') 
5

私のように怠け者かもしれない人々への公的サービスとして。上記のコードを実行することができます。

from lxml import etree 

def get_text1(node): 
    result = node.text or "" 
    for child in node: 
     if child.tail is not None: 
      result += child.tail 
    return result 

def get_text2(node): 
    return ((node.text or '') + 
      ''.join(map(get_text2, node)) + 
      (node.tail or '')) 

def get_text3(node): 
    return (node.text or "") + "".join(
     [etree.tostring(child) for child in node.iterchildren()]) 


root = etree.fromstring(u"<td> text1 <a> link </a> text2 </td>") 

print root.xpath("string()") 
print root.xpath("text()") 
print get_text1(root) 
print get_text2(root) 
print etree.tostring(root, method = "text") 
print etree.tostring(root, method = "xml") 
print get_text3(root) 

出力は次のようになります。ここでは

snowy:rpg$ python test.py 
text1 link text2 
[' text1 ', ' text2 '] 
text1 text2 
text1 link text2 
text1 link text2 
<td> text1 <a> link </a> text2 </td> 
text1 <a> link </a> text2 
1
<td> text1 <a> link </a> text2 </td> 

は、それが(空白を無視して)された方法は次のとおりです。

td.text == 'text1' 
a.text == 'link' 
a.tail == 'text2' 

あなたは、子要素内にあるテキストを使用しない場合あなたは尾だけを集めることができます:

<td>に等しい場合
3

要素からテキストを取得するためにうまく動作しているようだもう一つは、"".join(element.itertext())

0

です。あなたは以下を行うことができます。

element.xpath('.//text()') 

それはあなたのself(ドットの意味)からすべてのテキスト要素のリストを提供します。 //はすべての要素を取り、最後にtext()がテキストを抽出する関数であることを意味します。

0
element.xpath('normalize-space()') also works. 
+3

貼り付けるコードだけでは不十分です。あなたはなぜそれが動作するか説明する必要があります:) –

関連する問題