如何在scrapy(Python)中间件中实现并发

如何在scrapy(Python)中间件中实现并发,python,scrapy,Python,Scrapy,编辑2 第二种方法。现在,我放弃了使用多个实例,并将scrapy设置配置为不使用并发请求。它缓慢但稳定我开了一个赏金。谁能同时帮助完成这项工作?如果将scrapy配置为并发运行,则会出现分段错误 class WebkitDownloader( object ): def __init__(self): os.environ["DISPLAY"] = ":99" self.proxyAddress = "a:b@" + PROXY_DEFAULT_HOST

编辑2

第二种方法。现在,我放弃了使用多个实例,并将scrapy设置配置为不使用并发请求。它缓慢但稳定我开了一个赏金。谁能同时帮助完成这项工作?如果将scrapy配置为并发运行,则会出现分段错误

class WebkitDownloader( object ):

    def __init__(self):
        os.environ["DISPLAY"] = ":99"
        self.proxyAddress = "a:b@" + PROXY_DEFAULT_HOST + ":" + str(PROXY_DEFAULT_PORT)


    def process_response(self, request, response, spider):
        self.request = request
        self.response = response
        if 'cached' not in response.flags:
            webkitBrowser = webkit.WebkitBrowser(proxy = self.proxyAddress, gui=False, timeout=0.5, delay=0.5, forbidden_extensions=['js','css','swf','pdf','doc','xls','ods','odt'])
            #print "added to queue: " + str(self.counter)
            webkitBrowser.get(html=response.body, num_retries=0)
            html = webkitBrowser.current_html()
            respcls = responsetypes.from_args(headers=response.headers, url=response.url)
            kwargs = dict(cls=respcls, body=killgremlins(html))
            response = response.replace(**kwargs)
            webkitBrowser.setPage(None)
            del webkitBrowser
        return response
编辑:

同时,我试图回答我自己的问题,并实现了一个队列,但由于某些原因,它不会异步运行。基本上,当
webkitBrowser.get(html=response.body,num\u retries=0)
忙时,会阻止scrapy,直到方法完成。新请求不会分配给
self.queue
中剩余的空闲实例

有人能给我指一下正确的方向吗

class WebkitDownloader( object ):

    def __init__(self):
        proxyAddress = "http://" + PROXY_DEFAULT_HOST + ":" + str(PROXY_DEFAULT_PORT)
        self.queue = list()
        for i in range(8):
            self.queue.append(webkit.WebkitBrowser(proxy = proxyAddress, gui=True, timeout=0.5, delay=5.5, forbidden_extensions=['js','css','swf','pdf','doc','xls','ods','odt']))

    def process_response(self, request, response, spider):

        i = 0
        for webkitBrowser in self.queue:
            i += 1
            if webkitBrowser.status == "WAITING":
                break
        webkitBrowser = self.queue[i]

        if webkitBrowser.status == "WAITING":
            # load webpage
            print "added to queue: " + str(i)
            webkitBrowser.get(html=response.body, num_retries=0)
            webkitBrowser.scrapyResponse = response

        while webkitBrowser.status == "PROCESSING":
            print "waiting for queue: " + str(i)  

        if webkitBrowser.status == "DONE":
            print "fetched from queue: " + str(i)
            #response = webkitBrowser.scrapyResponse
            html = webkitBrowser.current_html()
            respcls = responsetypes.from_args(headers=response.headers, url=response.url)
            kwargs = dict(cls=respcls, body=killgremlins(html))
            #response = response.replace(**kwargs)
            webkitBrowser.status = "WAITING"
            return response
我在一个scrapy中间件中使用WebKit来呈现JavaScript。目前,scrapy配置为一次处理1个请求(无并发)

我希望使用并发(例如,一次8个请求),但我需要确保
WebkitBrowser()
的8个实例根据各自的处理状态接收请求(只要
WebkitBrowser.get()
完成并准备好接收下一个请求,就会发出新的请求)

我如何使用Python实现这一点?这是我当前的中间件:

class WebkitDownloader( object ):

    def __init__(self):
        proxyAddress = "http://" + PROXY_DEFAULT_HOST + ":" + str(PROXY_DEFAULT_PORT)
        self.w = webkit.WebkitBrowser(proxy = proxyAddress, gui=True, timeout=0.5, delay=0.5, forbidden_extensions=['js','css','swf','pdf','doc','xls','ods','odt'])

    def process_response(self, request, response, spider):
        if not ".pdf" in response.url:
            # load webpage
            self.w.get(html=response.body, num_retries=0)
            html = self.w.current_html()
            respcls = responsetypes.from_args(headers=response.headers, url=response.url)
            kwargs = dict(cls=respcls, body=killgremlins(html))
            response = response.replace(**kwargs)

        return response 

我没有完全理解你的问题,因为我不知道scrapy,也不知道是什么导致了SEGFULT,但我想我可以回答一个问题:当webkitBrowser.get忙时,为什么scrapy会被阻止

在您的“队列”示例中,我没有看到任何东西能够为您提供并行性的可能性。通常情况下,可以使用
线程化
多处理
模块,以便多个东西可以“并行”运行。与其简单地调用
webkitBrowser.get
,我怀疑您可能希望在线程中运行它。在检索网页的情况下,python线程应该工作得相当好。Python不能同时完成两个CPU密集型任务(由于GIL),但它可以并行地等待web服务器的响应


这里有一个如何让你开始的想法。创建一个。定义一个函数,该函数将此队列作为参数,获取网页并将响应放入队列中。在主程序中,输入
while True:
在生成所有get线程后循环:检查队列并处理下一个条目,或者
time.sleep(.1)
如果它是空的。

我知道这是一个老问题,但我有类似的问题,希望我偶然发现的这些信息可以帮助其他人解决类似的问题:

  • 如果适合您(考虑到您使用的是webkit浏览器,他们可能会这样做,因为splash基于webkit),那么它可能是最简单的解决方案

  • 如果1不起作用,您可以使用或do同时运行多个spider

  • 根据浏览器渲染主要是等待(等待页面渲染)、IO密集型还是CPU密集型,您可能希望使用扭曲、多线程或多处理的非阻塞睡眠。对于后者,坚持使用scrapy的价值会降低,您可能想要破解一个简单的刮板(例如,由a.Jesse Jiryu Davis和Guido van Rossum编写的网络爬虫:and)或创建自己的刮板


  • 问题是,如果我使用多线程,我需要首先创建一个回调函数,在webkitBrowser处理完该项目后,它最终返回该项目。get()有什么建议吗?如果你能让我走上正轨,我很乐意将赏金积分归你所有。@Jabb别担心赏金。我对scrapy和webkit的了解还不足以给你一个完整的例子,但我想我可以让你开始。创建一个Define函数,该函数将此队列作为参数,
    获取网页并将响应放入队列中。在主程序中,输入
    while True:
    在生成所有
    get
    线程后循环:检查队列并处理下一个条目,或者
    time.sleep(.1)
    如果它为空。如果这听起来对你有希望,我会在我的答案中加入这个想法。