设为首页 加入收藏

TOP

关于python爬虫的一些面试题积累(一)
2023-07-23 13:44:04 】 浏览:34
Tags:关于 python

1、描述下 scrapy 框架运行的机制?

从 start_urls 里获取第一批 url 并发送请求,请求由引擎交给调度器入请求队列,获取完毕后,调度器将请求队列里的请求交给下载器去获取请求对应的响应资源,并将响应交给自己编写的解析方法做提取处理:

(1) 如果提取出需要的数据,则交给管道文件处理;

(2) 如果提取出 url,则继续执行之前的步骤(发送 url 请求,并由引擎将请求交给调度器入队列...),直到请求队列里没有请求,程序结束。

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 来说,上一次的状态是抓取的特征数据和上次爬取的 request 队列(url 列表),request 队列可以通过 request 队列可以通过 scrapy.core.scheduler 的 pending_requests 成员得到,在爬虫启动时导入上次爬取的特征数据,并且用上次 request 队列的数据作为 start url 进行爬取,不在上一次状态中的数据便保存。

选用 BloomFilter 原因:对爬虫爬取数据的保存有多种形式,可以是数据库,可以是磁盘文件等,不管是数据库,还是磁盘文件,进行扫描和存储都有很大的时间和空间上的开销,为了从时间和空间上提升性能,故选用 BloomFilter 作为上一次爬取数据的保存。保存的特征数据可以是数据的某几项,即监控这几项数据,一旦这几项数据有变化,便视为增量持久化下来,根据增量的规则可以对保存的状态数据进行约束。比如:可以选网页更新的时间,索引次数或是网页的实际内容,cookie 的更新等。

4、爬虫向数据库存数据开始和结束都会发一条消息,是 scrapy 哪个模块实现的?

Scrapy 使用信号来通知事情发生,因此答案是 signals 模块。

5、爬取下来的数据如何去重,说一下具体的算法依据?

(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)。

6、Scrapy 的优缺点?

优点

(1) scrapy 是异步的

(2) 采取可读性更强的 xpath 代替正则

(3)强大的统计和 log 系统

(4) 同时在不同的 url 上爬行

(5) 支持 shell 方式,方便独立调试

(6) 写 middleware,方便写一些统一的过滤器

(7) 通过管道的方式存入数据库

缺点

(1) 基于 python 的爬虫框架,扩展性比较差

(2) 基于 twisted 框架,运行中的 exception 是不会干掉 reactor(反应器),并且异步框架出错后是不会停掉其他任务的,数据出错后难以察觉。

7、什么是 scrapy-redis 中的指纹?是如何去重的?

指纹

通过 sha1 加密,把请求体,请求方式,请求 url 放在一起。然后进行 16 进制的转义符字符串生成指纹。生成一个字符串,放到数据库中作为唯一标示。

去重

url 中按照 url 去重:

(1) 按照 url 去重,有一个列表,发送请求之前从数据表中看一下这个 url有没有请求过,请求过了就不用看了

(2) 内容判断,从数据库中查数据的表示,如果请求过了就在不在请求了。

8、怎么设置深度爬取?

通过在 settings.py 中设置 depth_limit 的值可以限制爬取深度,这个深度是与 start_urls 中定义 url 的相对值。也就是相对 url 的深度。若定义 url 为 http://www.domz.com/game/,depth_limit=1 那么限制爬取的只能是此 url 下一级的网页。深度大于设置值的将被忽视。

9、scrapy 和 scrapy-redis 有什么区别?为什么选择 redis 数据库?

scrapy 是一个 Python 爬虫框架,爬取效率极高,具有高度定制性,但是不支持分布式。而scrapy-redis 一套基于 redis 数据库、运行在 scrapy 框架之上的组件,可以让 scrapy 支持分布策略,Slaver 端共享 Master 端 redis 数据库里的 item 队列、请求队列和请求指纹集合。

为什么选择 redis 数据库,因为 redis 支持主从同步,而且数据都是缓存在内存中的,所以基于 redis的分布式爬虫,对请求和数据的高频读取效率非常高。

10、分布式爬虫主要解决什么问题?

主要解决一下 4 个问题:

(1) ip

(2) 带宽

(3) cpu

(4) io

11、什么是反向代理?作用是什么?

代理可以假扮 Web 服务

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Django笔记九之model查询filter、.. 下一篇【manim动画教程】-- 安装

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目