2016-09-09 6 views
0

Я делаю паука с помощью Scrapy (1.1.2) для утилизации продуктов. Мне удалось заставить его работать и очистить достаточно данных, но теперь я хочу, чтобы каждый элемент делал новый запрос к product page и лому, например описание продукта.Scrapy: TypeError: объект «Запрос» не итерируется

Во-первых, вот мой последний рабочий код

spider.py (кроме)

class ProductScrapSpider(Spider): 
    name = "dmoz" 
    allowed_domains = ["example.com"] 
    start_urls = [ 
     "http://www.example.com/index.php?id_category=24" 
     # ... 
    ] 

    def parse(self, response): 
     for sel in response.xpath("a long string"): 
      mainloader = ProductLoader(selector=sel) 
      mainloader.add_value('category', 'Category Name') 
      mainloader.add_value('meta', self.get_meta(sel)) 
      # more data 

      yield mainloader.load_item() 

      # Follows the pagination 
      next_page = response.css("li#pagination_next a::attr('href')") 
      if next_page: 
       url = response.urljoin(next_page[0].extract()) 
       yield scrapy.Request(url, self.parse) 

    def get_meta(self, response): 
     metaloader = ProductMetaLoader(selector=response) 
     metaloader.add_value('store', "Store name") 
     # more data 

     yield metaloader.load_item() 

Выход

[ 
{ 
    "category": "Category Name", 
    "price": 220000, 
    "meta": { 
     "baseURL": "", 
     "name": "", 
     "store": "Store Name" 
    }, 
    "reference": "100XXX100" 
}, 
... 
] 

После прочтения документации и ответы на некоторые вопросы здесь, я 'изменил метод get_meta и добавил обратный вызов для запроса get_product_page:

new_spider.py (кроме)

def get_meta(self, response): 
    metaloader = ProductMetaLoader(selector=response) 
    metaloader.add_value('store', "Store name") 
    # more data 

    items = metaloader.load_item() 
    new_request = scrapy.Request(items['url'], callback=self.get_product_page) 

    # Passing the metadata 
    new_request.meta['item'] = items 

    # The source of the problem 
    yield new_request 

def get_product_page(self, response): 
    sel = response.selector.css('.product_description') 
    items = response.meta['item'] 

    new_meta = items 
    new_meta.update({'product_page': sel[0].extract()}) 

    return new_meta 

Ожидаемый выход

[ 
{ 
    "category": "Category Name", 
    "price": 220000, 
    "meta": { 
     "baseURL": "", 
     "name": "", 
     "store": "Store Name", 
     "product_page": "<div> [...] </div>" 
    }, 
    "reference": "100XXX100" 
}, 
... 
] 

Ошибка

TypeError: 'Request' object is not iterable 

full output

Я ничего не мог найти об этой ошибке, поэтому, пожалуйста, помогите мне исправить это.

Большое спасибо.

+0

Где 'get_meta' вызывается? Вы пытались вернуть новый объект запроса внутри конвейера элементов? – starrify

+0

Извините, я добавил отсутствующий вызов 'get_meta' внутри поля товара' meta'. – Be0wulf

ответ

1

Ошибки вы испытываете (TypeError: 'Request' object is not iterable) произошла потому, что Request экземпляр претворяется в поле элемента (в обновленном get_meta функции метода), в то время как подача экспортер не может сериализовать его.

Вам нужно будет вернуть метатеку get на Scrapy вместе с мета-аргументом, чтобы передать элемент с половинным анализом. Вот пример обновленного parse метода и новый parse_get_meta метод:

def parse(self, response): 
    for sel in response.xpath("a long string"): 
     mainloader = ProductLoader(selector=sel) 
     mainloader.add_value('category', 'Category Name') 
     #mainloader.add_value('meta', self.get_meta(sel)) 
     # more data 
     item = mainloader.load_item() 
     get_meta_req = self.get_meta(sel) 
     get_meta_req['meta']['item'] = item 
     yield get_meta_req.replace(callback=self.parse_get_meta) 

def parse_get_meta(self, response): 
    """Parses a get meta response""" 
    item = response.meta['item'] 
    # Parse the response and load the data here, e.g. item['foo'] = bar 
    pass 
    # Finally return the item 
    return item 

Смотрите также: http://doc.scrapy.org/en/latest/topics/request-response.html#topics-request-response-ref-request-callback-arguments

+0

Два метода 'parse_get_meta' и' get_product_page' были перекрывающимися, поэтому было сложно ввести свой подход в мой код, двигатель фактически отправлял запросы, но ничего не получал. Результат немного отличается от всех выровненных клавиш, так как мне также пришлось модифицировать класс Item внутри 'items.py'. Я упоминал, что это работает. – Be0wulf

Смежные вопросы