Получить весь текст внутри тега в lxml - PullRequest
64 голосов
/ 07 января 2011

Я хотел бы написать фрагмент кода, который будет захватывать весь текст внутри тега <content> в lxml во всех трех нижеприведенных случаях, включая теги кода. Я пробовал tostring(getchildren()), но это пропустило бы текст между тегами. Мне не очень повезло, что я искал в API соответствующую функцию. Не могли бы вы помочь мне?

<!--1-->
<content>
<div>Text inside tag</div>
</content>
#should return "<div>Text inside tag</div>

<!--2-->
<content>
Text with no tag
</content>
#should return "Text with no tag"


<!--3-->
<content>
Text outside tag <div>Text inside tag</div>
</content>
#should return "Text outside tag <div>Text inside tag</div>"

Ответы [ 14 ]

0 голосов
/ 08 октября 2017

lxml имеет метод для этого:

node.text_content()
0 голосов
/ 18 августа 2017

Вот рабочее решение.Мы можем получить содержимое с помощью родительского тега, а затем вырезать родительский тег из вывода.

import re
from lxml import etree

def _tostr_with_tags(parent_element, html_entities=False):
    RE_CUT = r'^<([\w-]+)>(.*)</([\w-]+)>$' 
    content_with_parent = etree.tostring(parent_element)    

    def _replace_html_entities(s):
        RE_ENTITY = r'&#(\d+);'

        def repl(m):
            return unichr(int(m.group(1)))

        replaced = re.sub(RE_ENTITY, repl, s, flags=re.MULTILINE|re.UNICODE)

        return replaced

    if not html_entities:
        content_with_parent = _replace_html_entities(content_with_parent)

    content_with_parent = content_with_parent.strip() # remove 'white' characters on margins

    start_tag, content_without_parent, end_tag = re.findall(RE_CUT, content_with_parent, flags=re.UNICODE|re.MULTILINE|re.DOTALL)[0]

    if start_tag != end_tag:
        raise Exception('Start tag does not match to end tag while getting content with tags.')

    return content_without_parent

parent_element должно иметь тип Element.

Обратите внимание, что если вы хотите текстовое содержимое (не html-объекты в тексте), пожалуйста, оставьте параметр html_entities как False.

0 голосов
/ 08 января 2015
import re
from lxml import etree

node = etree.fromstring("""
<content>Text before inner tag
    <div>Text
        <em>inside</em>
        tag
    </div>
    Text after inner tag
</content>""")

print re.search("\A<[^<>]*>(.*)</[^<>]*>\Z", etree.tostring(node), re.DOTALL).group(1) 
0 голосов
/ 14 ноября 2012

Если это тег, вы можете попробовать:

node.values()
...