zoukankan      html  css  js  c++  java
  • scrapy基础

    scrapy

    Scrapy 是用 Python 实现的一个为了爬取网站数据、提取结构性数据而编写的应用框架。
    Scrapy 常应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。
    Scrapy 是基于twisted框架开发而来,twisted是一个流行的事件驱动的python网络框架。因此Scrapy使用了一种非阻塞(又名异步)的代码来实现并发。

    安装

    • Linux:
    pip install scrapy
    
    • Windows:
    1. pip install wheel
    2. 下载twisted 
       http://www.lfd.uci.edu/-gohlke/pythonlibs/#twisted
    3. 安装twisted
       进入到下载目录,pip install Twisted-xxx.whl
    4. pip install pywin32
    5. pip install scrapy
    

    Scrapy结构,执行流程

    • 架构图

    • 各部分作用

      • Scrapy Engine(引擎): 负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等。
      • Scheduler(调度器): 它负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎。
      • Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理,
      • Spider(爬虫):它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器).
      • Item Pipeline(管道):它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方。
      • Downloader Middlewares(下载中间件):你可以当作是一个可以自定义扩展下载功能的组件。
      • Spider Middlewares(Spider中间件):你可以理解为是一个可以自定扩展和操作引擎和Spider中间通信的功能组件(比如进入Spider的Responses;和从Spider出去的Requests)
    • 执行流程图

    起始url被封装成request请求对象,经引擎传给调度器,存放在队列中且会对重复的请求对象进行过滤,之后经引擎传递给下载器去下载数据得到响应对象,响应对象经引擎返回给spider进行解析并封装到item对象中,用yield将item对象经引擎传给管道进行持久化处理,若spider中解析到新的url,重复上述操作。

    请求传参

    当爬取的数据不在同一页面中时,要进行请求传参,不然持久化的数据结果会出错。

    • 使用meta进行传参,如下:
    def parse(self, response):
    	...
    	yield scrapy.Request(url, callback=self.detail, meta={"item": item})
    	
    def detail(self, response):
    	item = response.meta['item']
    	...
    

    如何提高scrapy爬取效率

    1. 增大并发数
      默认情况下scrapy没有开启线程并发,需在settings.py中手动开启。CONCURRENT_REQUESTS=32,但是并不是只能设置不超过32,可以适度增加并发数。
    2. 降低日志等级
      减少日志信息的输出会降低CPU的使用率。
      如:LOG_LEVEL = 'INFO'
      LOG_FILE = 'path' 将日志输出到指定文件中
    3. 禁用cookie
      除非真的需要cookie,否则请关闭以提升爬取效率。
      COOKIES_ENABLED = False
    4. 限制重试
      重新请求爬取失败的url会减慢爬取速度。
      RETRY_ENABLED= False
    5. 缩减下载超时
      放弃请求响应慢的url,可以提高爬取效率。
      DOWNLOAD_TIMEOUT = 10 (单位是秒)

    如何设置代理池和UA池

    ua_list = [
        
    ]
    ip_list = [
        
    ]
    
    # 在下载中间件中
    import random
    
    def process_request(self, request, spider):
    	request.meta['proxy'] = random.choice(ip_list)
    	request.headers['User-Agent'] = random.choice(ua_list)
    	...
    

    使用管道进行持久化存储的流程

    1. 在items中定义字段
    2. 获取解析后的数据值
    3. 将解析后的数据值存储到item对象中
    4. 通过yield将item对象提交到管道
    5. 管道中持久化存储代码的编写
    6. settings.py中开启管道, 并设置优先级

    在scrapy中使用selenium

    1. 在spider的__init__方法中实现浏览器
    2. 在spider的closed方法中关闭浏览器
    3. 在下载中间件的响应中使用spider.browser获取浏览器对象,并得到需要的网页源码,实例化一个新的响应对象,之后将浏览器获取的页面源码加载到该对象中,返回这个新的响应对象。
    # spider.py
       def __init__(self):
            self.browser = webdriver.Firefox()
    
        def closed(self,spider):
            print("spider closed")
            self.browser.close()
    
    # middlewares.py
    def process_request(self, request, spider):
            if spider.name == 'xxx':
                try:
                    spider.browser.get(request.url)
                    spider.browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')
                except TimeoutException as e:
                    print('超时')
                    spider.browser.execute_script('window.stop()')
                time.sleep(2)
                return HtmlResponse(url=spider.browser.current_url, body=spider.browser.page_source,
                                    encoding="utf-8", request=request)
    

    其他知识点

    • scrapy为什么要把持久化操作放到管道中, 而不是在爬虫文件中?
      • 放到管道中进行持久化操作的效率会更高
    • spider参数是干嘛用的?
      • 用来传递除了item对象之外的其他属性等
    • 管道文件中return item的作用?
      • 为了让优先级低于本管道类的能拿到item对象
    • 在scrapy框架中不需要考虑cookie
    • 原始的scrapy为啥不能进行分布式爬虫?
      • 原生scrapy的调度器、管道不能共享。
  • 相关阅读:
    gearman任务分发改进
    gearman实现任务分发
    BeanStalkd 做队列服务
    Tomcat各种日志的关系与catalina.out文件的分割
    数据库系统原理-关系数据库的规范化理论总结
    MySQL配置参数innodb_flush_log_at_trx_commit
    gRPC快速入门
    使用vagrant和kubeadm搭建k8s集群
    VS项目属性中的C/C++运行库:MT、MTd、MD、MDd
    消除C++中警告代码
  • 原文地址:https://www.cnblogs.com/tmdhhl/p/10661139.html
Copyright © 2011-2022 走看看