lxml classic: получить текстовое содержимое, кроме вложенных тегов? - PullRequest
3 голосов
/ 15 ноября 2011

Это должно быть абсолютной классикой, но я не могу найти ответ здесь.Я анализирую следующий тег с помощью lxml cssselect:

<li><a href="/stations/1"><span class="num">3</span> Detroit</a></li>

Я хочу получить содержимое <li> тега без содержимое тега <span>.

В настоящее время у меня есть:

stop_list = doc.cssselect('ol#stations li a')
start = stop_list[0].text_content().strip()

Но это дает мне 3 Detroit.Как я могу просто получить Detroit?

Ответы [ 2 ]

3 голосов
/ 15 ноября 2011

Я не очень знаком с lxml, но это работает в IDLE (v2.7.2). Я думаю, что использовать XPath лучше, чем CSS:

>>> xml = '<li><a href="/stations/1"><span class="num">3</span> Detroit</a></li>'
>>> root = etree.fromstring(xml)
>>> print( root.xpath('/li/a/text()'))
[' Detroit']

Похоже, что после выбора нужно меньше сомнений.

РЕДАКТИРОВАТЬ 1

Вот немного другой пример, который может повлиять на ваше решение:

>>> xml = '<li><a href="/stations/1">I <span>FooBar!</span> love <span class="num">3</span> Detroit</a></li>'
>>> root = etree.fromstring(xml)
>>> print( root.xpath('/li/a/text()'))
['I ', ' love ', ' Detroit']
>>> ' '.join([x.strip() for x in root.xpath('/li/a/text()')])
'I love Detroit'

Надеюсь, это поможет,
Zachary

3 голосов
/ 15 ноября 2011

itertext метод элемента возвращает итератор текстовых данных узла.Для вашего <a> тега ' Detroit' будет вторым значением, возвращаемым итератором.Если структура вашего документа всегда соответствует известной спецификации, вы можете пропустить определенные текстовые элементы, чтобы получить то, что вам нужно.

from lxml import html

doc = html.fromstring("""<li><a href="/stations/1"><span class="num">3</span> Detroit</a></li>""")
stop_nodes = doc.cssselect('li a') 
stop_names = []
for start in stop_list:
    node_text = start.itertext()
    node_text.next() # Skip '3'
    stop_names.append(node_text.next().lstrip())
    continue

Вы можете комбинировать селектор css с функцией xpath text(), упомянутой в Ответ Захария следующим образом (Если вам удобнее использовать селекторы CSS, чем xpath):

stop_names = [a.xpath('text()').lstrip() for a in doc.cssselect('li a')]
...