2014-11-16 2 views
2

Я пытаюсь разобрать эту страницу с помощью Scrapy http://mobileshop.ae/one-xПочему результаты response.xpath ('// html') отличаются от response.body?

Мне нужно извлечь ссылки из продуктов. Проблема заключается в том, что ссылки доступны в отчете response.body, но не доступны, если вы попробуете response.xpath ('// body'). Extract()

Результаты response.body и response.xpath ('// body') различны.

>>> body = response.body 
>>> body_2 = response.xpath('//html').extract()[0] 
>>> len(body) 
238731 
>>> len(body_2) 
67520 

же короткий результат для response.xpath (''). Экстракт() [0]

есть какие-либо идеи, почему это происходит, и как я могу извлечь нужны данные?

+0

Похоже, проблема связана с недопустимой разметкой HTML на этой странице - у нее есть несколько тегов, которые не были закрыты (проверьте это с помощью http://validator.w3.org). – elias

+0

Как вы думаете, я должен это исправить? вы рекомендуете библиотеку, которая может исправить этот недопустимый html? – Vanddel

+0

Итак, оказывается, что у lxml есть способ обойти это - lemme добавить правильный ответ. – elias

ответ

3

Таким образом, проблема заключается в том, что на этой странице много некорректного контента, включая несколько незакрытых тегов. Один из способов решения этой проблемы - использовать lxml's soupparser для синтаксического анализа несоответствующего содержимого (используя BeautifulSoup под обложками) и создать с ним селектор Scrapy.

Пример сеанса с scrapy shell http://mobileshop.ae/one-x:

>>> from lxml.html import soupparser 
>>> from scrapy import Selector 
>>> sel = Selector(_root=soupparser.fromstring(response.body)) 
>>> sel.xpath('//h4[@class="name"]/a').extract() 
[u'<a href="http://mobileshop.ae/one-x/htc-one-x-16gb-gray">HTC One X 3G 16GB Grey</a>', 
u'<a href="http://mobileshop.ae/one-x/htc-one-x-16gb-white">HTC One X 3G 16GB White</a>', 
u'<a href="http://mobileshop.ae/one-x/htc-one-x-32gb-gray">HTC One X 3G 32GB Grey</a>', 
u'<a href="http://mobileshop.ae/one-x/htc-one-x-32gb-white">HTC One X 3G 32GB White</a>'] 

Обратите внимание, что с помощью синтаксического анализатора BeautifulSoup намного медленнее, чем по умолчанию парсер LXML в. Вы, вероятно, захотите сделать это только в тех местах, где это действительно необходимо.

0

Response.xpath("//body") возвращает body of 'html' element содержащийся в ответ, в то время как response.body возвращает тело (or message-body) всего ответа HTTP (так что все HTML в ответ включая головки & элементов кузова).

Response.xpath("//body") - это на самом деле ярлык, который преобразует тело ответа HTTP в объект Selector, который можно перемещать с помощью xpath.

Ссылки, которые вам нужны, содержатся в корпусе элемента html, они не могут быть нигде больше, я не уверен, почему вы предполагаете, что их там нет. response.xpath("//body//a/@href") предоставит вам все ссылки на странице, вам, вероятно, потребуется создать правильный xpath, который будет выбирать только те ссылки, которые вам нужны.

Длина response.xpath("//body") что вы упоминаете в вашем примере является результатом того, что ваш первый пример len(response.xpath('//body').extract()) возвращает число элементов тела в HTML документа, список response.xpath.extract() возврата элементов, соответствующих XPath. В документе есть только одно тело. В вашем втором примере len(response.xpath('//body')).extract()[0]) вы фактически получаете элемент body как строку, и вы получаете длину строки (количество символов, содержащихся в теле). len(response.body) также дает вам количество символов всего HTTP-ответа, число которых, скорее всего, выше, потому что html HEAD содержит множество скриптов и таблиц стилей, которых нет в теле HTML.

+0

Прошу прощения, было что-то, что нужно было отредактировать под вопросом, я имел в виду разницу между response.body и response.xpath ('// html'), он должен быть одним и тем же, оба содержат элемент head. Хотя этот xpath со связанными мне ссылками: response.xpath ('// h4 [@ class = "name"]/a'). Extract() доступен на response.body, но ссылки отсутствуют в response.xpath ('// html') – Vanddel

+0

Pawel, проблема в том, что на странице есть недопустимый HTML (несколько закрытых тегов), кажется, что lxml вызывает некоторый контент. – elias

+0

ага! что не было ясно из первой версии вопроса. OP отредактировал вопрос и его образец кода :) ранее он выбирал xpath («// body»), теперь он выбирает «// html». –