Scrapy> IndexError: список индексов вне диапазона - PullRequest
0 голосов
/ 11 февраля 2019

Я пытаюсь удалить некоторые данные TripAdvisor.Мне интересно получить "Диапазон цен / Кухня и питание" ресторанов.

Поэтому я использую следующий путь xpath для извлечения каждой из этих 3 строк в одном классе:

response.xpath('//div[@class="restaurants-detail-overview-cards-DetailsSectionOverviewCard__categoryTitle--14zKt"]/text()').extract()[1]

Я делаю тест непосредственно в оболочке Scrapy, и он работает нормально:

scrapy shell https://www.tripadvisor.com/Restaurant_Review-g187514-d15364769-Reviews-La_Gaditana_Castellana-Madrid.html

Но когда я интегрирую его в свой скрипт, у меня появляется следующая ошибка:

    Traceback (most recent call last):
  File "/usr/lib64/python3.6/site-packages/scrapy/utils/defer.py", line 102, in iter_errback
    yield next(it)
  File "/usr/lib64/python3.6/site-packages/scrapy/spidermiddlewares/offsite.py", line 29, in process_spider_output
    for x in result:
  File "/usr/lib64/python3.6/site-packages/scrapy/spidermiddlewares/referer.py", line 339, in <genexpr>
    return (_set_referer(r) for r in result or ())
  File "/usr/lib64/python3.6/site-packages/scrapy/spidermiddlewares/urllength.py", line 37, in <genexpr>
    return (r for r in result or () if _filter(r))
  File "/usr/lib64/python3.6/site-packages/scrapy/spidermiddlewares/depth.py", line 58, in <genexpr>
    return (r for r in result or () if _filter(r))
  File "/root/Scrapy_TripAdvisor_Restaurant-master/tripadvisor_las_vegas/tripadvisor_las_vegas/spiders/res_las_vegas.py", line 64, in parse_listing
    (response.xpath('//div[@class="restaurants-details-card-TagCategories__categoryTitle--o3o2I"]/text()')[1])
  File "/usr/lib/python3.6/site-packages/parsel/selector.py", line 61, in __getitem__
    o = super(SelectorList, self).__getitem__(pos)
IndexError: list index out of range

Я вставляю вам часть своего кода и объясняю это ниже:

# extract restaurant cuisine
    row_cuisine_overviewcard = \
    (response.xpath('//div[@class="restaurants-detail-overview-cards-DetailsSectionOverviewCard__categoryTitle--14zKt"]/text()')[1])
    row_cuisine_card = \
    (response.xpath('//div[@class="restaurants-details-card-TagCategories__categoryTitle--o3o2I"]/text()')[1])


    if (row_cuisine_overviewcard == "CUISINES"):
        cuisine = \
        response.xpath('//div[@class="restaurants-detail-overview-cards-DetailsSectionOverviewCard__tagText--1XLfi"]/text()')[1]
    elif (row_cuisine_card == "CUISINES"):
        cuisine = \
        response.xpath('//div[@class="restaurants-details-card-TagCategories__tagText--2170b"]/text()')[1]
    else:
        cuisine = None

В ресторанах tripAdvisor есть 2 разных типа страниц, с 2 разными форматами.Первый с картой обзора класса, второй с картами класса

Поэтому я хочу проверить, присутствует ли первый (карта обзора), если нет, выполнить вторую (карту) и, если нет, поставитьЗначение «None».

: D Но похоже, что Python выполняет оба .... и поскольку второй не существует на странице, сценарий останавливается.

Может ли это бытьошибка отступа?

Спасибо за вашу помощь С уважением

Ответы [ 2 ]

0 голосов
/ 11 февраля 2019

Ваша проблема уже в вашем чеке в этой строке_

row_cuisine_card = \
    (response.xpath('//div[@class="restaurants-details-card-TagCategories__categoryTitle--o3o2I"]/text()')[1])

