2011-08-11 62 views
12

Tôi đang sử dụng thư viện lxml.html để phân tích cú pháp tài liệu HTML.Python: Đưa nội dung HTML vào thẻ bằng cách sử dụng `lxml.html`

Tôi nằm một từ khóa cụ thể, mà tôi gọi là content_tag, và tôi muốn thay đổi nội dung của nó (ví dụ: văn bản giữa <div></div>,) và các nội dung mới là một chuỗi với một số html trong nó, nói nó 'Hello <b>world!</b>'.

Tôi làm như thế nào? Tôi cố gắng content_tag.text = 'Hello <b>world!</b>' nhưng sau đó nó thoát tất cả các thẻ html, thay thế < với &lt;, vv

tôi muốn tiêm văn bản mà không thoát bất kỳ HTML. Làm thế nào tôi có thể làm điều đó?

+0

Cách _nice_, vì bạn thực sự cố gắng sửa đổi cấu trúc DOM, sẽ thêm nút con mới cho 'world'. – katrielalex

+0

Tôi làm như thế nào? –

Trả lời

8

Đây là một cách:

#!/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> 

Xem thêm: http://lxml.de/lxmlhtml.html#creating-html-with-the-e-factory

Edit: Vì vậy, tôi phải thú nhận trước đó rằng tôi không tất cả những gì quen thuộc với lxml. Tôi đã xem xét các tài liệu và nguồn một thời gian ngắn, nhưng không tìm thấy một giải pháp sạch. Có lẽ, một người quen thuộc hơn sẽ dừng lại và đặt chúng tôi cả hai thẳng.

Trong khi đó, điều này dường như để làm việc, nhưng cũng không phải là thử nghiệm:

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) 

Chỉnh sửa lần nữa: và phiên bản này loại bỏ văn bản và con

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

Cách đó không hiệu quả với tôi vì 2 lý do: (1) Tôi không muốn thay thế thẻ, tôi muốn thay thế nội dung của thẻ và (2) Đoạn html mà tôi muốn tiêm đã có sẵn dạng văn bản, tôi không muốn xây dựng nó bằng 'E'. –

+0

@Ram Rachum: câu trả lời được cập nhật, hy vọng nó hữu ích. – Marty

0

Giả sử content_tag không có bất kỳ phân bổ nào, bạn chỉ có thể thực hiện:

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

Không giúp được - Văn bản HTML của tôi không được biết trước và tôi không thể tạo văn bản đó dưới dạng cấu trúc HTML trong mã. –

+0

Ahh, nhưng bạn đã không xác định điều đó trong câu hỏi của bạn (phần "không được biết trước"). – sayap

+0

Câu trả lời được chỉnh sửa của mwalsh có vẻ tốt và nên hoạt động với html tùy ý. – sayap

0

Sau khi dò tìm xung quanh, tôi tìm thấy giải pháp này:

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 
Các vấn đề liên quan