Scrapy框架笔记

-创建一个工程
    -scrapy startproject ProName
    -目录结构
        -spiders:爬虫文件夹
            -必须要存放一个爬虫源文件
        -setting.py:工程的配置文件
-cd ProName
-创建爬虫源文件:
    -scrapy genspider spiderName www.xxx.com
    -编写对应的代码在爬虫文件中
-执行工程
    -scrapy crawl spiderName
    -执行工程后,默认会输出工程所有的日志信息
    -指定类型日志的输出:
        -settings.py:
            -LOG_LEVEL = 'ERROR'
-爬虫文件spiderName内容阐述:
    -name:爬虫文件名称,该文件的唯一表示
    -start_urls:其实url列表,存储的都是url,url可以被子弹进行get请求的发送
    -parse方法:请求后的数据解析操作
-settings.py:
    -1.禁止robots
    -2.指定日志类型: LOG_LEVEL = 'ERROR'
    -3.UA伪装
-scrapy数据解析
    -使用:response.xpath('xpath表达式')
    -scrapy封装的xpath和etree中的xpath的区别:
        -scrapy中的xpath直接将定位到的标签中存储的值或者属性值取出返回的是sele对象,
        且相关的数据是存在Selector对象的data属性中,需要调用extract,extract_first()取出数据
-持久化存储
    -基于终端指令的持久化存储
        -要求:该方法只可以将parse方法的返回值存储到本地指定后缀的文件中
        -执行要求:scrapy crawl spiderName -o filePath
        -缺点:
            -存储类型局限,存储类型受限制
            -不可以存储到数据库等地方
    -基于管道的持久化存储(重点)
        -在爬虫文件中进行解析数据
        -在items.py中定义相关属性
            -步骤1中解析出了几个字段的数据,在此就定义一个属性
        -在爬虫文件中将解析到的数据存储封装到Item类型的对象中
        -将Item类型的对象提交给管道
        -在管道文件(pipelines.py)中,接受爬虫文件提交过来的Item类型对象,且对其进行任意形式的
        持久化存储操作
        -在配置文件中打开管道机制
            ITEM_PIPELINES = {
                 'duanziwang.pipelines.DuanziwangPipeline': 300,
                }
    -基于管道实现数据的备份
        -将爬取到的数据分别存储到不同的载体。
        -实现 :将数据一份存储到mysql一份存储到redis
        -问题:管道文件中的一个管道类表示怎样的一组操作?
            -一个管道类对应一种形式的持久化存储操作,如果将数据存储到不同的载体中就需要使用多个管道类。
        -已经定义好了三个管道类,将数据写入三个载体中进行存储:
            -item会不会一次提交给三个管道类
                -不会,爬虫的文件中的item只会北条给优先级最高的那一个管道类
                -优先级高德管道类需要在process_item中实现return item,就item传递给下一个即将被执行的管道类
-scrapy的手动请求发送实现全站数据爬取
    -yield scrapy.Request(url,callback):   GET
        -callback(回调函数)指定解析函数,用于解析数据

    -yield scrapy.FormRequest(url,callback,formdata):   POST
        -callback(回调函数)指定解析函数,用于解析数据
-为什么start_urls列表中的url会被自动进行get请求的发送?
    -因为列表中的url其实是被start_requests这个父类方法实现的get请求发送
    def start_requests(self):
        for u in self.start_urls:
            yield scrapy.Request(url=u,callback=self.parse)
-如何将start_urls中的ur1默认进行post请求的发送?
    -重写start_requests方法即可def start_requests(self):
    for u in self.start_urls:
        yield scrapy.FormRequest(url=u,callback=self.parse)
scrapy五大核心组件:
    ·引肇[Scrapy]
        用来处理整个系统的数据流处理,的发事务(框架核心)
    ·调度器(Scheduler)
        用来接受引擎发过来的请求,压入队列中,并在引擎再次请求的时候返回,可以想像成一个URL(抓取网页的网址现者说是链接)的优先队列,由它来决定下一个要抓取的网址是什么,同时去除重复的网址
    ·下载器(Downloader)
        用于下毅网页内器,并将网页内器返回给筑铁(Scrapy下载器是建立在1wisted这个高效的异步提型上的)
    ·爬虫(Spiders)
        爬虫是主要干活的,用于从特定的网页中提取自己需要的信息,即所谓的实体(tem)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
    ·项目管道(Pipeline)
        负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将披发送到项目管道,并经过几个特定的次序处理数据。

请求传参实现的深度爬取
    -深度爬取:爬取的数据没有在同一张页面中(首页数据+详情页数据)-在scrapy中如果没有请求传参我们是无法持久化存储数据-实现方式:
        scrapy.Request(url,callback,meta)
    -meta是一个字典,可以将meta传递给callback-calback取出meta:
        - response.meta
中间件:
    -作用:批量拦截请求和响应
    -爬虫中间件
    -下载中间件(推荐)
    拦截请求:
        -篡改请求url
        -伪装请求头信息
            - UA
            - cookie
        -设置请求代理(重点)
            -拦截响应
        -篡改响应数据
            -代理操作必须使用中间件才可以实现process_exception:- request.meta['proxy']='http://ip:port'
大文件下载
    -下载管道类是scrapy封装好的我们可以直接使用
    -from scrapy.pipelines.images import ImagesPipeline
    -重写该管道类的三个方法:
        -get_media_requests(self, item, info)
            -对图片地址发送请求
        -file_path(self, request, response=None, info=None, *, item=None)
            -返回图片名称即可
        -item_completed
            -返回item,将其返回给下一个即将被执行的管道类
        -在配置文件中添加:
            -IMAGES_STORE = 'filepath'
        -修改配置文件管道类的名称
            -ITEM_PIPELINES
