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

Jab*_*abb 6 python scrapy

编辑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
Run Code Online (Sandbox Code Playgroud)

编辑:

我试图在此期间回答我自己的问题并实现了一个队列,但由于某种原因它不会异步运行.基本上当webkitBrowser.get(html=response.body, num_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
Run Code Online (Sandbox Code Playgroud)

我在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 
Run Code Online (Sandbox Code Playgroud)

jre*_*nie 3

我没有遵循你问题中的所有内容,因为我不知道 scrapy,也不明白什么会导致段错误,但我想我可以解决一个问题:为什么当 webkitBrowser.get 繁忙时 scrapy 被阻止?

我在你的“队列”示例中没有看到任何可以给你并行性的可能性。通常,人们会使用threadingmultiprocessing模块,以便多个事物可以“并行”运行。webkitBrowser.get我怀疑您可能想在线程中运行它,而不是简单地调用。在检索网页时,Python 线程应该工作得相当好。Python 无法同时执行两个 CPU 密集型任务(由于 GIL),但它可以并行等待 Web 服务器的响应。

这是最近的 SO Q/A,其中包含可能有帮助的示例代码。

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