如何在start\u requests方法完成之前让Scrapy执行回调?

如何在start\u requests方法完成之前让Scrapy执行回调?,scrapy,twisted,scrapy-spider,Scrapy,Twisted,Scrapy Spider,我有一个很大的相对URL文件,我想用Scrapy来清理,我已经编写了一些代码来逐行阅读这个文件,并为我的爬行器生成解析请求。下面是一些示例代码 蜘蛛网: def start_requests(self): with open(self._file) as infile: for line in infile: inlist = line.replace("\n","").split(",") item = MyItem(da

我有一个很大的相对URL文件,我想用Scrapy来清理,我已经编写了一些代码来逐行阅读这个文件,并为我的爬行器生成解析请求。下面是一些示例代码

蜘蛛网:

def start_requests(self):
    with open(self._file) as infile:
        for line in infile:
            inlist = line.replace("\n","").split(",")
            item = MyItem(data = inlist[0])

            request = scrapy.Request(
                url = "http://foo.org/{0}".format(item["data"]),
                callback = self.parse_some_page
            )
            request.meta["item"]
            yield request


def parse_some_page(self,response):
    ...
    request = scrapy.Request(
        url = "http://foo.org/bar",
        callback = self.parse_some_page2
    )
    yield request

这很好,但是对于一个大的输入文件,我发现在
start\u请求
生成所有初始请求之前,
parse\u一些页面2
不会被调用。有什么方法可以让Scrapy更早地开始调用回调吗?最终,我不想等到一百万个请求之后才开始看到项目在管道中流动。

我想出了两个解决方案。1) 如果大型站点太多,则在单独的进程中运行spider。2) 通过Twisted使用延迟和回调(请不要逃跑,这不会太可怕)。我将讨论如何使用第二种方法,因为第一种方法可以简单地用谷歌搜索

执行
屈服请求的每个函数将“阻塞”,直到结果可用。因此,您的
parse_some_page()
函数将生成一个不完整的响应对象,并且在返回响应之前不会转到下一个URL。我确实找到了一些网站(主要是外国政府网站),它们需要一段时间才能获取,希望它能模拟您正在经历的类似情况。下面是一个简单的例子:

#spider/stackoverflow_spider.py
从twisted.internet导入延迟
进口羊瘙痒
类StackOverflow(scrapy.Spider):
名称='stackoverflow'
def start_请求(自我):
URL=[
'http://www.gob.cl/en/',
'http://www.thaigov.go.th/en.html',
'https://www.yahoo.com',
'https://www.stackoverflow.com',
'https://swapi.co/',
]
对于索引,枚举中的url(url):
#在返回响应后创建回调链
deferred=deferred.deferred()
deferred.addCallback(self.parse\u some\u页面)
deferred.addCallback(self.write_到_磁盘,url=url,filenumber=index+1)
#根据需要添加回调和错误回调
请按我的要求(
url=url,
callback=deferred.callback)#此函数将在返回响应后启动回调链
def解析某些页面(自我,响应):
打印(“[1]正在分析%s%”(response.url))
return response.body#这将传递给下一个回调
def写入磁盘(自身、内容、url、文件号):
打印(“[2]正在将%s内容写入磁盘“%”(url))
文件名=“%d.html”%filenumber
将open(filename,'wb')作为f:
f、 写作(内容)
#返回要传递给下一个回调函数的内容
#或者引发错误并启动Errbacks链
我稍微做了一些改变,使它更易于阅读和运行。在
start\u requests()
中要注意的第一件事是在
url
循环中创建对象并链接回调函数(通过
addCallback()
)。现在查看
scrapy.Request
回调
参数:

yield scrapy.Request(
    url=url,
    callback=deferred.callback)
此代码段将做的是在请求中
scrapy.Response
可用后立即启动回调链。在Twisted中,
Deferreds
仅在
Deferred之后才开始运行回调链。回调(结果)
使用值执行

提供响应后,
parse_some_page()
函数将以
response
作为参数运行。您将要做的是提取您在此处需要的内容,并将其传递给下一个回调(即
write\u to\u disk()
my example)。如有必要,您可以向循环中的
延迟
添加更多回调

因此,这个答案与您最初所做的不同之处在于,您使用
yield
先等待所有响应,然后执行回调。其中,as-my方法使用
Deferred.callback()
作为每个请求的回调,以便立即处理每个响应

希望这有帮助(和/或有效)

工具书类
  • :简要总结yeild/return如何影响解析
  • :我以前写过一篇关于Klien/Twisted异步回调的博文。可能对新手有帮助
附言
我不知道这是否真的适用于您,因为我找不到一个太大而无法解析的站点。另外,我在Scrapy:D是一个全新的人,但我有多年的经验。

我可能错了,但我认为发生这种情况是因为你在
解析某些页面()
中产生了
结果。当您删除了yield时会发生什么情况?@san臭名昭著。不,如果我选择省略
yield
,我不知道该如何处理新请求。谢谢您这么好的回复!我要试试看,读一些东西,然后再给你回复。