2011-08-11 39 views
12

我正在使用lxml.html庫來解析HTML文檔。Python:使用`lxml.html`將HTML內容注入到標記中

我所在的特定的標籤,我稱之爲content_tag,我想改變它的內容(即<div></div>,之間的文本)和新的內容與它的一些HTML字符串,說這是'Hello <b>world!</b>'

我該怎麼做?我試圖content_tag.text = 'Hello <b>world!</b>'但隨後逃脫所有的HTML標籤,與&lt;

我要注入文本更換<沒有逃避任何HTML。我怎樣才能做到這一點?

+0

_nice_方式,因爲你真的試圖修改DOM結構,將爲'world'添加一個新的子節點。 – katrielalex

+0

我該怎麼做? –

回答

8

這是一種方式:

#!/usr/bin/env python2.6 
from lxml.html import fromstring, tostring 
from lxml.html import builder as E 
fragment = """\ 
<div id="outer"> 
    <div id="inner">This is div.</div> 
</div>""" 

div = fromstring(fragment) 
print tostring(div) 
# <div id="outer"> 
# <div id="inner">This is div.</div> 
# </div> 
div.replace(div.get_element_by_id('inner'), E.DIV('Hello ', E.B('world!'))) 
print tostring(div) 
# <div id="outer"> 
# <div>Hello <b>world!</b></div></div> 

參見:http://lxml.de/lxmlhtml.html#creating-html-with-the-e-factory

編輯:所以,我應該早一點,我不是所有熟悉LXML供認不諱。我簡要地看了一下文檔和源代碼,但沒有找到一個乾淨的解決方案。也許,更熟悉的人會停下來,讓我們兩個都挺直。

在此期間,這似乎是工作,但沒有得到很好的測試:再次

import lxml.html 
content_tag = lxml.html.fromstring('<div>Goodbye.</div>') 
content_tag.text = '' # assumes only text to start 
for elem in lxml.html.fragments_fromstring('Hello <b>world!</b>'): 
    if type(elem) == str: #but, only the first? 
     content_tag.text += elem 
    else: 
     content_tag.append(elem) 
print lxml.html.tostring(content_tag) 

編輯:這個版本中刪除的文字和兒童

somehtml = 'Hello <b>world!</b>' 
# purge element contents 
content_tag.text = '' 
for child in content_tag.getchildren(): 
    content_tag.remove(child) 

fragments = lxml.html.fragments_fromstring(somehtml) 
if type(fragments[0]) == str: 
    content_tag.text = fragments.pop(0) 
content_tag.extend(fragments) 
+0

這種方式對我來說不起作用有兩個原因:(1)我不想替換標籤,我想替換標籤的內容和(2)我想注入的html片段已經在文本形式,我不想用'E'來構建它。 –

+0

@Ram Rachum:更新了答案,希望對您有所幫助。 – Marty

0

假設content_tag不有任何子元素,你可以這樣做:

from lxml import html 
from lxml.html.builder import B 

... 

content_tag.text = 'Hello ' 
content_tag.append(B('world!')) 
print html.tostring(content_tag) 
+0

沒有幫助 - 我的HTML文本不是事先知道的,我不能將它構造爲代碼中的HTML結構。 –

+0

啊,但你沒有在你的問題中說明(「事先不知道」部分)。 – sayap

+0

mwalsh的編輯答案看起來不錯,應該適用於任意html。 – sayap

0

經過修改後,我發現這個解決方案:

fragments = lxml.html.fragments_fromstring(<string with tags to inject>) 
last = None 

for frag in fragments: 
    if isinstance(frag, lxml.etree._Element): 
    content_tag.append(frag) 
    last = frag 
    else: 
    if last: 
     last.tail = frag 
    else: 
     content_tag.text = frag