-创建一个工程 -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可以的 -可以持久化存储
Scrapy框架笔记
于 2023-10-21 21:14:08 首次发布