附答案 | 最强Python面试题之爬虫常见问题(1)

写在之前

大家好呀,我是帅蛋。

开心开心,今天又开始新的专题啦!Python 爬虫系列!!主要分为两部分内容来讲呀,一部分是常见问题,另一部分是框架问题,Python 面试八股文尽在帅蛋的【最强Python面试题】,大家一定要记得点赞收藏呀!!!

欢迎和帅蛋聊一聊~扣扣2群:609771600,获取最新秋招信息 & 内推进度,日常聊聊迷茫吹吹牛皮,抱团取暖

顺便提一句,我所有和面试相关的内容都会放在#帅蛋的面试空间# 中,大家可以关注下这个话题~

我会尽我最大的努力帮助到大家哒!!!

主要内容

这些面试题是我结合自己的经验整理的,主要就是下面这 5 个专题:

  • Python 基础面试题(已完成
  • Python 进阶(已完成
  • Python 后台开发(已完成
  • 爬虫
  • 机器学习

PS:往期文章可以看文末链接哟~


对每道面试题我都会附带详细的答案,有些我觉得重要的内容会详细讲解,虽然是面试八股文,我还是希望大家不是只“知其然”,更得“知其所以然”

关于更新频率,每天我会更新 10 道题左右,总共会有差不多 200 道。

无论是准备面试还是自己学习,这份面试题绝对值得你去看,去学习。

大家可以关注我,再关注我,使劲关注我,不要错过每天的更新~

以下是正文

Python 爬虫常见问题第一部分,大家一定要记得点赞收藏,一起加油!

1、爬取数据后使用哪个数据库存储数据的,为什么?

MongoDB 是使用比较多的数据库,这里以 MongoDB 为例,大家需要结合自己真实开发环境回答。

原因:

1.与关系型数据库相比,MongoDB 的优点如下。

(1) 弱一致性(最终一致),更能保证用户的访问速度

举例来说,在传统的关系型数据库中,一个 COUNT 类型的操作会锁定数据集,这样可以保证得到“当前”情况下的较精确值。这在某些情况下,例 如通过 ATM 查看账户信息的时候很重要,但对于 Wordnik 来说,数据是不断更新和增长的,这种“较精确”的保证几乎没有任何意义,反而会产生很大的延 迟。他们需要的是一个“大约”的数字以及更快的处理速度。

但某些情况下 MongoDB 会锁住数据库。如果此时正有数百个请求,则它们会堆积起来,造成许多问题。我们使用了下面的优化方式来避免锁定。

每次更新前,我们会先查询记录。查询操作会将对象放入内存,于是更新则会尽可能的迅速。在主/从部署方案中,从节点可以使用“-pretouch”参数运行,这也可以得到相同的效果。

使用多个 mongod 进程。我们根据访问模式将数据库拆分成多个进程。

(2) 文档结构的存储方式,能够更便捷的获取数据。

对于一个层级式的数据结构来说,如果要将这样的数据使用扁平式的,表状的结构来保存数据,这无论是在查询还是获取数据时都十分困难。

(3) 内置 GridFS,支持大容量的存储。

GridFS 是一个出色的分布式文件系统,可以支持海量的数据存储。内置了 GridFS 了 MongoDB,能够满足对大数据集的快速范围查询。

(4) 内置 Sharding。

提供基于 Range 的 Auto Sharding 机制:一个 collection 可按照记录的范围,分成若干个段,切分到不同的Shard上。Shards可以和复制结合,配合Replica sets能够实现Sharding+fail-over,不同的 Shard 之间可以负载均衡。查询是对 客户端是透明的。客户端执行查询,统计,MapReduce 等操作,这些会被 MongoDB 自动路由到后端的数据节点。这让我们关注于自己的业务,适当的时候可以无痛的升级。MongoDB 的 Sharding 设计能力较大可支持约 20 petabytes,足以支撑一般应用。

这可以保证 MongoDB 运行在便宜的 PC 服务器集群上。PC 集群扩充起来非常方便并且成本很低,避免了“sharding”操作的复杂性和成本。

(5) 第三方支持丰富。(这是与其他的 NoSQL 相比,MongoDB 也具有的优势)

现在网络上的很多 NoSQL 开源数据库完全属于社区型的,没有官方支持,给使用者带来了很大的风险。而开源文档数据库 MongoDB 背后有商业公司 10gen 为其提供供商业培训和支持。而且 MongoDB 社区非常活跃,很多开发框架都迅速提供了对 MongDB 的支持。不少知名大公司和网站也在生产环境中使用MongoDB,越来越多的创新型企业转而使用 MongoDB 作为和 Django,RoR 来搭配的技术方案。

(6) 性能优越

在使用场合下,千万级别的文档对象,近 10G 的数据,对有索引的 ID 的查询不会比 mysql 慢,而对非索引字段的查询,则是全面胜出。 mysql 实际无法胜任大数据量下任意字段的查询,而 mongodb 的查询性能实在让我惊讶。写入性能同样很令人满意,同样写入百万级别的数据,mongodb 比我以前试用过的couchdb 要快得多,基本 10 分钟以下可以解决。补上一句,观察过程中 mongodb 都远算不上是 CPU 杀手。

2.Mongodb 与 redis 相比较

(1) mongodb 文件存储是 BSON 格式类似 JSON,或自定义的二进制格式。mongodb 与 redis 性能都很依赖内存的大小,mongodb 有丰富的数据表达、索引;最类似于关系数据库,支持丰富的查询语言,redis 数据丰富,较少的 IO ,这方面 mongodb 优势明显。

(2) mongodb 不支持事物,靠客户端自身保证,redis 支持事物,比较弱,仅能保证事物中的操作按顺序执行,这方面 redis 优于 mongodb。

(3) mongodb 对海量数据的访问效率提升,redis 较小数据量的性能及运算,这方面 mongodb 性能优于 redis.monbgodb 有mapredurce功能,提供数据分析,redis 没有,这方面 mongodb 优于 redis。

2、你用过的爬虫框架或者模块有哪些?谈谈他们的区别或者优缺点?

用过的:

(1) Python 自带:urllib、urllib2

urllib 和 urllib2 模块都做与请求 URL 相关的操作,但他们提供不同的功能。

urllib2:urllib2.urlopen 可以接受一个 Request 对象或者 url,(在接受 Request 对象时候,并以此可以来设置一个 URL 的 headers),urllib.urlopen 只接收一个 url。

urllib 有 urlencode,urllib2 没有,因此总是 urllib,urllib2 常会一起使用的原因。

(2) 第三方:requests

request 是一个 HTTP 库, 它只是用来,进行请求,对于 HTTP 请求,他是一个强大的库,下载,解析全部自己处理,灵活性更高,高并发与分布式部署也非常灵活,对于功能可以更好实现

(3) 框架: Scrapy

scrapy 是封装起来的框架,它包含了下载器,解析器,日志及异常处理,基于多线程,twisted 的方式处理,对于固定单个网站的爬取开发,有优势,但是对于多网站爬取,并发及分布式处理方面,不够灵活,不便调整与括展。

Scrapy 优点

scrapy 是异步的

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

强大的统计和 log 系统

同时在不同的 url 上爬行

支持 shell 方式,方便独立调试

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

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

Scrapy 缺点

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

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

3、写爬虫是用多进程好?还是多线程好? 为什么?

IO 密集型代码(文件处理、网络爬虫等),多线程能够有效提升效率(单线程下有 IO 操作会进行 IO 等待,造成不必要的时间浪费,而开启多线程能在线程 A 等待时,自动切换到线程 B,可以不浪费 CPU 的资源,从而能提升程序执行效率)。在实际的数据采集过程中,既考虑网速和响应的问题,也需要考虑自身机器的硬件情况,来设置多进程或多线程。

4、常见的反爬虫和应对方法?

(1) 通过 Headers 反爬虫

从用户请求的 Headers 反爬虫是最常见的反爬虫策略。很多网站都会对 Headers 的 User-Agent 进行检测,还有一部分网站会对 Referer 进行检测(一些资源网站的防盗链就是检测 Referer)。如果遇到了这类反爬虫机制,可以直接在爬虫中添加 Headers,将浏览器的 User-Agent 复制到爬虫的 Headers 中;或者将 Referer 值修改为目标网站域名。对于检测 Headers 的反爬虫,在爬虫中修改或者添加 Headers 就能很好的绕过。

(2) 基于用户行为反爬虫

还有一部分网站是通过检测用户行为,例如同一 IP 短时间内多次访问同一页面,或者同一账户短时间内多次进行相同操作。

大多数网站都是前一种情况,对于这种情况,使用 IP 代理就可以解决。可以专门写一个爬虫,爬取网上公开的代理 ip,检测后全部保存起来。这样的代理 ip 爬虫经常会用到,最好自己准备一个。有了大量代理 ip 后可以每请求几次更换一个 ip,这在 requests 或者 urllib2 中很容易做到,这样就能很容易的绕过第一种反爬虫。

对于第二种情况,可以在每次请求后随机间隔几秒再进行下一次请求。有些有逻辑漏洞的网站,可以通过请求几次,退出登录,重新登录,继续请求来绕过同一账号短时间内不能多次进行相同请求的限制。

(3) 动态页面的反爬虫

上述的几种情况大多都是出现在静态页面,还有一部分网站,我们需要爬取的数据是通过 ajax 请求得到,或者通过 JavaScript 生成的。首先用 Fiddler 对网络请求进行分析。如果能够找到 ajax 请求,也能分析出具体的参数和响应的具体含义,我们就能采用上面的方法,直接利用 requests 或者 urllib2模拟 ajax 请求,对响应的 json 进行分析得到需要的数据。

能够直接模拟 ajax 请求获取数据固然是极好的,但是有些网站把 ajax 请求的所有参数全部加密了。我们根本没办法构造自己所需要的数据的请求。这种情况下就用 selenium+phantomJS,调用浏览器内核,并利用 phantomJS 执行 js 来模拟人为操作以及触发页面中的 js 脚本。从填写表单到点击按钮再到滚动页面,全部都可以模拟,不考虑具体的请求和响应过程,只是完完整整的把人浏览页面获取数据的过程模拟一遍。

用这套框架几乎能绕过大多数的反爬虫,因为它不是在伪装成浏览器来获取数据(上述的通过添加Headers 一定程度上就是为了伪装成浏览器),它本身就是浏览器,phantomJS 就是一个没有界面的浏览器,只是操控这个浏览器的不是人。利 selenium+phantomJS 能干很多事情,例如识别点触式(12306)或者滑动式的验证码,对页面表单进行暴力破解等。

5、需要登录的网页,如何解决同时限制 ip,cookie,session(其中有一些是动态生成的)在不使用动态爬取的情况下?

(1) 解决限制 IP 可以使用代理 IP 地址池、服务器

(2)不适用动态爬取的情况下可以使用反编译 JS 文件获取相应的文件,或者换用其他平台(比如手机端)看看是否可以获取相应的 json 文件。

6、验证码的解决?

(1) 图形验证码

干扰、杂色不是特别多的图片可以使用开源库 Tesseract 进行识别,太过复杂的需要借助第三方打码平台。

(2) 滑块验证码

点击和拖动滑块验证码可以借助 selenium、无图形界面浏览器(chromedirver 或者 phantomjs)和pillow 包来模拟人的点击和滑动操作,pillow 可以根据色差识别需要滑动的位置。

7、使用最多的数据库(Mysql,Mongodb,redis 等),对他们的理解?

(1) MySQL 数据库

开源免费的关系型数据库,需要实现创建数据库、数据表和表的字段,表与表之间可以进行关联(一对多、多对多),是持久化存储。

(2) Mongodb 数据库

非关系型数据库,数据库的三元素是,数据库、集合、文档,可以进行持久化存储,也可作为内存数据库,存储数据不需要事先设定格式,数据以键值对的形式存储。

(3) redis 数据库

非关系型数据库,使用前可以不用设置格式,以键值对的方式保存,文件格式相对自由,主要用与缓存数据库,也可以进行持久化存储。

8、写一个邮箱地址的正则表达式?

[A-Za-z0-9_-]+@[a-zA-Z0-9_-]+(.[a-zA-Z0-9_-]+)+$

9、如何定时启动你的爬虫项目?

(1) 最简单的方法:直接使用 Timer 类

1. import time
2. import os
3.
4. while True:
5. os.system("scrapy crawl News")
6. time.sleep(86400) #每隔一天运行一次 24*60*60=86400s

(2) 使用 sched

1. import sched
2. #初始化 sched 模块的 scheduler 类
3. #第一个参数是一个可以返回时间戳的函数,第二个参数可以在定时未到达之前阻塞。
4. schedule = sched.scheduler ( time.time, time.sleep )
5.
6. #被周期性调度触发的函数
7. def func():
8. os.system("scrapy crawl News")
9. def perform1(inc):
10. schedule.enter(inc,0,perform1,(inc,))
11. func() # 需要周期执行的函数
12. def mymain():
13. schedule.enter(0,0,perform1,(86400,))
14.
15. if __name__=="__main__":
16. mymain()
17. schedule.run() # 开始运行,直到计划时间队列变成空为止

(3) 使用 Crontab

10、爬的那些内容数据量有多大,多久爬一次,爬下来的数据是怎么存储?

京东整站的数据大约在 1 亿左右,爬下来的数据存入数据库,mysql 数据库中如果有重复的 url 建议去重存入数据库,可以考虑引用外键。评分、评论如果做增量,Redis 中 url 去重,评分和评论建议建立一张新表用 id 做关联。

多久爬一次这个问题要根据公司的要求去处理,不一定是每天都爬。

Mongo 建立唯一索引键(id)可以做数据重复 前提是数据量不大, 2 台电脑几百万的情况 数据库需要做分片 (数据库要设计合理)。

例:租房的网站数据量每天大概是几十万条 ,每周固定爬取。

已完成

Python 基础题

Python 进阶题

Python 后台开发


以上就是今天的内容,我是帅蛋,我们明天见~

❤️ 欢迎关注我,有问题,找帅蛋,我最看不得别人迷茫!

❤️ 如果你觉得有帮助,希望爱学习的你不要吝啬三连击哟[点赞 + 收藏 + 评论]~

还有小小公众号 【编程文青李狗蛋】,聊聊迷茫吹吹牛皮~

#帅蛋的面试空间##面试八股文##23届秋招##Python##python面试#
全部评论
来啦!兄弟们顶起来!!
点赞 回复 分享
发布于 2022-08-26 11:02 山东
点赞 回复 分享
发布于 2022-08-26 12:57 上海
点赞 回复 分享
发布于 2022-08-26 16:04 北京
分享的很好,继续催更!
点赞 回复 分享
发布于 2022-08-26 16:05 安徽
码住学习
点赞 回复 分享
发布于 2022-08-26 16:12 广东
来了!我是帅蛋忠实读者!赶快更!
点赞 回复 分享
发布于 2022-08-27 11:20 湖北
码住学习
点赞 回复 分享
发布于 2022-08-27 21:53 上海
点赞 回复 分享
发布于 2022-08-28 09:56 广东
爱了爱了
点赞 回复 分享
发布于 2022-09-03 12:01 江苏

相关推荐

评论
20
71
分享
牛客网
牛客企业服务