爬虫知识综合

1.  Scrapy怎么设置深度爬取?

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

2.怎么样让scrapy框架发送一个post请求(具体写出来)

爬虫知识综合_第1张图片

3.用什么方法提取数据?

答:可以使用正则、xpath、json、pyquery、bs4等(任选一二即可)。

4.写一个邮箱地址的正则表达式?

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

5.平常怎么使用代理的 ?

1.  自己维护代理池

2.  付费购买(目前市场上有很多ip代理商,可自行百度了解,建议看看他们的接口文档(API&SDK))

6.代理IP里的“透明”“匿名”“高匿”分别是指?

透明代理的意思是客户端根本不需要知道有代理服务器的存在,但是它传送的仍然是真实的IP。你要想隐藏的话,不要用这个。  

普通匿名代理能隐藏客户机的真实IP,但会改变我们的请求信息,服务器端有可能会认为我们使用了代理。不过使用此种代理时,虽然被访问的网站不能知道你的ip地址,但仍然可以知道你在使用代理,当然某些能够侦测ip的网页仍然可以查到你的ip。

高匿名代理不改变客户机的请求,这样在服务器看来就像有个真正的客户浏览器在访问它,这时客户的真实IP是隐藏的,服务器端不会认为我们使用了代理。

7. IP存放在哪里?怎么维护IP?对于封了多个ip的,怎么判定IP没被封?

存放在数据库(redis、mysql等)

维护多个代理网站

一般代理的存活时间往往在十几分钟左右,定时任务,加上代理IP去访问网页,验证其是否可用,如果返回状态为200,表示这个代理是可以使用的。

8.怎么获取加密的数据?

1.  Web端加密可尝试移动端(app)

2.  解析加密,看能否破解

3.  反爬手段层出不穷,js加密较多,只能具体问题具体分析

9.谈一谈你对Selenium PhantomJS了解?

Selenium是一个Web的自动化测试工具,可以根据我们的指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏,或者判断网站上某些动作是否发生。Selenium 自己不带浏览器,不支持浏览器的功能,它需要与第三方浏览器结合在一起才能使用。但是我们有时候需要让它内嵌在代码中运行,所以我们可以用一个叫 PhantomJS 的工具代替真实的浏览器。Selenium 库里有个叫 WebDriver 的 API。WebDriver 有点儿像可以加载网站的浏览器,但是它也可以像 BeautifulSoup 或者其他 Selector 对象一样用来查找页面元素,与页面上的元素进行交互 (发送文本、点击等),以及执行其他动作来运行网络爬虫。

PhantomJS 是一个基于Webkit的“无界面”(headless)浏览器,它会把网站加载到内存并执行页面上的 JavaScript,因为不会展示图形界面,所以运行起来比完整的浏览器要高效。

如果我们把 Selenium 和 PhantomJS 结合在一起,就可以运行一个非常强大的网络爬虫了,这个爬虫可以处理 JavaScrip、Cookie、headers,以及任何我们真实用户需要做的事情。

10.“极验”滑动验证码如何破解?

1.selenium控制鼠标实现,速度太机械化,成功率比较低

2.计算缺口的偏移量(推荐博客:http://blog.csdn.net/paololiu/article/details/52514504?%3E)

3.“极验”滑动验证码需要具体网站具体分析,一般牵扯算法乃至深度学习相关知识

11.分布式爬虫主要解决什么问题?

分布式只是提高爬虫功能和效率的一个环节而已,它从来不是爬虫的本质东西。

爬虫的本质是网络请求和数据处理,如何稳定地访问网页拿到数据,如何精准地提取出高质量的数据才是核心问题。

分布式爬虫只有当爬虫任务量很大的时候才会凸显优势,一般情况下也确实不必动用这个大杀器,所以要明确你的目标是什么

1)ip

2)带宽

3)cpu

4)io

5)大量任务

12.什么是分布式存储?

传统定义:分布式存储系统是大量PC服务器通过Internet互联,对外提供一个整体的服务。

分布式存储系统具有以下的几个特性:

可扩展:分布式存储系统可以扩展到几百台甚至几千台这样的一个集群规模,系统的整体性能线性增长。

低成本:分布式存储系统的自动容错、自动负载均衡的特性,允许分布式存储系统可以构建在低成本的服务器上。另外,线性的扩展能力也使得增加、减少服务器的成本低,实现分布式存储系统的自动运维。

