使用Scrapy迭代地从两个站点获取项目

时间:2016-12-27 22:22:09

标签: python scrapy

我正在用Scrapy编写一个刮刀,我担心它的异步行为可能会导致问题。

我从一个包含多个链接a的页面开始,每个链接都有一个x。保存(下载)这些x。然后我转到另一个页面b,在那里我使用我从其中一个a链接获得的一些信息(所有这些链接都是常量)来选择并下载y
然后我“配对”xy,我对它们进行配对并不重要,只有xy都存在(下载)。
现在我会考虑处理我的起始页面(start_urls),然后我会得到“转向”页面的链接(如我在第1页,现在转到第2页),然后我请求从一开始就开始这个过程。

代码看起来大致如下:

# ..imports, class etc.

start_url = ['bla']
start_url_buddy = ['bli']


def parse(self, response):

    urls = response.xpath(...)
    for url in urls:
        yield scrapy.Request(url, callback=self.parse_child)

    yield scrapy.Request(start_url_buddy, callback=self.parse_buddy)

    pair_function(self.info)

    # Finished processing start page. Now turning the page.
    # could do smth like this to get next page:
    nextpage_url = response.xpath(...@href)
    yield scrapy.Request(nextpage_url)

    # or maybe something like this?
    start_urls.append(response.xpath(...@href))

# links `a`
def parse_child(self, response):

    # info for processing link `b`
    self.info = response.xpath(...)

    # Download link
    x = response.xpath(...)
    # urlopen etc. write x to file in central dir

# link `b`
def parse_buddy(self, response):

    # Download link
    y = response.xpath(...self.info...)
    # urlopen etc. write y to file in central dir

我还没有进入页面转换部分,我担心这是否会按预期工作(我正在摆弄合并函数atm,得到x s和y正常工作一页)。我不关心xy的顺序是什么,只要它在pair_function和'翻页'之前(当解析函数应该再次出现时)。

我已经查看了其他几个问题,例如this,但我无法从他们那里得到明确的答案。我的基本问题是我不确定异步性是如何实现的(它似乎没有在文档中解释过?)。

编辑:要明确我害怕会发生的事情是yield scrapy.Request(nextpage_url)将在之前的事件发生前被调用。我现在想我可以安全地防范这一点,只需在完成所有操作后附加到start_urls(就像我在代码中所做的那样)(这样做的逻辑应该导致parse在附加的URL上调用函数?

1 个答案:

答案 0 :(得分:2)

您将无法知道请求何时完成,因为scrapy正在处理您的所有请求,但它不会等待请求的服务器在处理下一个待处理请求之前返回响应。

关于异步调用,您不知道“何时”它们将结束,但您知道“where”,这就是回调方法。因此,例如,如果您想要一个接一个地执行请求,您可以执行以下操作:

def callback_method_1(self, response):
    # working with response 1
    yield Request(url2, callback=self.callback_method_2)

def callback_method_2(self, response):
    # working with response 2, after response 1
    yield Request(url3, callback=self.callback_method_3)

def callback_method_3(self, response):
    # working with response 3, after response 2 
    yield myfinalitem

在此示例中,您确定第一个请求是在url2请求之前完成的,而且是在url3之前完成的。正如您所看到的,您并不完全知道“何时”这些请求已完成,但您确实知道“在哪里”。

还要记住,回调之间进行通信的方法是使用meta请求参数。