Scrapy - анализировать страницу для извлечения элементов - затем следовать и хранить содержимое URL-адреса элемента
У меня вопрос о том, как это сделать в процессе лечения. У меня есть паук, который сканирует список страниц.
Каждый раз, когда отображается страница листинга с элементами, существует обратный вызов parse_item(), который вызывается для извлечения данных элементов и получения элементов. Пока все хорошо, все отлично работает.
Но каждый элемент имеет среди других данных URL-адрес, с более подробной информацией об этом элементе. Я хочу следовать этому url и хранить в другом поле item (url_contents) выбранное содержимое этого URL-адреса элемента.
И я не уверен, как организовать код для достижения этого, поскольку две ссылки (ссылки ссылок и одна ссылка на конкретный элемент) выполняются по-разному, с обратными вызовами, вызываемыми в разное время, но я должен их сопоставить в та же обработка элементов.
Мой код выглядит так:
class MySpider(CrawlSpider):
name = "example.com"
allowed_domains = ["example.com"]
start_urls = [
"http://www.example.com/?q=example",
]
rules = (
Rule(SgmlLinkExtractor(allow=('example\.com', 'start='), deny=('sort='), restrict_xpaths = '//div[@class="pagination"]'), callback='parse_item'),
Rule(SgmlLinkExtractor(allow=('item\/detail', )), follow = False),
)
def parse_item(self, response):
main_selector = HtmlXPathSelector(response)
xpath = '//h2[@class="title"]'
sub_selectors = main_selector.select(xpath)
for sel in sub_selectors:
item = ExampleItem()
l = ExampleLoader(item = item, selector = sel)
l.add_xpath('title', 'a[@title]/@title')
......
yield l.load_item()
Ответы
Ответ 1
После некоторого тестирования и мышления я нашел это решение, которое работает для меня.
Идея состоит в том, чтобы использовать только первое правило, которое дает вам списки предметов, а также очень важно добавить follow = True в это правило.
И в parse_item() вы должны предоставить запрос вместо элемента, но после загрузки элемента. Запрос на URL-адрес деталя. И вы должны отправить загруженный элемент в обратный вызов этого запроса. Вы выполняете свою работу с ответом, и там вы получаете элемент.
Итак, финиш parse_item() будет выглядеть так:
itemloaded = l.load_item()
# fill url contents
url = sel.select(item_url_xpath).extract()[0]
request = Request(url, callback = lambda r: self.parse_url_contents(r))
request.meta['item'] = itemloaded
yield request
И тогда parse_url_contents() будет выглядеть так:
def parse_url_contents(self, response):
item = response.request.meta['item']
item['url_contents'] = response.body
yield item
Если у кого-то есть другой (лучший) подход, сообщите нам.
Стефан
Ответ 2
Я сижу с точно такой же проблемой, и из-за того, что никто не ответил на ваш вопрос в течение 2 дней, я полагаю, что единственным решением является следовать этому URL-адресу вручную из функции parse_item
.
Я новичок в Scrapy, поэтому я бы не попытался с этим (хотя я уверен, что это возможно), но мое решение будет заключаться в использовании urllib
и BeatifulSoup для загрузки второй страницы вручную, информацию и сохранить ее как часть предмета. Да, гораздо больше проблем, чем Scrapy, делает обычный синтаксический анализ, но он должен выполнять работу с наименьшими проблемами.