Scrapy is coming!!
在写了七篇爬虫基础文章之后,终于写到心心念念的Scrapy了。Scrapy开启了爬虫2.0的时代,让爬虫以一种崭新的形式呈现在开发者面前。
在18年实习的时候开始接触Scrapy,花了一个月的时间,理论结合实践学习了Scrapy。本篇文章不写代码操作,只讲前因后果及理论,愿你懂得Scrapy。
无论使用Java的Jsoup也好,python的requests也罢,开发爬虫都会面临下面几个问题:
爬虫程序一般只运行在一台主机上,如果是一模一样的爬虫程序部署在不同的主机上,那都是独立爬虫程序。如果想要弄一个分布式的爬虫,通常的思路是将爬虫程序分为url采集和数据采集两个部分。
现将url爬取下来放入到数据库中,然后通过where条件限制,或者直接使用redis的list结构,让不同主机上的爬虫程序读取到不同的url,然后进行数据爬取。
爬取数据的时候会经常遇到重复的url,如果重复爬取是不是浪费时间。通过url去重的思路就是:将爬取的url放入到集合中,每次爬取都去判断url是否存在于集合中。那么,如果程序中途停止了,这个内存中集合也将不复存在,再次启动程序,将无法判断哪些是已经爬取过的。
那么就用数据库,将已经爬取过的url插入到数据库中,这样就算重启程序,爬取过的url也不会丢失了。可是如果我就是想重新开始爬取,是不是还得手动清空数据库中的url表。每次查询数据库耗费的时间,这都是需要考虑的。
假如有1000个页面需要爬取,爬到第999个页面,进度条马上满格的时候,程序咯噔一下挂了,就差一个,但是还是没爬完啊,咋整?我选择重新启动程序,那么你说我怎么样才能直接从第999个开始爬取呢?
这里先讲讲我写的第一个爬虫:爬取10+个地市的poi信息。
实习,第一次开发爬虫,也不知道有高德poi接口啥的,于是就找了个网站来爬取poi信息。当时那个网站估计还在起步阶段,服务器带宽应该不高,访问速度是真的慢,而且动不动维护停站,所以我的程序也得跟着停止。如果每次启动都重新爬取,估计几年也爬不完,于是我想了个办法。
我先将所有地市下所有区县数据的条数(网站上有)先手动录入到数据库表中,每次重新启动爬虫程序的时候,先统计结果数据表中各个区县已经爬取的条数,与总条数进行对比。如果小于的话,说明还没有爬取完,然后通过某区县已爬取条数 / 网站每页展示条数计算出我已经爬取到此区县的页数,再通过余数定位到我爬到了此页面的第几个。通过这种方法,最后无丢失爬取了163w条数据。
换种思路,将爬取的url放到表中,重启程序开始爬取url的时候,先去判断url是否存在于数据表中,如果存在就不进行爬取,这样也能实现断点续爬。也是沿用了原始的url的去重的思路。
在第六篇基金篇写了一个jsonp的动态加载,算是比较简单的一种,只要找到请求接口获取数据进行处理即可。第七篇写了电视猫的eval()的js加密,这算是很复杂的一种动态加载。请求接口的参数是加密的,需要耗费大量时间来分析密密麻麻的js,来计算出这个186位的参数。
so,有没有一种方式让我既能脱离阅读分析js,还能绕过动态加载?
sure!!首先关于动态加载,可以理解为浏览器内核通过执行js在前端渲染数据。那么我们在程序中搞个浏览器内核,我们直接获取js渲染后的页面数据不就可以了么?
通常使用selenium + chrome、phantomjs、pyvirtualdisplay来处理动态加载,但是或多或少都会有性能问题。
上面说了那么多,根据一贯的套路,大家也应该知道接下来我要说什么了。
Scrapy带给我的感受就是:模块分明、结构封装、功能强大。
Scrapy是一个分布式爬虫框架,我把它比作成爬虫界的Spring。reqeusts就像是servlet一样,各种功能逻辑都需要自己去实现,而Spring做了集成,底层对用户透明。
就像我们知道,Spring是在application配置文件中初始化bean,在mapper中定义数据库操作一样,而使用者无需关心Spring是如何读取这些配置文件进行各种操作的。同样,Scrapy也提供了这样的功能配置。
所以说,Scrapy是一个爬虫框架,requests是一个爬虫模块,两者是有区别的。
我的政治老师曾经说过:没有无缘无故的爱,也没有无缘无故的恨。 根据我个人的使用体验,说一下我为什么那么推荐Scrapy。
Scrapy又是框架、功能还那么强大,是不是很难学会啊。
这种担忧大可不必,Scrapy的安装和普通python模块的安装一样,只要了解其中四个模块的作用,入门极其简单。而Scrapy爬虫程序的开发逻辑,代码更少、层次更分明,比requests要简单很多。
Scrapy作为一个框架,有人觉得scrapy太重量级了,不如requests用起来轻便。在这里只能说,应用场景和侧重点不一样。
Scrapy的开发更像是一个工程项目开发。通常用来做多数据源的爬虫数据整合,例如整合视频、小说、音乐、漫画等信息数据到一个数据表中。开发者只需事先约定好的数据字段,即可进行多人协作开发,因为scrapy通过yield关键字即可将数据放到数据库,无需再去显式地调用任何方法。
而requests更适合无需进行统一管理、无需分布式部署的单个爬虫程序的开发。
其实,第一篇应该写Scrapy的架构与安装,但是我觉得用一个技术前,了解这个技术的功能和应用场景还是很有必要的,所以写了这一篇理论知识。
这篇文章写了两遍,第一遍写完了之后,不知道什么原因,在编辑器里被覆盖了,所以只能再重新写一遍。辛亏中间部分截图发给过朋友,还能少写一部分。我也终于明白了曾经网上流传的一种心情:作业写完被狗撕了,不想再写一遍。
希望本篇文章能让你对爬虫的理论知识有更深层次的了解,期待下一次相遇。
95后小程序员,写的都是日常工作中的亲身实践,置身于初学者的角度从0写到1,详细且认真。
文章会在公众号 [入门到放弃之路] 首发,期待你的关注。