账号密码登录
微信安全登录
微信扫描二维码登录

登录后绑定QQ、微信即可实现信息互通

手机验证码登录
找回密码返回
邮箱找回 手机找回
注册账号返回
其他登录方式
分享
  • 收藏
    X
    scrapy写多爬虫 并行报错 ,求人指导
    76
    0

    from scrapy.utils.project import get_project_settings
    from Espider.spiders.chinafof import chinafof
    from Espider.spiders.ifenxi import ifenxi
    from Espider.spiders.vcbeat import vcbeat
    from Espider.spiders.zdreview import zdreview
    from scrapy.crawler import CrawlerProcess
    from multiprocessing import Process

    def run_crawl():

    process=CrawlerProcess(get_project_settings())
    process.crawl(chinafof)
    process.crawl(ifenxi)
    process.crawl(vcbeat)
    process.crawl(zdreview)
    process.start()
    
    
    

    if __name__=='__main__':

    [Process(target=run_crawl).start() for _ in range(4)]
    
    
    File "/home/shenjianlin/.local/lib/python3.4/site-packages/twisted/python/log.py", line 86, in callWithContext
        return context.call({ILogContext: newCtx}, func, *args, **kw)
      File "/home/shenjianlin/.local/lib/python3.4/site-packages/twisted/python/context.py", line 122, in callWithContext
        return self.currentContext().callWithContext(ctx, func, *args, **kw)
      File "/home/shenjianlin/.local/lib/python3.4/site-packages/twisted/python/context.py", line 85, in callWithContext
        return func(*args,**kw)
    --- <exception caught here> ---
      File "/home/shenjianlin/.local/lib/python3.4/site-packages/twisted/internet/posixbase.py", line 619, in _doReadOrWrite
        why = selectable.doWrite()
      File "/home/shenjianlin/.local/lib/python3.4/site-packages/twisted/internet/base.py", line 1186, in doWrite
        "doWrite called on a %s" % reflect.qual(self.__class__))
    builtins.RuntimeError: doWrite called on a twisted.internet.tcp.Port
    
    2018-12-02 17:25:54 [twisted] CRITICAL: Unhandled Error
    Traceback (most recent call last):
      File "/home/shenjianlin/.local/lib/python3.4/site-packages/twisted/python/log.py", line 103, in callWithLogger
        return callWithContext({"system": lp}, func, *args, **kw)
      File "/home/shenjianlin/.local/lib/python3.4/site-packages/twisted/python/log.py", line 86, in callWithContext
        return context.call({ILogContext: newCtx}, func, *args, **kw)
      File "/home/shenjianlin/.local/lib/python3.4/site-packages/twisted/python/context.py", line 122, in callWithContext
        return self.currentContext().callWithContext(ctx, func, *args, **kw)
      File "/home/shenjianlin/.local/lib/python3.4/site-packages/twisted/python/context.py", line 85, in callWithContext
        return func(*args,**kw)
    --- <exception caught here> ---
      File "/home/shenjianlin/.local/lib/python3.4/site-packages/twisted/internet/posixbase.py", line 619, in _doReadOrWrite
        why = selectable.doWrite()
      File "/home/shenjianlin/.local/lib/python3.4/site-packages/twisted/internet/base.py", line 1186, in doWrite
        "doWrite called on a %s" % reflect.qual(self.__class__))
    builtins.RuntimeError: doWrite called on a twisted.internet.tcp.Port
    
    
    1
    打赏
    收藏
    点击回答
        全部回答
    • 0
    • 卍魅惑 普通会员 1楼

      在Scrapy中,你可能会遇到多爬虫并发报错的情况。这通常是由于多个爬虫共享同一连接,或者在爬取同一数据时,其中一个爬虫的网络连接出现故障或耗尽。以下是一些可能的解决方案:

      1. 使用scrapy的并发控制器(Executor): Scrapy提供了一个内置的并发控制器,用于管理多线程的爬虫任务。在发送请求时,你可以通过设置并发队列来控制请求的顺序和数量。以下是一个简单的示例:

      ```python from scrapy.crawler import CrawlerProcess from scrapy.pipeline import Pipeline from scrapy.exceptions import MultipleRequestsExcusion

      class MySpider(scrapy.Spider): name = "myspider"

      def start_requests(self):
          # 创建一个并发队列
          queue = Queue()
      
          # 创建多个爬虫进程
          process1 = Process(target=self.process_request, args=(queue,))
          process2 = Process(target=self.process_request, args=(queue,))
          process3 = Process(target=self.process_request, args=(queue,))
      
          # 启动爬虫进程
          process1.start()
          process2.start()
          process3.start()
      
          # 等待所有爬虫结束
          while not queue.empty():
              # 爬取并添加请求到队列
              request = queue.get()
              yield request
      
      def process_request(self, queue):
          # 处理请求
          response = yield Request(url=self.url)
      
          # 如果请求成功,将结果添加到队列
          if response.status_code == 200:
              queue.put(response)
      
          # 如果请求失败,返回一个错误消息
          else:
              raise MultipleRequestsExcusion(response.status_code, "Multiple requests occurred concurrently.")
      
          # 关闭爬虫进程
          process1.join()
          process2.join()
          process3.join()
      

      ```

      在这个示例中,我们创建了三个爬虫进程,每个进程都继承自CrawlerProcess类,并通过start_requests方法发送一个请求到URL。我们使用Queue类创建了一个并发队列,以便在请求完成后将请求添加到队列中。当所有爬虫都完成后,我们通过get方法从队列中取出请求并处理它们。

      1. 使用多线程同时运行爬虫: 在并发环境中,如果你希望同时运行多个爬虫,你可能需要使用多线程来处理请求。以下是一个简单的示例:

      ```python from scrapy.crawler import CrawlerProcess from scrapy.pipeline import Pipeline from scrapy.exceptions import MultipleRequestsExcusion

      class MySpider(scrapy.Spider): name = "myspider"

      def start_requests(self):
          # 创建一个并发队列
          queue = Queue()
      
          # 创建多个爬虫进程
          process1 = Process(target=self.process_request, args=(queue,))
          process2 = Process(target=self.process_request, args=(queue,))
          process3 = Process(target=self.process_request, args=(queue,))
      
          # 启动爬虫进程
          process1.start()
          process2.start()
          process3.start()
      
          # 等待所有爬虫结束
          while not queue.empty():
              # 选择一个爬虫进程,从队列中取出请求
              process = process1 if queue.get() else process2
      
              # 处理请求
              response = yield process(response)
      
              # 如果请求成功,将结果添加到队列
              if response.status_code == 200:
                  queue.put(response)
      
              # 如果请求失败,返回一个错误消息
              else:
                  raise MultipleRequestsExcusion(response.status_code, "Multiple requests occurred concurrently.")
      
          # 关闭爬虫进程
          process1.join()
          process2.join()
          process3.join()
      

      ```

      在这个示例中,我们选择一个爬虫进程,从队列中取出请求,并处理它们。我们使用get方法从队列中取出请求,然后根据请求的状态码和返回结果来选择哪个爬虫进程来处理请求。当所有爬虫都完成后,我们通过join方法关闭当前爬虫进程。

      注意,使用多线程同时运行爬虫可能会增加系统的负载和响应时间,因为爬虫会同时处理多个请求。如果你需要处理大量数据,可能需要考虑其他策略,例如并行处理数据或者使用异步处理。

      另外,Scrapy的并发控制器默认情况下会管理所有请求的并发队列。如果你需要在每个请求完成后移除请求,你可以在CrawlerProcessfinish_requests方法中添加以下代码:

      ```python def finish_requests(self): # 从队列中移除所有请求 for request in queue: request.delete()

      # 关闭队列
      queue.close()
      

      ```

      这将从队列中移除所有请求,确保每个请求都在各自的爬虫进程中完成。如果某个爬虫进程没有完成所有的请求,那么它将被移除,其他爬虫进程将自动处理剩余的请求。

    更多回答
    扫一扫访问手机版
    • 回到顶部
    • 回到顶部