高性能:无论是针对单台服务器,还是针对整个分布式的存储集群,都要求分布式存储系统具备高性能。

易用:分布式存储系统需要对外提供方便易用的接口,另外,也需要具备完善的监控、运维工具,并且可以方便的与其他的系统进行集成。

分布式存储系统的挑战主要在于数据和状态信息的持久化,要求在自动迁移、自动容错和并发读写的过程中,保证数据的一致性。分布式存储所涉及到的技术主要来自于两个领域:分布式系统以及数据库,如下所示:

数据分布:如何将数据均匀的分布到整个分布式存储集群中的各台服务器?如何从分布式存储集群中读取数据?

一致性:如何将数据的多个副本复制到多台服务器,即使在异常情况下,也能保证不同副本之间的数据一致性。

容错:如何可以快速检测到服务器故障,并自动的将在故障服务器上的数据进行迁移

负载均衡:新增的服务器如何在集群中保障负载均衡?数据迁移过程中如何保障不影响现有的服务。

事务与并发控制:如何实现分布式事务。

易用性:如何设计对外接口,使得设计的系统易于使用

压缩/加压缩:如何根据数据的特点设计合理的压缩/解压缩算法?如何平衡压缩/解压缩算法带来的空间和CPU计算资源?

13.你所知道的分布式爬虫方案有那些?

三种分布式爬虫策略:

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比作工头。策略一就是工人遇到新任务都上报给工头,需要干活的时候就去工头那里领任务;策略二就是工头去找新任务,工人只管从工头那里领任务干活;策略三就是工人遇到新任务时询问工头此任务是否有人做了,没有的话工人就将此任务加到自己的“行程表”。

14.假如每天爬取量在5、6万条数据,一般开几个线程,每个线程ip需要加锁限定吗?

1.5、6万条数据相对来说数据量比较小,线程数量不做强制要求(做除法得一个合理值即可)

2.多线程使用代理,应保证不在同时一刻使用一个代理IP

3. 一般请求并发量主要考虑网站的反爬程度来定。

15.怎么监控爬虫的状态

1. 使用 python 的 STMP 包将爬虫的状态信心发送到指定的邮箱

2. Scrapyd、pyspider

3. 引入日志     集成日志处理平台来进行监控,如 elk

16.怎么判断网站是否更新?

静态页面可以考虑使用 http 的 head 方法查看网站的最后更新时间

如果前者行不通,则需要对数据进行标识,如利用加密算法生成指纹,然后定期发起请求获取数据,比对指纹是否一致,如果一致,说明网站没有更新;反之说明更新。

使用MD5数字签名,每次下载网页时,把服务器返回的数据流ResponseStream先放在内存缓冲区,然后对ResponseStream生成MD5数字签名S1,下次下载同样生成签名S2,比较S2和S1,如果相同,则页面没有跟新,否则网页就有更新。

17.增量爬取?

增量爬取即保存上一次状态,本次抓取时与上次比对,如果不在上次的状态中,便视为增量,保存下来。对于scrapy来说,上一次的状态是抓取的特征数据和上次爬取的 request队列(url列表),request队列可以通过request队列可以通过scrapy.core.scheduler的pending_requests成员得到,在爬虫启动时导入上次爬取的特征数据,并且用上次request队列的数据作为start url进行爬取,不在上一次状态中的数据便保存。

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

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

 一般爬虫使用的数据库,是根据项目来定的。如需求方指定了使用什么数据库、如果没指定,那么决定权就在爬虫程序员手里,如果自选的话,mysql 和 mongodb 用的都是比较多的。但不同的数据库品种有各自的优缺点,不同的场景任何一种数据库都可以用来存储,但是某种可能会更好。比如如果抓取的数据之间的耦合性很高,关系比较复杂的话,那么 mysql 可能会是更好的选择。如果抓取的数据是分版块的,并且它们之间没有相似性或关联性不强,那么可能 mongodb 会更好。另外主流的几种永久存储数据库,都是具备处理高并发、具备存储大量数据的能力的,只是由于各自的实现机制不一样,因此优化方案也是不尽相同。总结就是:数据库的选择尽量从项目的数据存在的特性来考虑,还有一个问题就是开发人员最擅长那种数据库。

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

