Разбор lxml.etree._Element содержимого - PullRequest
4 голосов
/ 04 января 2012

У меня есть следующий элемент, который я проанализировал из <table>

<td align="center" valign="top">
  <a href="ConfigGroups.aspx?cfgID=451161&amp;prjID=11778&amp;grpID=DTST" 
    target="_blank">
    5548U
  </a><br/>Power La Vaca<br/>(M8025K)<br/>Linux 4.2.x.x<br/>
</td>

Я пытаюсь извлечь из этого элемента «55488 Power La Vaca (8025K) Linux 4.2.x.x» (включая пробелы).

import lxml.etree as ET
td_html = """
<td align="center" valign="top">
  <a href="ConfigGroups.aspx?cfgID=451161&amp;prjID=11778&amp;grpID=DTST" 
    target="_blank">
    5548U
  </a><br/>Power La Vaca<br/>(M8025K)<br/>Linux 4.2.x.x<br/>
</td>
"""

td_elem = ET.fromstring(td_html)

fail_1 = td_elem.find('a').text + td_elem.text
print "FAIL_1", fail_1

print "FAIL_2"
for elem in td_elem.iterchildren():
    print elem.tag, elem.text

Результаты

$ python textxml.py

FAIL_1
    5548U


FAIL_2
a
    5548U

br None
br None
br None
br None
$

Вопрос

Унизительно, что я должен задать этот вопрос, поскольку не похоже, что это должно быть трудно.

Как извлечь «Power La Vaca (8025K) Linux 4.2.x.x» из элемента td_elem (включая пробелы)?

Пожалуйста, никаких регулярных выражений.

Решение

Явное решение (используя предложение Финна itertext()):

import lxml.etree as ET
td_html = """
<td align="center" valign="top">
  <a href="ConfigGroups.aspx?cfgID=451161&amp;prjID=11778&amp;grpID=DTST" 
    target="_blank">
    5548U
  </a><br/>Power La Vaca<br/>(M8025K)<br/>Linux 4.2.x.x<br/>
</td>
"""

td_elem = ET.fromstring(td_html)
print "SUCCESS", ' '.join([txt.strip() for txt in td_elem.itertext()])

Ответы [ 2 ]

3 голосов
/ 04 января 2012

При работе с XML, даже в Python, мне нравится пытаться использовать доступные инструменты для конкретного домена. Для разбора битов XML XPath для меня.

>>> td_elem = ET.fromstring(td_html)
>>>
>>> # Use XPath to grab just the text nodes under <td/>, 
>>> # ignoring any text nodes in child nodes of <td/> (i.e., <a...>5548U</a>)
>>> print(td_elem.xpath('/td/text()'))
['\n  ', 'Power La Vaca', '(M8025K)', 'Linux 4.2.x.x', '\n']
>>>
>>> # Make it a little cleaner
>>> ' '.join(x.strip() for x in td_elem.xpath('/td/text()'))
' Power La Vaca (M8025K) Linux 4.2.x.x '
>>>
>>> # Just for reference, grab all text nodes with '//'
>>> ' '.join(x.strip() for x in td_elem.xpath('/td//text()'))
' 5548U Power La Vaca (M8025K) Linux 4.2.x.x '
3 голосов
/ 04 января 2012

Я знаю, что должен быть лучший способ, но это работает.

link = td_elem.find('a').text.strip()
text = ''.join(td_elem.itertext()).strip()
text.split(link)[1]

Вывод Мощность La Vaca (M8025K) Linux 4.2.xx

Обновление:Это на самом деле лучше, если вы хотите, чтобы вместо этих <br> s

' '.join(map(str, [el.tail for el in td_elem.iterchildren() if el.tail]))

map str фактически не было необходимости, но я могу представить другие значения, для которых это будет,

...