概述
1. 描述下scrapy 框架运行的机制?
从 start_urls 里获取第一批 url 并发送请求,请求由引擎交给调度器入请求队列,获取完毕后,调度器将请求队列里的请求交给下载器去获取请求对应的响应资源,并将响应交给自己编写的解析方法做提取处理:
1. 如果提取出需要的数据,则交给管道文件处理;
2. 如果提取出 url,则继续执行之前的步骤(发送 url 请求,并由引擎将请求交给调度器入队列...), 直到请求队列里没有请求,程序结束。
3. 根据 scrapy 的流程图,描述出五大组件、两个中间件,以及完成一个请求的流程。
2. 谈谈你对Scrapy 的理解?
scrapy 是一个为了爬取网站数据,提取结构性数据而编写的应用框架,我们只需要实现少量代码, 就能够快速的抓取到数据内容。Scrapy 使用了 Twisted 异步网络框架来处理网络通讯,可以加快我们的下载速度,不用自己去实现异步框架,并且包含了各种中间件接口,可以灵活的完成各种需求。
scrapy 框架的工作流程:
1. 首先 Spiders(爬虫)将需要发送请求的 url(requests)经 ScrapyEngine(引擎)交给 Scheduler
(调度器)。
2. Scheduler(排序,入队)处理后,经 ScrapyEngine,DownloaderMiddlewares(可选,主要有 User_Agent, Proxy 代理)交给 Downloader。
3. Downloader 向互联网发送请求,并接收下载响应(response)。将响应(response)经
ScrapyEngine,SpiderMiddlewares(可选)交给 Spiders。
4. Spiders 处理 response,提取数据并将数据经 ScrapyEngine 交给ItemPipeline 保存(可以是本地,可以是数据库)。提取 url 重新经 ScrapyEngine 交给 Scheduler 进行下一个循环。直到无 Url 请求程序停止结束。
3. 怎么样让 scrapy 框架发送一个 post 请求(具体写出来)
使 用 FormRequest
4. 怎么判断网站是否更新?
静态页面可以考虑使用 http 的 head 方法查看网站的最后更新时间
如果前者行不通,则需要对数据进行标识,如利用加密算法生成指纹,然后定期发起请求获取数据,比对指纹是否一致,如果一致,说明网站没有更新;反之说明更新。
5. 图片、视频爬取怎么绕过防盗连接,或者说怎么获取正确的链接地址?
自定义 Referer(建议自行 Google 相关知识)。
6. 你爬出来的数据量大概有多大?大概多长时间爬一次?
无标准答案,根据自己爬取网站回答即可(几百万,几千万,亿级)。 根据项目需求来定,另外并发量根据网站反爬和机器数量带宽大小来计算
7. 增量爬取
实现一个持久化的请求队列
增量爬取即保存上一次状态,本次抓取时与上次比对,如果不在上次的状态中,便视为增量,保存下来。对于 scrapy 来说,上一次的状态是抓取的特征数据和上次爬取的
request 队列(url 列表),request 队列可以通过 request 队列可以通过
scrapy.core.scheduler 的 pending_requests 成员得到,在爬虫启动时导入上次爬取的特征数据,并且用上次 request 队列的数据作为 start url 进行爬取,不在上一次状态中的数据便保存。
选用 BloomFilter 原因:对爬虫爬取数据的保存有多种形式,可以是数据库,可以是磁盘文件等,不管是数据库,还是磁盘文件,进行扫描和存储都有很大的时间和空间上的开
销,为了从时间和空间上提升性能,故选用 BloomFilter 作为上一次爬取数据的保存。保存的特征数据可以是数据的某几项,即监控这几项数据,一旦这几项数据有变化,便视为增
量持久化下来,根据增量的规则可以对保存的状态数据进行约束。比如:可以选网页更新的时间,索引次数或是网页的实际内容,cookie 的更新等。
8. 爬虫向数据库存数据开始和结束都会发一条消息,是 scrapy 哪个模块实现的?
Scrapy 使用信号来通知事情发生,因此答案是 signals 模块。
9. 爬取下来的数据如何去重,说一下具体的算法依据
1. 通过 MD5 生成电子指纹来判断页面是否改变
2. nutch 去重。nutch 中 digest 是对采集的每一个网页内容的 32 位哈希值,如果两个网页内容完全一样,它们的 digest 值肯定会一样。
数据量不大时,可以直接放在内存里面进行去重,python 可以使用set()进行去重。当去重数据需要持久化时可以使用 redis 的 set 数据结构。
当数据量再大一点时,可以用不同的加密算法先将长字符串压缩成 16/32/40 个字符,再使用上面两种方法去重。
当数据量达到亿(甚至十亿、百亿)数量级时,内存有限,必须用“位”来去重,才能够满足需求。Bloomfilter 就是将去重对象映射到几个内存“位”,通过几个位的 0/1 值来判断一个对象是否已经存在。
然而 Bloomfilter 运行在一台机器的内存上,不方便持久化(机器 down 掉就什么都没啦),也不方便分布式爬虫的统一去重。如果可以在 Redis 上申请内存进行 Bloomfilter,以上两个问题就都能解决了。
simhash 最牛逼的一点就是将一个文档,最后转换成一个 64 位的字节,暂且称之为特征字,然后判断重复只需要判断他们的特征字的距离是不是<n(根据经验这个 n 一般取值为 3),就可以判断两个文档是否相似。
可见 scrapy_redis 是利用 set 数据结构来去重的,去重的对象是 request 的 fingerprint(其实就是用 hashlib.sha1()对 request 对象的某些字段信息进行压缩)。其实 fp 就是 request 对象加密压缩后的一个字符串(40 个字符,0~f)。
优点:
1)scrapy 是 异 步 的2)采取可读性更强的 xpath 代替正则
3) 强大的统计和 log 系统
4) 同时在不同的 url 上爬行
5) 支持 shell 方式,方便独立调试
5)写 middleware,方便写一些统一的过滤器6)通过管道的方式存入数据库
缺点:
1) 基于 python 的爬虫框架,扩展性比较差
2) 基于 twisted 框架,运行中的 exception 是不会干掉 reactor(反应器),并且异步框架出错后是不会停掉其他任务的,数据出错后难以察觉。
11. 怎么设置深度爬取?
通过在 settings.py 中设置 depth_limit 的值可以限制爬取深度,这个深度是与 start_urls 中定义 url 的相对值。也就是相对 url 的深度。若定义 url 为
http://www.domz.com/game/,depth_limit=1 那么限制爬取的只能是此 url 下一级的网页。深度大于设置值的将被忽视。
1. scrapy 和scrapy-redis 有什么区别?为什么选择redis 数据库?
scrapy 是一个 Python 爬虫框架,爬取效率极高,具有高度定制性,但是不支持分布式。而scrapy-redis 一套基于redis 数据库、运行在 scrapy 框架之上的组件,可以让 scrapy 支持分布式策略,
Slaver 端共享 Master 端 redis 数据库里的 item 队列、请求队列和请求指纹集合。
为什么选择 redis 数据库,因为 redis 支持主从同步,而且数据都是缓存在内存中的,所以基于 redis 的分布式爬虫,对请求和数据的高频读取效率非常高。
3. 什么是分布式存储?
传统定义:分布式存储系统是大量 PC 服务器通过 Internet 互联,对外提供一个整体的服务。分布式存储系统具有以下的几个特性:
可扩展 :分布式存储系统可以扩展到几百台甚至几千台这样的一个集群规模,系统的整体性能线性增长。
低成本 :分布式存储系统的自动容错、自动负载均衡的特性,允许分布式存储系统可以构建在低成本的服务器上。另外,线性的扩展能力也使得增加、减少服务器的成本低, 实现分布式存储系统的自动运维。
高性能 :无论是针对单台服务器,还是针对整个分布式的存储集群,都要求分布式存储系统具备高性能。
易用 :分布式存储系统需要对外提供方便易用的接口,另外,也需要具备完善的监控、运维工具,并且可以方便的与其他的系统进行集成。
布式存储系统的挑战主要在于数据和状态信息的持久化,要求在自动迁移、自动容错和并发读写的过程中,保证数据的一致性。
容错:可以快速检测到服务器故障,并自动的将在故障服务器上的数据进行迁移。
负载均衡:新增的服务器在集群中保障负载均衡?数据迁移过程中保障不影响现有的服务。
事务与并发控制:实现分布式事务。
易用性:设计对外接口,使得设计的系统易于使用。
4. 你所知道的分布式爬虫方案有哪些?
三种分布式爬虫策略:
1. Slaver 端从 Master 端拿任务(Request/url/ID)进行数据抓取,在抓取数据的同时也生成新任务,并将任务抛给 Master。Master 端只有一个 Redis 数据库,负责对 Slaver 提交的任务进行去重、加入待爬队列。
优点: scrapy-redis 默认使用的就是这种策略,我们实现起来很简单,因为任务调度
等工作 scrapy-redis 都已经帮我们做好了,我们只需要继承 RedisSpider、指定 redis_key 就行了。
缺点: scrapy-redis 调度的任务是 Request 对象,里面信息量比较大(不仅包含 url, 还有 callback 函数、headers 等信息),导致的结果就是会降低爬虫速度、而且会占用
Redis 大量的存储空间。当然我们可以重写方法实现调度 url 或者用户 ID。
2. Master 端跑一个程序去生成任务(Request/url/ID)。Master 端负责的是生产任务, 并把任务去重、加入到待爬队列。Slaver 只管从 Master 端拿任务去爬。
优点: 将生成任务和抓取数据分开,分工明确,减少了 Master 和 Slaver 之间的数据交流;Master 端生成任务还有一个好处就是:可以很方便地重写判重策略(当数据量大时优化判重的性能和速度还是很重要的)。
缺点: 像 QQ 或者新浪微博这种网站,发送一个请求,返回的内容里面可能包含几十个待爬的用户 ID,即几十个新爬虫任务。但有些网站一个请求只能得到一两个新任务,并且返回的内容里也包含爬虫要抓取的目标信息,如果将生成任务和抓取任务分开反而会降
低爬虫抓取效率。毕竟带宽也是爬虫的一个瓶颈问题,我们要秉着发送尽量少的请求为原则,同时也是为了减轻网站服务器的压力,要做一只有道德的 Crawler。所以,视情况而定。
3. Master 中只有一个集合,它只有查询的作用。Slaver 在遇到新任务时询问 Master 此任务是否已爬,如果未爬则加入 Slaver 自己的待爬队列中,Master 把此任务记为已爬。它和策略一比较像,但明显比策略一简单。策略一的简单是因为有 scrapy-redis 实现了
scheduler 中间件,它并不适用于非 scrapy 框架的爬虫。
优点: 实现简单,非 scrapy 框架的爬虫也适用。Master 端压力比较小,Master 与
Slaver 的数据交流也不大。
缺点:“健壮性”不够,需要另外定时保存待爬队列以实现“断点续爬”功能。各 Slaver 的待爬任务不通用。
如果把 Slaver 比作工人,把 Master 比作工头。策略一就是工人遇到新任务都上报给工头,需要干活的时候就去工头那里领任务;策略二就是工头去找新任务,工人只管从工头那里领任务干活;策略 三就是工人遇到新任务时询问工头此任务是否有人做了,没有的话工人就将此任务加到自己的“行程表”。
5. 除了 scrapy-redis,有做过其他的分布式爬虫吗?
Celery、gearman 等,参考其他分布式爬虫策略。
6. 在爬取的时候遇到某些内容字段缺失怎么判断及处理?
判读字段缺失,做异常处理即可。
最后
以上就是温婉衬衫为你收集整理的067、Scrapy常见问题1. 描述下scrapy 框架运行的机制?2. 谈谈你对Scrapy 的理解?3. 怎么样让 scrapy 框架发送一个 post 请求(具体写出来)4. 怎么判断网站是否更新?5. 图片、视频爬取怎么绕过防盗连接,或者说怎么获取正确的链接地址?6. 你爬出来的数据量大概有多大?大概多长时间爬一次?7. 增量爬取8. 爬虫向数据库存数据开始和结束都会发一条消息,是 scrapy 哪个模块实现的?9. 爬取下来的数据如何去重,说一下具体的算法依据11. 怎么设置深度爬取的全部内容,希望文章能够帮你解决067、Scrapy常见问题1. 描述下scrapy 框架运行的机制?2. 谈谈你对Scrapy 的理解?3. 怎么样让 scrapy 框架发送一个 post 请求(具体写出来)4. 怎么判断网站是否更新?5. 图片、视频爬取怎么绕过防盗连接,或者说怎么获取正确的链接地址?6. 你爬出来的数据量大概有多大?大概多长时间爬一次?7. 增量爬取8. 爬虫向数据库存数据开始和结束都会发一条消息,是 scrapy 哪个模块实现的?9. 爬取下来的数据如何去重,说一下具体的算法依据11. 怎么设置深度爬取所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复