原因:

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

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

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

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

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

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

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

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

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

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

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

2)Mongodb 与 redis 相比较

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

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

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

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

Python 自带:urllib、urllib2

第三方:requests,aiohttp

框架: Scrapy、pyspider

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

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

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

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

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

aiohttp 是一个基于 python3 的 asyncio 携程机制实现的一个 http 库,相比 requests,aiohttp 自身就具备了异步功能。但只能在 python3 环境使用。

Scrapy 优点:

  • scrapy 是异步的;
  • 采取可读性更强的 xpath 代替正则;
  • 强大的统计和 log 系统;
  • 同时在不同的 url 上爬行;
  • 支持 shell 方式,方便独立调试;
  • 写 middleware,方便写一些统一的过滤器;
  • 通过管道的方式存入数据库;

Scrapy 缺点:

  • 基于 python 的爬虫框架,扩展性比较差;
  • 基于 twisted 框架,运行中的 exception 是不会干掉 reactor,并且异步框架出错后是不会停掉其他任务的,数据出错后难以察觉。
  • Pyspider 是一个重量级的爬虫框架,为什么说重量级?我们知道 scrapy 没有数据库集成、没有分布式、断点续爬的支持、没有 UI 控制界面等等、如果基于 scrapy 想要实现这些功能,都需要自行开发,但 pyspider 都已经集成了。但也正因如此 pyspider 另一个问题就是,扩展性太差,学习难度较大。

20.写爬虫是用多进程好?还是多线程好? 为什么?

一般情况下,在选择是使用多进程还是多线程时,主要考虑的业务到底是 IO 密集型(多线程)还是计算密集型(多进程)。在爬虫中,请求的并发业务属于是网络 的 IO 类型业务,因此网络并发适宜使用多线程;但特殊需求下,比如使用 phantomjs 或者 chrome-headless 来抓取的爬虫,应当是多进程的,因为每一个 phan/chro 实例就是一个进程了,并发只能是多进程。此外爬虫中还是数据处理业务,如果数据处理业务是一个比较耗时的计算型操作,那么对数据处理部分应当设为多进程,但更多可能会考虑将该部分数据处理操作和爬虫程序解耦,也就是先把数据抓取下来,事后单独运行另外的程序解析数据。

21.常见的反爬虫和应对方法?

反爬虫简单的说指的是:网站根据某些因素断定该请求是一个爬虫程序发出的请求,然后对该请求采取了一定的制裁措施。

因此反爬虫应该从两方面来探讨:

1. 网站如何断定该请求是一个爬虫:请求头、请求频率、IP 地址、cookie 等(持续更新请求头、cookie、用户 cookie 池、代理 IP 池、设置一定的延时)

2. 网站如何制裁这个它认为是爬虫的请求(假数据、空数据、不返回响应、验证码、4xx 状态码等)

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

基于用户行为反爬虫:

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

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

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

动态页面的反爬虫:

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

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

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

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

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

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

23.验证码的解决?

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

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

手动打码(有的验证码确实无解)

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

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

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

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

25.字符集和字符编码

字符是各种文字和符号的总称,包括各个国家文字、标点符号、图形符号、数字等。

字符集是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,常见字符集有: ASCII 字符集、ISO 8859 字符集、GB2312 字符集、BIG5 字符集、GB18030 字符集、Unicode 字符集等。

字符编码就是以二进制的数字来对应字符集的字符。

常见的编码字符集(简称字符集)如下所示:

Unicode:也叫统一字符集,它包含了几乎世界上所有的已经发现且需要使用的字符 (如中文、日文、英文、德文等)。

ASCII:ASCII 既是编码字符集,又是字符编码。早期的计算机系统只能处理英文,所以 ASCII 也 就成为了计算机的缺省字符集,包含了英文所需要的所有字符。

GB2312:中文字符集,包含 ASCII 字符集。ASCII 部分用单字节表示,剩余部分用双字节表 示。

GBK:GB2312 的扩展,但完整包含了 GB2312 的所有内容。

GB18030:GBK 字符集的超集,常叫大汉字字符集,也叫 CJK(Chinese,Japanese, Korea)字符集,包含了中、日、韩三国语。

注意:Unicode 字符集有多种编码方式,如 UTF-8、UTF-16 等;ASCII 只有一种;大多 数 MBCS(包括 GB2312)也只有一种。