三.如何提高scrapy的爬取效率
    增加并发:
        默认scrapy开启的并发线程为32个,可以适当进行增加。在settings配置文件中修改CONCURRENT_REQUESTS= 180值为100,并发设置成了为180。
    降低日志级别:
        在运行scrapy时,会有大量日志信息的输出,为了减少CPU的使用率。可以设置1og输出信息为INFO或者ERROR即可。在配置文件中编写:LOG_LEVEL='INFO'
    禁止cookie:
        如果不是真的需要cookie,则在scrapy爬取数据时可以禁止cookie从而减少CPU的使用率,提升爬取效率,在配置文件中编写:C00KIES_ENABLED= False
    禁止重试:
        对失败的HITP进行重新请求(重试)会减慢爬取速度,因此可以禁止重试。在配置文件中编写:RETRY_ENABLED = FaLse
    减少下载超时:
        如果对一个非常慢的链接进行爬取,减少下载超时可以能让卡住的链接快速被放弃,从而提升效率。在配置文件中进行编写:DONLOAD_TIHEOUT=10超时时间为10s
CrawlSpider
    -其实Spider的一个子类。Spider爬虫文件中爬虫类的父类。
    -子类的功能一定是多余父类-作用:被用作于专业实现全站数据爬取
    -将一个页面下所有页码对应的数据进行爬取-基本使用:
        -1.创建一个工程
       -2.cd工程
        -3.创建一个基于CrawlSpider的爬虫文件
        - scrapy genspider -t crawl SpiderName www.xxx.com
        -4.执行工程
    -注意:
        -1.一个链接提取器对应一个规则解析器(多个链接提取器和多个规则解析器)
        -2.在实现深度爬取的过程中需要和scrapy.Request()结合使用
    -面试题:
        -如何将一个网站中全站所有的链接都进行爬取。

- selenium在scrapy中的使用流程
    -1.在爬虫类中实例化一个浏览器对象,将其作为爬虫类的一个属性
    -2.在中间件中实现浏览器自动化相关的操作
    -3.在爬虫类中重写closed(self,spider),在其内部关闭浏览器对象

分布式
    实现方式:scrapytredis(scrapy结合着scrapy-redis组件)
        -原生的scrapy框架是无法实现分布式
        -什么是是分布式
            -需要搭建一个分布式的机群,让后让机群中的每一台电脑执行同一组程序,让其对同一组资源进行联合且分布的数据爬取。
        -为什么原生的scrapy框架无法实现分布式?
            -调度器无法被分布式机群共享管道无法分布式机群被共享
        -如何实现分布式:使用scrapy-redis组件即可
            -scrapy-redis组件的作用:
            -可以给原生的scrapy框架提供共享的管道和调度器
            - pip install scrapy-redis
实现流程
    1.修改爬虫文件
        -1.1导包:from scrapy redis.spiders import RedisCrawlSpider
        -1.2修改当前爬虫类的父类为:RedisCrawLSpider
        -1.3将start_url替换成redis_keys的属性,属性值为任意字符串
            redis_key=‘xxx':表示的是可以被共享的调度器队列的名称,最终是需要将起始的url手动放置到redis_key表示的队列中
        -1.4将数据解析的补充完整即可

    2.对settings.py进行配置
        -指定调度器
            #增加了一个去重容器类的配置,作用使用Redis的set集合来存储请求的指纹数据,
            DUPEFILTER_CLASS="scrapy_redis.dupefilter.RFPDupeFilter"
            #使用scrapy-redis组件自己的调度器
            SCHEDULER="scrapy_redis.scheduler.Scheduler""
            #配置调度器是否要持久化,也就是当爬虫结束了,要不要清空Redis中请求队列
            SCHEDULER_PERSIST = True
        -指定管道
            ITEM_PIPELINES ={
                "scrapy_redis.pipelines.RedisPipeline':400}
                特点:该种管道只可以将item写入redis
        -指定redis
            REDIS_HOST='redis服务的ip地址'
            REDIS_PORT= 6379
    3.配置redis的配置文件(redis.window.conf)解除默认绑定
           -56行:#bind 127.0.0.1
        -关闭保护模式
            -75行:protected-mode no
    4.启动redis服务和客户端
    5.执行scrapy工程(不要在配置文件中加入LOG_LEVEL)
        -程序会停留在Listening位置:等待起始的urL加入
    6.向redis_ey表示的队列中添加起始url
        -需要在redis的客户端执行如下指令:(调度器队列是存在于redis中)
            -lpush redis_key_name 初始网址

增量式
    -概念:监测网站数据更新的情况,以便于爬取到最新更新出来的数据。
    -实现核心:去重
    -实战中去重的方式:记录表
        -记录表需要记录什么?记录的一定是爬取过的相关信息。-爬取过的相关信息:每一部电影详情页的url
            -只需要使用某一组数据,该组数据如果可以作为该部电影的唯一标识即可,刚好电影详情页的url
                就可以作为电影的唯一标识。只要可以表示电影唯一标识的数据我们统称为数据指纹。
    -去重的方式对应的记录表:
        - python中的set集合(不可以)
            -set集合无法持久化存储
        - redis中的set可以的
            -可以持久化存储

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值