- 什么是scrapy
- 爬虫中封装好的一个框架
- 功能:高性能的持久化存储,异步的数据下载,高性能的数据解析,分布式
- scrapy环境的搭建
- pip install wheel (服务第2步与第3步操作)
- 下载twisted包 (scrapy借助它完成了异步数据下载),下载地址:http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
- 安装twisted: pip install 下好的twisted包存放路径+包名 (对应的python版本就下载)
- pip install pywin32
- pip install scrapy
测试:在终端里录入scrapy指令,没有报错即表示安装成功!
- 使用scrapy
- 创建一个工程:找到一个工作目录 使用cmd命令执行:scrapy startproject 工程名称
- 此时就会在对应的工作目录中生成一个目录
- cd 工程名称
- 在spiders子目录中创建一个爬虫文件
- scrapy genspider 爬虫名称 www.xxx.com LinkedIn
- 执行工程:在cmd中执行
- scrapy crawl 爬虫名称 【--nolog】#表示不打印日志信息,同时也会忽略错误信息
注意在执行工程之前要干三件事
修饰配置文件settings.py里面的ROBOTSTXT_OBEY的值改为False
在配置文件settings.py中取消里面的注释 UA伪装
向配置文件settings.py中添加 LOG_LEVEL="ERROR" 显示错误信息
#设置字符集 FEED_EXPORT_ENCODING = 'utf-8' #添加
- 项目结构:
|-- proName
|-- reProName
|--spiders 【爬虫文件夹,放置爬虫文件,】
|-- 爬虫源文件.py 【命令创建:scrapy genspider 爬虫名称 www.xxx.com】
|-- init.py 【】
|-- items.py 【将解析到的数据封装到item对象中】
|-- middlewares.py 【中间件】
|-- pipelines.py 【管道文件:用于清洗、验证、导出到外部文件、存储到数据库等,一个管道类对应一个持久化存储方式】
管道文件中可以自定义管道类,定义之后的管道类需要到配置文件中注册
|-- settings.py 【工程的配置文件】
|-- scrapy.cfg
scrapy进行数据解析:
在爬虫文件中有一个parse函数,这个函数就是用于数据解析的
def parse(self,response):#parse会被调用多次,数量由start_urls中的url个数所决定
#response就是请求返回的url
#使用xpath对响应数据进行解析,xpath返回的是一个列表,元素是Selector对象
#取出Selector对象中的数据需要使用:extract_first() extract()
res=response.xpath("xpath表达式").extract_first() extract_first表示取出第一个元素的data数据
res=response.xpath("xpath表达式").extract() extract对列表中的每一个元素进行操作,取出里面的data数据
extract返回还是一个列表,需要转换成字符串,需要使用"".join()方法
response.text 获取页面,源码文本数据
response.body 获取响应中的二进制数据
scrapy进行持久化存储:
两种方式:
- 基于终端指令:scrapy crawl 爬虫名称 -o 存储的路径和文件名称
- 只能存储parse方法的返回值,存储到本地的文本文件中
- 注意:只能存储到('json', 'jsonlines', 'jl', 'csv', 'xml', 'marshal', 'pickle')类型的文件中
- 好处:简洁高效
- 缺点:只能存储到指定的文件类型中
- 基于管道:scrapy crawl 爬虫名称
- 编码流程:
- 数据解析
- 先在item类中定义要存储的数据字段名称
- 将解析到数据封装到item类型的对象中(process_item这个函数是管道专门用于数据持久化存储的,它只能接收item对象,所以要将数据先封装到item对象中)
- 将item对象提交到管道,实现数据持久化存储
- 在管道类的process_item中要将其接收到的item对象中存储的数据进行持久化存储操作,()
- 在settings文件中开启管道 (ITEM_PIPELINES)
- 好处:通用性强
- 缺点:比较繁琐
- 面试题:将爬取到的数据一份存储到本地一份存储到数据库,如何实现?
- 创建两个管道类:一个管道类对应一个存储方式,
- 爬虫文件将item提交给级别最高的爬虫类,
- 在process_item中使用return item将item传递给下一个管道类
- 基于Spider的全站数据的爬取
- 全站数据爬取:将网页某板块对应的全部页码对应数据进行爬取
- 案例:爬取校花网
- 全站数据爬取:需要使用手动发送请求
- yield scrapy.Requests(url=new_url,callback=回调函数)递归调用的话,就需要由结束条件
- 请求传参:
- 使用场景:(爬取的数据不在同一张页面中)解析的数据不在同一张页面中,
(深度爬取:首页中提取出详情页中url,然后爬取详情页,详情页的解析与首页的解析不是同一个解析函数,导致item无法使用,需要在scrapy.Request()中设置meta={"item":item}传递参数,传给详情页的解析函数)
- 爬取:水浒传:爬取文章标题,与详情页的文章内容 https://www.shicimingju.com/book/shuihuzhuan.html
- 图片数据爬取:
- ImagesPipeline 专门用于爬取图片的管道类,自己封装一个管道类,管道类需要继承这个类ImagesPipeline=》from scrapy.pipelines.images import ImagesPipeline
- ImagesPipeline作用:
- 需要在解析函数中,将图片的url,提交到管道,管道就会单独对图片发送请求,然后在进行持久化存储
ImagesPipeline使用流程:
- 在管道文件中导入该类:from scrapy.pipelines.images import ImagesPipeline
- 自己封装一个管道类,继承ImagesPipeline
- 自己手动重写父类的方法
- def get_media_requests(self, item, info) ==》需要手动发送请求,(同时系统会自动将请求的数据保存下来)
- def file_path(self, request, response=None, info=None, *, item=None): 设置图片的名称,一般通过request.url.split("/")[-1]对每个图片命名
- def item_completed(self, results, item, info): 将item传递给下一个管道类
- 在settings配置文件中添加:IMAGES_STORE="指定图片存放的目录"
- 在settings配置文件中开启管道类
爬取站长素材中的图片:https://sc.chinaz.com/tupian/
- 图片懒加载:只有当浏览器的可视窗口滑动到了图片,图片才会加载出来
- 一般的,图片懒加载,使用的都是伪属性,进行加载,所以在解析图片地址的时候,需要使用伪属性进行解析
- 中间件:
- 下载中间件DownloaderMiddleware:处于引擎与下载器之间
- 作用:可以拦截请求,响应数据
- 拦截请求:
- 可以进行UA伪装,反爬,可以对每一个请求单独的设置请求头与UA
- 写在process_request函数中 request.header["User-Agent"]=
- 代理ip
- 写在process_exception函数中 request.meta["proxy"]=修改ip
- 拦截响应数据
- 篡改响应数据与响应对象
-案例:网页新闻五大板块的新闻的标题与详情页的内容
- 先找到国内,国际,军事,航空,无人机对应的url
- 但是每个模块对应的新闻,都是动态加载出来的,需要使用到中间件
- 爬虫中间件SpiderMiddleware:处于引擎与爬虫文件之间
- 使用中间件(需要在配置文件中开启中间件)
- CrawlSpider类:是Spider的一个子类
- 全站数据爬取
- 两种方式:
- 基于Spider:发起手动请求scrapy.Request()
- 基于CrawSpider:基于CrawSpider的爬虫文件进行全站数据爬取
- 使用流程:
- 创建工程
- cd 工程名
- 创建爬虫文件 :scrapy genspider -t crawl 爬虫名称 www.xx.com
- 规则解析器Rule( LinkExtractor(allow="正则表达式"),callback='parse_item', follow=True)
- 作用:将链接提取器提取到的链接,进行指定规则的解析(callback回调函数进行数据解析)
- 链接提取器:LinkExtractor(allow="正则表达式")
- 作用:根据指定规则提取url链接,并对这些url进行自动的请求发送
- 指定规则:allow="正则表达式" 根据正则提取符合要求的链接
- 分布式爬虫
- 作用:提升爬取效率
- 实现:安装 pip install scrapy-redis
- 原生的scrap不能实现分布式爬虫
- 为什么原生的scrapy不可以实现分布式?
- 调度器不可以被分布式机群共享
- 管道不可以被分布式机群共享
- scrapy-redis组件作用:
- 可以给原生的scrapy框架提供可以被共享的管道和调度器
twisted 下载地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
安装twisted:pip install twisted下载到的路径+包名称