由于scrapy中的时间戳身份验证,网址将过期

时间:2017-04-24 18:53:53

标签: python scrapy web-crawler amazon scrapy-spider

我试图抓住亚马逊杂货店,并获得杂货类别,我使用的是Associate Product Advertising api。我的请求被排队但是由于请求的有效期为15分钟,一些请求在排队15分钟后被抓取,这意味着它们在被抓取时会过期并产生400错误。我正在考虑批量排队请求的解决方案,但即使这样做也会失败,如果实现控制批量处理它们,因为问题是批量准备请求而不是批量处理它们。不幸的是,Scrapy几乎没有关于这个用例的文档,那么如何批量准备请求呢?

from scrapy.spiders import XMLFeedSpider
from scrapy.utils.misc import arg_to_iter
from scrapy.loader.processors import TakeFirst


from crawlers.http import AmazonApiRequest
from crawlers.items import (AmazonCategoryItemLoader)
from crawlers.spiders import MySpider


class AmazonCategorySpider(XMLFeedSpider, MySpider):
    name = 'amazon_categories'
    allowed_domains = ['amazon.co.uk', 'ecs.amazonaws.co.uk']
    marketplace_domain_name = 'amazon.co.uk'
    download_delay = 1
    rotate_user_agent = 1

    grocery_node_id = 344155031

    # XMLSpider attributes
    iterator = 'xml'
    itertag = 'BrowseNodes/BrowseNode/Children/BrowseNode'

    def start_requests(self):
        return arg_to_iter(
            AmazonApiRequest(
                qargs=dict(Operation='BrowseNodeLookup',
                           BrowseNodeId=self.grocery_node_id),
                meta=dict(ancestor_node_id=self.grocery_node_id)
            ))

    def parse(self, response):
        response.selector.remove_namespaces()
        has_children = bool(response.xpath('//BrowseNodes/BrowseNode/Children'))
        if not has_children:
            return response.meta['category']
        # here the request should be configurable to allow batching
        return super(AmazonCategorySpider, self).parse(response)

    def parse_node(self, response, node):
        category = response.meta.get('category')
        l = AmazonCategoryItemLoader(selector=node)
        l.add_xpath('name', 'Name/text()')
        l.add_value('parent', category)
        node_id = l.get_xpath('BrowseNodeId/text()', TakeFirst(), lambda x: int(x))
        l.add_value('node_id', node_id)
        category_item = l.load_item()
        return AmazonApiRequest(
            qargs=dict(Operation='BrowseNodeLookup',
                       BrowseNodeId=node_id),
            meta=dict(ancestor_node_id=node_id,
                      category=category_item)
        )

1 个答案:

答案 0 :(得分:0)

这样做的一种方法:

由于有两个地方可以产生请求,因此您可以利用priority属性来优先处理来自parse方法的请求:

class MySpider(Spider):
    name = 'myspider'

    def start_requests(self):
        for url in very_long_list:
            yield Request(url)

    def parse(self, response):
        for url in short_list:
            yield Reuest(url, self.parse_item, priority=1000)

    def parse_item(self, response):
        # parse item

在此示例中,scrapy将优先处理来自parse的请求,这样可以避免时间限制。

详情请见Request.priority

  

priority(int) - 此请求的优先级(默认为0)。调度程序使用优先级来定义用于处理请求的顺序。具有更高优先级值的请求将更早执行。允许使用负值以指示相对较低的优先级。

on scrapy docs