26.编写过哪些爬虫中间件?

user-agent、代理池等。

27.cookie 过期的处理问题?

因为 cookie 存在过期的现象,一个很好的处理方法就是做一个异常类,如果有异常的话 cookie 抛 出异常类在执行程序。

28.动态加载又对及时性要求很高怎么处理?

分析出数据接口 API(利用 chrome 或者抓包工具),然后利用 requests 等 http 库实现爬虫,如 果有需要执行 js 代码,可借助 js2py、pyexecjs 等工具实现。

Selenium+Phantomjs

尽量不使用 sleep 而使用 WebDriverWait

29.HTTPS 有什么优点和缺点

优点:

1、使用 HTTPS 协议可认证用户和服务器,确保数据发送到正确的客户机和服务器;

2、HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,要比 http 协议安全,可防止数据在传输过程中不被窃取、改变,确保数据的完整性。

3、HTTPS 是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻击的成本

缺点:

1.HTTPS 协议的加密范围也比较有限,在黑客攻击、拒绝服务攻击、服务器劫持等方面几乎起不到什么作用

2.HTTPS 协议还会影响缓存,增加数据开销和功耗,甚至已有安全措施也会受到影响也会因此 而受到影响。

3.SSL 证书需要钱。功能越强大的证书费用越高。个人网站、小网站没有必要一般不会用。

4.HTTPS 连接服务器端资源占用高很多,握手阶段比较费时对网站的相应速度有负面影响。

5.HTTPS 连接缓存不如 HTTP 高效。

30.HTTPS 是如何实现安全传输数据的。

HTTPS 其实就是在 HTTP 跟 TCP 中间加多了一层加密层 TLS/SSL。SSL 是个加密套件,负责对 HTTP 的数据进行加密。TLS 是 SSL 的升级版。现在提到 HTTPS,加密套件基本指的是 TLS。原先是应用层将数据直接给到 TCP 进行传输,现在改成应用层将数据给到 TLS/SSL,将数据加密后,再给到 TCP 进行 传输。

31.谈一谈你对 Selenium 和 PhantomJS 了解

Selenium 是一个 Web 的自动化测试工具,可以根据我们的指令,让浏览器自动加载页面,获取需 要的数据,甚至页面截屏,或者判断网站上某些动作是否发生。Selenium 自己不带浏览器,不支持浏览器的功能,它需要与第三方浏览器结合在一起才能使用。但是我们有时候需要让它内嵌在代码中运行, 所以我们可以用一个叫 PhantomJS 的工具代替真实的浏览器。Selenium 库里有个叫 WebDriver 的 API。WebDriver 有点儿像可以加载网站的浏览器,但是它也可以像 BeautifulSoup 或者其他Selector 对象一样用来查找页面元素,与页面上的元素进行交互 (发送文本、点击等),以及执行其他 动作来运行网络爬虫。

PhantomJS 是一个基于 Webkit 的“无界面”(headless)浏览器,它会把网站加载到内存并执行页面上的 JavaScript,因为不会展示图形界面,所以运行起来比完整的浏览器要高效。相比传统的 Chrome 或 Firefox 浏览器等,资源消耗会更少。 如果我们把 Selenium 和 PhantomJS 结合在一起,就可以运行一个非常强大的网络爬虫了,这个爬虫可以处理 JavaScript、Cookie、headers,以及任何我们真实用户需要做的事情。 主程序退出后,selenium 不保证 phantomJS 也成功退出,最好手动关闭 phantomJS 进程。(有可能会导致多个 phantomJS 进程运行,占用内存)。 WebDriverWait 虽然可能会减少延时,但是目前存在 bug(各种报错),这种情况可以采用 sleep。 phantomJS 爬数据比较慢,可以选择多线程。如果运行的时候发现有的可以运行,有的不能,可以尝试将 phantomJS 改成 Chrome。

32.代理 IP 里的“透明”“匿名”“高匿”分别是指?

透明代理的意思是客户端根本不需要知道有代理服务器的存在,但是它传送的仍然是真实的 IP。你要想隐藏的话,不要用这个。

普通匿名代理能隐藏客户机的真实 IP,但会改变我们的请求信息,服务器端有可能会认为我们使用了代理。不过使用此种代理时,虽然被访问的网站不能知道你的 ip 地址,但仍然可以知道你在使用代理,当然某些能够侦测 ip 的网页仍然可以查到你的 ip。