Вы пытаетесь извлечь значение с веб-сайта, который может не существовать.Другими словами, если

response.xpath('//div[@class="restaurants-details-card-TagCategories__categoryTitle--o3o2I"]/text()')

возвращает нет или только один элемент, то вы не можете получить доступ ко второму элементу в возвращенном списке (к которому вы хотите получить доступ с добавленным [1]).

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

Это может выглядеть примерно так:

# extract restaurant cuisine
cuisine = None
cuisine_overviewcard_sections = response.xpath('//div[@class="restaurants-detail-overview-cards-DetailsSectionOverviewCard__categoryTitle--14zKt"]/text()'
if len(cuisine_overviewcard_sections) >= 2:
    row_cuisine_overviewcard = cuisine_overviewcard_sections[1]
    cuisine_card_sections = response.xpath('//div[@class="restaurants-details-card-TagCategories__categoryTitle--o3o2I"]/text()'
    if len(cuisine_card_sections) >= 2:
        row_cuisine_card = cuisine_card_sections[1]
        if (row_cuisine_overviewcard == "CUISINES"):
            cuisine = \
            response.xpath('//div[@class="restaurants-detail-overview-cards-DetailsSectionOverviewCard__tagText--1XLfi"]/text()')[1]
        elif (row_cuisine_card == "CUISINES"):
            cuisine = \
            response.xpath('//div[@class="restaurants-details-card-TagCategories__tagText--2170b"]/text()')[1]

Поскольку вам нужна только часть информации, если первая проверка XPath уже возвращает правильный ответ, код можно немного украсить:

# extract restaurant cuisine
cuisine = None
cuisine_overviewcard_sections = response.xpath('//div[@class="restaurants-detail-overview-cards-DetailsSectionOverviewCard__categoryTitle--14zKt"]/text()'
if len(cuisine_overviewcard_sections) >= 2 and cuisine_overviewcard_sections[1] == "CUISINES":
    cuisine = \
            response.xpath('//div[@class="restaurants-detail-overview-cards-DetailsSectionOverviewCard__tagText--1XLfi"]/text()')[1]
else:
    cuisine_card_sections = response.xpath('//div[@class="restaurants-details-card-TagCategories__categoryTitle--o3o2I"]/text()'
    if len(cuisine_card_sections) >= 2 and cuisine_card_sections[1] == "CUISINES":
        cuisine = \
            response.xpath('//div[@class="restaurants-details-card-TagCategories__tagText--2170b"]/text()')[1]

Таким образом вы выполняете (потенциально дорогой) поиск XPath только тогда, когда это действительно необходимо.

0 голосов
/ 11 февраля 2019

Ваш второй селектор (row_cuisine_card) не работает, потому что элемент не существует на странице.Затем, когда вы пытаетесь получить доступ к [1], в результате выдается ошибка, поскольку массив результатов пуст.

Если вы действительно хотите элемент 1, попробуйте это

row_cuisine_overviewcard = \
(response.xpath('//div[@class="restaurants-detail-overview-cards-DetailsSectionOverviewCard__categoryTitle--14zKt"]/text()')[1])
# Here we get all the values, even if it is empty.
row_cuisine_card = \
(response.xpath('//div[@class="restaurants-details-card-TagCategories__categoryTitle--o3o2I"]/text()').getall()) 


if (row_cuisine_overviewcard == "CUISINES"):
    cuisine = \
    response.xpath('//div[@class="restaurants-detail-overview-cards-DetailsSectionOverviewCard__tagText--1XLfi"]/text()')[1]
# Here we check first if that result has more than 1 item, and then we check the value.
elif (len(row_cuisine_card) > 1 and row_cuisine_card[1] == "CUISINES"):
    cuisine = \
    response.xpath('//div[@class="restaurants-details-card-TagCategories__tagText--2170b"]/text()')[1]
else:
    cuisine = None

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

...