CSS селектор или XPath, который получает информацию между двумя тегами i? - PullRequest
3 голосов
/ 11 июля 2020

Я пытаюсь очистить информацию о ценах, а HTML веб-сайта выглядит так:

<span class="def-price" datasku='....'>
   <i>$</i>
   "999"
   <i>.00<i>
</span>

Я хочу получить 999. (Мне не нужен знак доллара или. 00) Сейчас у меня

product_price_sn = product.css('.def-price i').extract()

Я знаю, что это неправильно, но не знаю, как это исправить. Есть идеи, как очистить эту информацию о ценах? Спасибо!

Ответы [ 3 ]

1 голос
/ 11 июля 2020

Вы можете использовать этот xpath //span[@class="def-price"]/text()

Убедитесь, что вы используете /text(), а не //text(). В противном случае он вернет все текстовые узлы внутри тега span.

или

Это css селектор .def-price::text. При использовании селектора css не используйте .def-price ::text, он вернет все текстовые узлы, такие как //text() в xpath.

Использование объекта scrapy response.xpath

from scrapy.http import Request, HtmlResponse as Response

content = '''<span class="def-price" datasku='....'>
   <i>$</i>
   "999"
   <i>.00<i>
</span>'''.encode('utf-8')

url = 'https://stackoverflow.com/questions/62849500'

''' mocking scrapy request object '''
request = Request(url=url)

''' mocking scrapy response object '''
response = Response(url=url, request=request, body=content)

''' using xpath  '''

print(response.xpath('//span[@class="def-price"]/text()').extract())
# outputs ['\n   ', '\n   "999"\n   ']

print(''.join(response.xpath('//span[@class="def-price"]/text()').extract()).strip())
# outputs "99"

''' using css selector '''

print(response.css('.def-price::text').extract())
# outputs ['\n   ', '\n   "999"\n   ']

print(''.join(response.css('.def-price::text').extract()).strip())
# outputs "99"

Посмотрите в действии здесь

Используя l xml html parser

from lxml import html

parser = html.fromstring("""
<span class="def-price" datasku='....'>
   <i>$</i>
   "999"
   <i>.00<i>
</span>
"""
)

print(parser.xpath('//span[@class="def-price"]/text()'))
# outputs ['\n   ', '\n   "999"\n   ']

print(''.join(parser.xpath('//span[@class="def-price"]/text()')).strip())
# outputs "999"

Посмотреть в действии здесь

0 голосов
/ 11 июля 2020

С BeautifulSoup вы можете использовать селектор CSS .def_price, а затем .find_all(text=True, recursive=0), чтобы сразу получить весь текст.

Например:

from bs4 import BeautifulSoup


txt = '''<span class="def-price" datasku='....'>
   <i>$</i>
   "999"
   <i>.00<i>
</span>'''

soup = BeautifulSoup(txt, 'html.parser')

print( ''.join(soup.select_one('.def-price').find_all(text=True, recursive=0)).strip() )

Печать:

"999"
0 голосов
/ 11 июля 2020

Scrapy реализует расширение для этого, поскольку оно не стандартно для селекторов CSS. Так что это должно сработать для вас:

product_price_sn = product.css('.def-price i::text').extract()

Вот что говорят docs :

Согласно стандартам W3 C, CSS селекторы делают не поддерживает выбор текстовых узлов или значений атрибутов. Но их выбор настолько важен в контексте парсинга, что Scrapy (parsel) реализует пару нестандартных псевдоэлементов:

для выбора текстовых узлов, используйте :: text

для выбора значения атрибутов, используйте :: attr (name), где name - это имя атрибута, значение которого вы хотите получить

...