高匿名代理不改变客户机的请求,这样在服务器看来就像有个真正的客户浏览器在访问它,这时客 户的真实 IP 是隐藏的,服务器端不会认为我们使用了代理。 设置代理有以下两个好处:

1,让服务器以为不是同一个客户端在请求

2,防止我们的真实地址被泄露,防止被追究

33.requests 返回的 content 和 text 的区别?

a)response.text 返回的是 Unicode 型数据;

a)response.content 返回的是 bytes 类型,也就是二进制数据;

b)获取文本使用,response.text;

b)获取图片,文件,使用 response.content;

c)response.text

  • 类型:str
  • 解码类型: 根据 HTTP 头部对响应的编码作出有根据的推测,推测的文本编码
  • 如何修改编码方式:response.encoding=”gbk”

c)response.content

  • 类型:bytes
  • 解码类型: 没有指定
  • 如何修改编码方式:response.content.decode(“utf8”)

34.robots 协议

Robots 协议:网站通过 Robots 协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取。

35.为什么 requests 请求需要带上 header?

让我们的爬虫请求看起来就是一个正常的浏览器请求

原因是:模拟浏览器,欺骗服务器,获取和浏览器一致的内容

header 的形式:字典

headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}

用法: requests.get(url,headers=headers)

36.dumps,loads 与 dump,load 的区别?

json.dumps()将 pyhton 的 dict 数据类型编码为 json 字符串;

json.loads()将 json 字符串解码为 dict 的数据类型;

json.dump(x,y) x 是 json 对象, y 是文件对象,最终是将 json 对象写入到文件中;

json.load(y) 从文件对象 y 中读取 json 对象。

37.requests 使用小技巧

1、reqeusts.util.dict_from_cookiejar 把 cookie 对象转化为字典

1.1. requests.get(url,cookies={})

2、设置请求不用 SSL 证书验证  response = requests.get("https://www.12306.cn/mormhweb/ ", verify=False)

3、设置超时  response = requests.get(url,timeout=10)

4、配合状态码判断是否请求成功

assert response.status_code == 200

38.平常怎么使用代理的 ?

1. 自己维护代理池

2. 付费购买(目前市场上有很多 ip 代理商,可自行百度了解,建议看看他们的接口文档(API&SDK))

39.IP 存放在哪里?怎么维护 IP?对于封了多个 ip 的,怎么判定 IP 没被封?

存放在数据库(redis、mysql 等)。

维护多个代理网站:

一般代理的存活时间往往在十几分钟左右,定时任务,加上代理 IP 去访问网页,验证其是否可用, 如果返回状态为 200,表示这个代理是可以使用的。

40.怎么获取加密的数据?

1. Web 端加密可尝试移动端(app)

2. 解析加密,看能否破解

3. 反爬手段层出不穷,js 加密较多,只能具体问题具体分析

分析前端 js 文件,找到加密解密数据的 js 代码,用 Python 代码实现或者利用 js2py 或 pyexecjs 等执行 js 代码

41.描述下 scrapy 框架运行的机制?

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

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

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

3. 根据 scrapy 的流程图,描述出五大组件、两个中间件,以及完成一个请求的流程。

42.谈谈你对 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 请求程序停止结束。

43.怎么样让 scrapy 框架发送一个 post 请求(具体写出来)

使用 FormRequest

class mySpider(scrapy.Spider):
    # start_urls = ["http://www.taobao.com/"]
    def start_requests(self):
        url = 'http://http://www.taobao.com//login'
        # FormRequest 是 Scrapy 发送 POST 请求的方法
        yield scrapy.FormRequest(
            url=url,
            formdata={"email": "xxx", "password": "xxxxx"},
            callback=self.parse_page
        )
# do something

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

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

45.爬取下来的数据如何去重,说一下具体的算法依据

1.通过 MD5 生成电子指纹来判断页面是否改变

2.nutch 去重。nutch 中 digest 是对采集的每一个网页内容的 32 位哈希值,如果两个网页内容完 全一样,它们的 digest 值肯定会一样。

数据量不大时,可以直接放在内存里面进行去重,python 可以使用 set()进行去重。当去重数据 需要持久化时可以使用 redis 的 set 数据结构。

