Ответ 1
Используйте element.xpath("string()")
или lxml.etree.tostring(element, method="text")
- см. документацию.
Я сломал некоторый html через xpath, и затем преобразовал его в этер. Что-то похожее на это:
<td> text1 <a> link </a> text2 </td>
но когда я вызываю element.text, я получаю text1 (он должен быть там, когда я проверяю свой запрос в FireBug, текст элементов выделяется, как текст до, так и после встроенных элементов привязки...
Используйте element.xpath("string()")
или lxml.etree.tostring(element, method="text")
- см. документацию.
Как общественная служба для людей, которые могут быть такими ленивыми, как я. Вот код сверху, который вы можете запустить.
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
выглядит как ошибка 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
Другая вещь, которая, кажется, хорошо работает, чтобы получить текст из элемента, - "".join(element.itertext())
def get_text_recursive(node):
return (node.text or '') + ''.join(map(get_text_recursive, node)) + (node.tail or '')
<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])
Если element
равно <td>
. Вы можете сделать следующее.
element.xpath('.//text()')
Он предоставит вам список всех текстовых элементов из self
(значение точки). //
означает, что он примет все элементы и, наконец, text()
- это функция для извлечения текста.
element.xpath('normalize-space()') also works.