Относительно того, почему вы получаете сообщение об ошибке "0 / страниц просканировано", несмотря на то, что вы не воссоздаете ваш случай, я должен предположить, что ваш метод итерации страницы не создает правильные URL-адреса страницы.
У меня проблемы с пониманием использования для создания массива переменных всех "последующих ссылок", а затем с помощью len для отправки их в parse_indetail (), но пара вещей, на которые стоит обратить внимание.
- Когда вы используете «мета» для передачи элементов из одной функции в другую, хотя у вас есть правильная идея, вам не хватает некоторых экземпляров для функции, в которую вы ее передаете (вам также следует использовать стандартное соглашение об именах для простота)
Должно быть что-то вроде этого ...
def parse(self,response):
# If you are going to capture an item at the first request, you must instantiate
# your items class
item = MovieItem()
....
# You seem to want to pass ratings to the next function for itimization, so
# you make sure that you have it listed in your items.py file and you set it
item[rating] = response.xpath(PATH).extact() # Why did you ad the url_next? huh?
....
# Standard convention for passing meta using call back is like this, this way
# allows you to pass multiple itemized item gets passed
yield scrapy.Request(abs_url, callback = self.parse_indetail, meta = {'item': item})
def parse_indetail(self,response):
# Then you must initialize the meta again in the function your passing it to
item = response.meta['item']
# Then you can continue your scraping
- Вы не должны усложнять логику итерации страницы. Кажется, вы понимаете, как это работает, но вам нужна помощь в настройке этого аспекта Я воссоздал ваш вариант использования и оптимизировал его.
#items.py file
import scrapy
class TestimbdItem(scrapy.Item):
title = scrapy.Field()
directors = scrapy.Field()
writers = scrapy.Field()
stars = scrapy.Field()
popularity = scrapy.Field()
rating = scrapy.Field()
# The spider file
import scrapy
from testimbd.items import TestimbdItem
class ImbdsdpyderSpider(scrapy.Spider):
name = 'imbdsdpyder'
allowed_domains = ['imdb.com']
start_urls = ['http://www.imdb.com/chart/top']
def parse(self, response):
for href in response.css("td.titleColumn a::attr(href)").extract():
yield scrapy.Request(response.urljoin(href),
callback=self.parse_movie)
def parse_movie(self, response):
item = TestimbdItem()
item['title'] = [ x.replace('\xa0', '') for x in response.css(".title_wrapper h1::text").extract()][0]
item['directors'] = response.xpath('//div[@class="credit_summary_item"]/h4[contains(., "Director")]/following-sibling::a/text()').extract()
item['writers'] = response.xpath('//div[@class="credit_summary_item"]/h4[contains(., "Writers")]/following-sibling::a/text()').extract()
item['stars'] = response.xpath('//div[@class="credit_summary_item"]/h4[contains(., "Stars")]/following-sibling::a/text()').extract()
item['popularity'] = response.css(".titleReviewBarSubItem span.subText::text")[2].re('([0-9]+)')
item['rating'] = response.css(".ratingValue span::text").extract_first()
yield item
Обратите внимание на две вещи:
Идентификатор функции parse (). Все, что я здесь делаю, - это использую цикл for для ссылок, каждый экземпляр в цикле ссылается на href и передает urljoined href в функцию парсера. Приведите пример использования, этого более чем достаточно. В ситуации, когда у вас есть следующая страница, она просто каким-то образом создает переменную для «следующей» страницы и вызывает обратный вызов для анализа, она будет продолжать это делать, пока не сможет отфильтровать «следующую» страницу.
Во-вторых, используйте xpath только тогда, когда элементы HTML имеют одинаковый тег с разным содержимым. Это скорее личное мнение, но я говорю людям, что селекторы xpath - это как скальпель, а селекторы css - как нож мясника. Вы можете быть чертовски точными с помощью скальпеля, но это занимает больше времени, и во многих случаях может быть проще использовать CSS-селектор, чтобы получить тот же результат.