当数据量再大一点时,可以用不同的加密算法先将长字符串压缩成 16/32/40 个字符,再使用 上面两种方法去重。

当数据量达到亿(甚至十亿、百亿)数量级时,内存有限,必须用“位”来去重,才能够满足需求。Bloomfilter 就是将去重对象映射到几个内存“位”,通过几个位的 0/1 值来判断一个对象是否已经存在。

然而 Bloomfilter 运行在一台机器的内存上,不方便持久化(机器 down 掉就什么都没啦),也不 方便分布式爬虫的统一去重。如果可以在 Redis 上申请内存进行 Bloomfilter,以上两个问题就都能解决了。

simhash 最牛逼的一点就是将一个文档,最后转换成一个 64 位的字节,暂且称之为特征字,然后判断重复只需要判断他们的特征字的距离是不是

可见 scrapy_redis 是利用 set 数据结构来去重的,去重的对象是 request 的 fingerprint(其实 就是用 hashlib.sha1()对 request 对象的某些字段信息进行压缩)。其实 fp 就是 request 对象加密 压缩后的一个字符串(40 个字符,0~f)。

46.Scrapy 的优缺点?

优点:

1)scrapy 是异步的

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

3)强大的统计和 log 系统

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

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

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

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

缺点:

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

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

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

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

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

48.分布式爬虫主要解决什么问题?

1.ip

2.带宽

3.cpu

4.io

49.什么是分布式存储?

传统定义:分布式存储系统是大量 PC 服务器通过 Internet 互联,对外提供一个整体的服务。

分布式存储系统具有以下的几个特性:

可扩展 :分布式存储系统可以扩展到几百台甚至几千台这样的一个集群规模,系统的整体性能线性增长。

低成本 :分布式存储系统的自动容错、自动负载均衡的特性,允许分布式存储系统可以构建在低成本的服务器上。另外,线性的扩展能力也使得增加、减少服务器的成本低, 实现分布式存储系统的自动运维。

高性能 :无论是针对单台服务器,还是针对整个分布式的存储集群,都要求分布式存储系统具备高性能。

易用 :分布式存储系统需要对外提供方便易用的接口,另外,也需要具备完善的监控、运维工具,并且可以方便的与其他的系统进行集成。

布式存储系统的挑战主要在于数据和状态信息的持久化,要求在自动迁移、自动容错和并发读写的过程中,保证数据的一致性。

容错:可以快速检测到服务器故障,并自动的将在故障服务器上的数据进行迁移。

负载均衡:新增的服务器在集群中保障负载均衡?数据迁移过程中保障不影响现有的服务。

事务与并发控制:实现分布式事务。

易用性:设计对外接口,使得设计的系统易于使用。

50.你所知道的分布式爬虫方案有哪些?

三种分布式爬虫策略:

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 比作工头。策略一就是工人遇到新任务都上报给工头,需要干活的时候就去工头那里领任务;策略二就是工头去找新任务,工人只管从工头那里领任务干活;策略三就是工人遇到新任务时询问工头此任务是否有人做了,没有的话工人就将此任务加到自己的“行程表”。

51.除了 scrapy-redis,有做过其他的分布式爬虫吗?

Celery、gearman 等,参考其他分布式爬虫策略。

52.在爬取的时候遇到某些内容字段缺失怎么判断及处理?

判读字段缺失,做异常处理即可。

53.什么是 HTTP 代理?作用是什么?

代理服务器英文全称是 Proxy Server,其功能就是代理网络用户去取得网络信息。形象的说:它是 网络信息的中转站。

代理服务器可以实现各种时髦且有用的功能。它们可以改善安全性,提高性能,节省费用。

54. 什么是反向代理?作用是什么?

代理可以假扮 Web 服务器。这些被称为替换物(surrogate)或反向代理(reverse proxy)的代理接收 发送给 Web 服务器的真实请求,但与 Web 服务器不同的是,它们可以发起与其他服务器的通信,以便按需定位所请求的内容。

可以用这些反向代理来提高访问慢速 Web 服务器上公共内容的性能。在这种配置中,通常将这些 反向代理称为服务器加速器(server accelerator)。还可以将替换物与内容路由功能配合使用,以创建按需复制内容的分布式网络。

55.xpath 使用的什么库?

lxml

你可能感兴趣的:(其它,python,爬虫)