lxml.etree, element.text не возвращает весь текст элемента - PullRequest
14 голосов
/ 22 января 2011

Я удалил html через xpath, который затем преобразовал в etree. Нечто похожее на это:

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

но когда я вызываю element.text, я получаю только text1 (он должен быть там, когда я проверяю свой запрос в FireBug, текст элементов подсвечивается, как текст до, так и после встроенных якорных элементов ...

Ответы [ 8 ]

15 голосов
/ 23 января 2011

Используйте element.xpath("string()") или lxml.etree.tostring(element, method="text") - см. документацию .

6 голосов
/ 06 октября 2013

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

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("text()")
print get_text1(root)
print get_text2(root)
print root.xpath("string()")
print etree.tostring(root, method = "text")
print etree.tostring(root, method = "xml")
print get_text3(root)

Вывод:

snowy:rpg$ python test.py 
[' text1 ', ' text2 ']
 text1  text2 
 text1  link  text2 
 text1  link  text2 
 text1  link  text2 
<td> text1 <a> link </a> text2 </td>
 text1 <a> link </a> text2 
5 голосов
/ 21 сентября 2011

выглядит для меня как ошибка 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
4 голосов
/ 06 апреля 2014

Другая вещь, которая, кажется, работает хорошо, чтобы получить текст из элемента, это "".join(element.itertext())

2 голосов
/ 08 декабря 2013
<td> text1 <a> link </a> text2 </td>

Вот как это делается (игнорируя пробелы):

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

Если вам не нужен текст внутри дочерних элементов, вы можете собрать только их хвосты:

text = td.text + ''.join([el.tail for el in td])
1 голос
/ 26 января 2012
def get_text_recursive(node):
    return (node.text or '') + ''.join(map(get_text_recursive, node)) + (node.tail or '')
0 голосов
/ 24 июля 2017
element.xpath('normalize-space()') also works.
0 голосов
/ 23 мая 2017

Если element равно <td>. Вы можете сделать следующее.

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

Это даст вам список всех текстовых элементов от self (значение точки). // означает, что он будет принимать все элементы и, наконец, text() - это функция для извлечения текста.

...