如何在scrapy(Python)中间件中实现并发
编辑2 第二种方法。现在,我放弃了使用多个实例,并将scrapy设置配置为不使用并发请求。它缓慢但稳定我开了一个赏金。谁能同时帮助完成这项工作?如果将scrapy配置为并发运行,则会出现分段错误如何在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
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)
如果它是空的。我知道这是一个老问题,但我有类似的问题,希望我偶然发现的这些信息可以帮助其他人解决类似的问题:
问题是,如果我使用多线程,我需要首先创建一个回调函数,在webkitBrowser处理完该项目后,它最终返回该项目。get()有什么建议吗?如果你能让我走上正轨,我很乐意将赏金积分归你所有。@Jabb别担心赏金。我对scrapy和webkit的了解还不足以给你一个完整的例子,但我想我可以让你开始。创建一个Define函数,该函数将此队列作为参数,
获取网页并将响应放入队列中。在主程序中,输入while True:
在生成所有get
线程后循环:检查队列并处理下一个条目,或者time.sleep(.1)
如果它为空。如果这听起来对你有希望,我会在我的答案中加入这个想法。