lxml разделяет элементы, а Beautifulsoup - нет

lxml возвращает два элемента, а beautifulsoup возвращает только один. Это потому что <br/> там не должно быть и Beautifulsoup более терпим к плохим HTML?

Есть ли лучший способ извлечь местоположение с помощью lxml? <br/> не всегда там

from lxml import html
from bs4 import BeautifulSoup as bs

s = '''<td class="location">
    <p>
    TRACY,<br/>&nbsp;CA&nbsp;95304&nbsp;
    </p></td>
'''

tree = html.fromstring(s)
r = tree.xpath('//td[@class="location"]/p/text()')
print r

soup = bs(s, 'lxml')
r = soup.find_all('td', class_='location')[0].get_text()
print r

2 ответа

Решение

Есть ли лучший способ извлечь местоположение с помощью lxml? <br/> не всегда там

Если под лучшим вы подразумеваете возвращение результата, который ближе к его аналогу BS, то выражение XPath, которое лучше напоминает ваш код BS:

>>> print tree.xpath('string(//td[@class="location"])')


    TRACY, CA 95304 

Кроме того, если вы хотите удалить лишние пробелы, используйте normalize-space() вместо string():

>>> print tree.xpath('normalize-space(//td[@class="location"])')
TRACY, CA 95304 

element.get_text() объединяет отдельные цепочки строк; из документации:

Если вам нужна только текстовая часть документа или тега, вы можете использовать метод get_text(). Возвращает весь текст в документе или под тегом в виде одной строки Unicode

Акцент мой.

Использовать Tag.strings генератор, если вы хотите отдельные строки:

>>> list(soup.find_all('td', class_='location')[0].strings)
[u'\n', u'\n    TRACY,', u'\xa0CA\xa095304\xa0\n    ']

Если вы хотите, чтобы lxml присоединился к тексту, просто присоедините текст:

r = ''.join(tree.xpath('//td[@class="location"]/p/text()'))

string() Функция XPath может сделать то же самое для <td> тег:

r = tree.xpath('string(//td[@class="location"])')

Демо-версия:

>>> ''.join(tree.xpath('//td[@class="location"]/p/text()'))
u'\n    TRACY,\xa0CA\xa095304\xa0\n    '
>>> tree.xpath('string(//td[@class="location"])')
u'\n    \n    TRACY,\xa0CA\xa095304\xa0\n    '

Я бы использовал str.strip() на любой результат:

>>> tree.xpath('string(//td[@class="location"])').strip()
u'TRACY,\xa0CA\xa095304'
>>> print tree.xpath('string(//td[@class="location"])').strip()
TRACY, CA 95304

или используйте normalize-space() Функция XPath:

>>> tree.xpath('normalize-space(string(//td[@class="location"]))')
u'TRACY,\xa0CA\xa095304\xa0'

Обратите внимание, что str.strip() удаляет завершающий неразрывный \xa0 пространство, а normalise-space() оставляет это.

Другие вопросы по тегам