Когда спайдер выдает ошибки при парсинге 2/3 страниц, то начинаются упреки и подозрения. Мне удалось "поймать" паука-халтурщика на странице Daewoo, здесь я сравниваю его поведение на страницах BMW и Daewoo. Трачу на это целый день. Оказалось, что я просто ошибся с "диагнозом". Не на всех страницах модификаций есть ссылки на цены. Спайдер выдавал ошибки, но продолжал работу. Оказалось, что при этом он может пропучкать сразу десятки страниц. Но целый день я искал отличия в коде страниц, здесь фрагменты кода и запросы XPath
item['disel'] = link.xpath('.//\
exceptions.UnboundLocalError: local variable 'link' referenced before assignment
# Вот такие ошибки были и на странице BMW, я проверил штуки три и выяснилось, что на них просто нет тега
<a href="35762/index.html" class="catalog-age__mod__item__equip clear">
# а это основной тег, вокнуг которого и проложены оси парсинга...
Хорошо, что прежде, чем писать обработку ошибок, я решил прогнать паука по всем модлеям, потом только по странице Daewoo. Здесь спайдер из 11 тегов спарсил только три... Файрбагом и Икпаз хелпером найти причину не смог. Пришлось писать этот пост.
Ниже фрагманты кода из двух страниц сайта.¶
Это страница седана Daewoo (file:///C:/Users/kiss/Desktop/carsmail/carsmail/cars.mail.ru/catalog/daewoo/nexia/ii/sedan/index.html)
<div class="catalog-age__mod__item__box">
<div class="catalog-age__mod__item__type clear">
<div class="catalog-age__mod__item__type__text catalog-age__mod__item__type__text_title">
<a href="specifications/indexbd21.html?gear_type=205&fuel=222&modification_id=15645" class="catalog-age__mod__item__type__link">1.5 MT</a>
</div>
<div class="catalog-age__mod__item__type__text catalog-age__mod__item__type__text_hp">80 л.с.</div>
</div>
<div class="catalog-age__mod__item__note">
Механика,
передний привод,
бензин, 12.5 с до 100 км/ч
</div>
<a href="35760/index.html" class="catalog-age__mod__item__equip clear">
<span>HC19 Classic</span>
<div class="catalog-age__mod__item__equip__price">
<span class="catalog-age__mod__item__equip__price__value">
<span class="rank"><i>289</i><i>000</i></span>
</span>
<span class="catalog-age__mod__item__equip__price__note">руб.</span>
</div>
</a>
<a href="35762/index.html" class="catalog-age__mod__item__equip clear">
<span>HC19/81</span>
<div class="catalog-age__mod__item__equip__price">
<span class="catalog-age__mod__item__equip__price__value">
<span class="rank"><i>329</i><i>000</i></span>
</span>
<span class="catalog-age__mod__item__equip__price__note">руб.</span>
</div>
</a>
<a href="35763/index.html" class="catalog-age__mod__item__equip clear">
<span>HC28/81</span>
<div class="catalog-age__mod__item__equip__price">
<span class="catalog-age__mod__item__equip__price__value">
<span class="rank"><i>342</i><i>000</i></span>
</span>
<span class="catalog-age__mod__item__equip__price__note">руб.</span>
</div>
</a>
<a href="35764/index.html" class="catalog-age__mod__item__equip clear">
<span>HC22/81</span>
<div class="catalog-age__mod__item__equip__price">
<span class="catalog-age__mod__item__equip__price__value">
<span class="rank"><i>356</i><i>000</i></span>
</span>
<span class="catalog-age__mod__item__equip__price__note">руб.</span>
</div>
</a>
<a href="35766/index.html" class="catalog-age__mod__item__equip clear">
<span>HC18</span>
<div class="catalog-age__mod__item__equip__price">
<span class="catalog-age__mod__item__equip__price__value">
<span class="rank"><i>360</i><i>000</i></span>
</span>
<span class="catalog-age__mod__item__equip__price__note">руб.</span>
</div>
</a>
<a href="35765/index.html" class="catalog-age__mod__item__equip clear">
<span>HC23/18</span>
<div class="catalog-age__mod__item__equip__price">
<span class="catalog-age__mod__item__equip__price__value">
<span class="rank"><i>368</i><i>000</i></span>
</span>
<span class="catalog-age__mod__item__equip__price__note">руб.</span>
</div>
</a>
<a href="35767/index.html" class="catalog-age__mod__item__equip clear">
<span>HC16</span>
<div class="catalog-age__mod__item__equip__price">
<span class="catalog-age__mod__item__equip__price__value">
<span class="rank"><i>386</i><i>000</i></span>
</span>
<span class="catalog-age__mod__item__equip__price__note">руб.</span>
</div>
</a>
</div>
А это шаблон для BMW, который я использовал для настройки ранее http://pythonr.blogspot.ru/2015/01/xpath_21.html#Вот-HTML-код-этого-фрагмента-для-парсинга¶
<div class="catalog-age__mod__item__box">
<div class="catalog-age__mod__item__type clear">
<div class="catalog-age__mod__item__type__text catalog-age__mod__item__type__text_title">
<a href="https://cars.mail.ru/catalog/bmw/3/f30_31/sedan/specifications/?gear_type=204&fuel=59&modification_id=22939" class="catalog-age__mod__item__type__link">320d 184hp xDrive AT</a>
</div>
<div class="catalog-age__mod__item__type__text catalog-age__mod__item__type__text_hp">184 л.с.</div>
</div>
<div class="catalog-age__mod__item__note">
Автомат,
полный привод,
дизель, 7.4 с до 100 км/ч
</div>
<a href="https://cars.mail.ru/catalog/bmw/3/f30_31/sedan/30440/" class="catalog-age__mod__item__equip clear">
<span>Sport Line SKD</span>
<div class="catalog-age__mod__item__equip__price">
<span class="catalog-age__mod__item__equip__price__value">
<span class="rank"><i>1</i><i>752</i><i>000</i></span>
</span>
<span class="catalog-age__mod__item__equip__price__note">руб.</span>
</div>
</a>
<a href="https://cars.mail.ru/catalog/bmw/3/f30_31/sedan/35796/" class="catalog-age__mod__item__equip clear">
<span>Modern Line SKD</span>
<div class="catalog-age__mod__item__equip__price">
<span class="catalog-age__mod__item__equip__price__value">
<span class="rank"><i>1</i><i>883</i><i>000</i></span>
</span>
<span class="catalog-age__mod__item__equip__price__note">руб.</span>
</div>
</a>
<a href="https://cars.mail.ru/catalog/bmw/3/f30_31/sedan/30439/" class="catalog-age__mod__item__equip clear">
<span>Luxury Line SKD</span>
<div class="catalog-age__mod__item__equip__price">
<span class="catalog-age__mod__item__equip__price__value">
<span class="rank"><i>1</i><i>950</i><i>000</i></span>
</span>
<span class="catalog-age__mod__item__equip__price__note">руб.</span>
</div>
</a>
</div>
from lxml import html
daewoo = html.fromstring(In[1])
bmw = html.fromstring(In[2])
Начнем с того, что работало в обоих случаях¶
#Сначала мы находим в цикле наш главнй тег класса
#это тег **a**, а не **div** !
<a href=".. ." class="catalog-age__mod__item__equip clear">
# Потом находим его старшего(предшественника) брата
# братьев div всего два, поэтому нам здесь и класс нужен
preceding-sibling::div[@class="catalog-age__mod__item__type clear"]
item['modification'] = link.xpath('.//\
preceding-sibling::div[@class="catalog-age__mod__item__type clear"] \
/div[@class="catalog-age__mod__item__type__text catalog-age__mod_\
_item__type__text_title"]/a/text()').extract()
bmw.xpath('.//\
preceding-sibling::div[@class="catalog-age__mod__item__type clear"] \
/div[@class="catalog-age__mod__item__type__text catalog-age__mod_\
_item__type__text_title"]/a/text()')
daewoo.xpath('.//\
preceding-sibling::div[@class="catalog-age__mod__item__type clear"] \
/div[@class="catalog-age__mod__item__type__text catalog-age__mod_\
_item__type__text_title"]/a/text()')
bmw.xpath('//\
preceding-sibling::div[@class="catalog-age__mod__item__type clear"] \
/div[@class="catalog-age__mod__item__type__text catalog-age__mod_\
_item__type__text_title"]/a/text()')
Видим, что все работает, как и ожидалось. Отметим, что код здесь мы немного упростили. Уьрали .extract() Однако, не понимаю, почемы находится только первый элемент из списка. Попробуем цикл, как в carmailPrice spider
Соберем все элементы в цикле¶
bmw_link_list = bmw.xpath('.//a[@class="catalog-age__mod__item__equip clear"]')
for link in bmw_link_list:
print link.xpath('//\
preceding-sibling::div[@class="catalog-age__mod__item__type clear"] \
/div[@class="catalog-age__mod__item__type__text catalog-age__mod_\
_item__type__text_title"]/a/text()')
daewoo_link_list = daewoo.xpath('.//a[@class="catalog-age__mod__item__equip clear"]')
for link in daewoo_link_list:
print link.xpath('//\
preceding-sibling::div[@class="catalog-age__mod__item__type clear"] \
/div[@class="catalog-age__mod__item__type__text catalog-age__mod_\
_item__type__text_title"]/a/text()')
daewoo_link_list
Теперь пробуем то, что выдавало ошибку¶
item['link_to_spec'] = link.xpath('.//\
preceding-sibling::div[@class="catalog-age__mod__item__type clear"]/\
div[@class="catalog-age__mod__item__type__text catalog-age__mod__item__type__text_title"]\
/a/@href').extract()
bmw.xpath('.//\
preceding-sibling::div[@class="catalog-age__mod__item__type clear"]/\
div[@class="catalog-age__mod__item__type__text catalog-age__mod__item__type__text_title"]\
/a/@href')
daewoo.xpath('.//\
preceding-sibling::div[@class="catalog-age__mod__item__type clear"]/\
div[@class="catalog-age__mod__item__type__text catalog-age__mod__item__type__text_title"]\
/a/@href')
# Этот путь ведет от каждого главного тега к первому тегу div
# мы его отличаем по классу
div[@class="catalog-age__mod__item__type clear"]
# а в него влолжен div с двумя длиннющими классами
div[@class="catalog-age__mod__item__type__text catalog-age__mod__item__type__text_title"]
# их бы заменить ?
#
for link in daewoo_link_list:
print link.xpath('.//\
preceding-sibling::div[@class="catalog-age__mod__item__type clear"]/\
div[@class="catalog-age__mod__item__type__text catalog-age__mod__item__type__text_title"]\
/a/@href')
Не понимаю, почему здесь все работает, пока пойдем дальше. Когда я закоментировал эту строчку, то ошибку стал выдавать вот этот код:
# Автомат, полный привод, дизель, 7.4 с до 100 км/ч
item['disel'] = link.xpath('.//\
preceding-sibling::div[@class="catalog-age__mod__item__note"]/text()').extract()
for link in daewoo_link_list:
print link.xpath('.//\
preceding-sibling::div[@class="catalog-age__mod__item__note"]/text()') # и здесь я тоже убрал .extract()
d = daewoo.xpath('.//\
preceding-sibling::div[@class="catalog-age__mod__item__note"]/text()') # и здесь я тоже убрал .extract()
print ' '.join(d)
bmw_link_list_a = bmw.xpath('//a[@class="catalog-age__mod__item__equip clear"]')
bmw_link_list_a
#bmw
# Все модели на странице
# file:///C:/Users/kiss/Desktop/carsmail/carsmail/cars.mail.ru/catalog/bmw/index.html
----------------------------
catalog-generation
catalog-generation__title
catalog-generation__list
...
...
catalog-generation__title
catalog-generation__list
---------------------------
catalog-age__mod__list js-catalog_mod_list
catalog-age__mod__list js-catalog_mod_list
bmw.xpath('.//\
preceding-sibling::div[@class="catalog-age__mod__item__type clear"]/\
div[@class="catalog-age__mod__item__type__text catalog-age__mod__item_\
_type__text_hp"]/text()')
Посты чуть ниже также могут вас заинтересовать
Комментариев нет:
Отправить комментарий