当采集一个大型网站时,一般栏目非常多,而python爬虫一天又不可能采集完,就算能采集完当前整个网站的数据,如果要采集明天的或未来更新的数据,就不可能一天完成了,这个时间就要记录采集点,例如,采集到哪个栏目了,采集到哪个子栏目,采集到哪一个页面了等,这些都是最基本的重要信息。
若没有记录这些信息,第二天采集的时候难道要重新从头采集?这就像下载软件似的,当我们下载一个几G的视频,如果不小心关闭了下载软件,而下载的软件会“记住”下载了多少,等再次打开软件软件会继续下载,而不是从零开始从头下载。
这就需要我们写的爬虫必须具备断点续爬的功能,当然我们可以使用分布式scrapy-redis来解决这个问题,但是,很多时候我们用不到分布式爬虫,例如,使用selenium来写爬虫,这时就要自己手动去设计断点续爬,根据爬虫之家设计并采集了约1200多万条数据的经验,现在把本人设计的方法分享给大家。
若要让爬虫下次爬取数据时,从上次断开的地方开始爬虫,就要根据我们项目的需求来设计,不同的爬虫项目需要设计的点不一样。
但是记住下面几点是我们必须的:
1)栏目
采集往往通过一个栏目一个栏目的采集,这样做主要是因为人家目标网站都已经分好栏目了,我们也跟着目标网站来创建栏目,然后把栏目数据采集到本地相应栏目即可,所以,记住栏目是非常有必要的。
2)页数
采集到哪一页了也比较重要,如果一个栏目有几千页,哪怕是几百页如果不对页数进行记录的话,每次采集都要从头采集,这样导致的结果就是浪费不少时间,采集的越多越广爬虫断开的可能性越高,所以有必要记住页数,在记录页数时也不一定非要精确到采集到了那一条数据,只需要记录将要采集的网页即可,最好故意有一点误差少记几页,例如,现在采集到了20页,我们记录时让程序知道我们采集到18,19页都可以,这样做的目的是如果网站更新,也可以有一定余地。
3) 采集次数
每个栏目全部采集完最好从头再采集一次,所以有必要设计一个程序记住这个栏目采集多少次了,毕竟第一遍采集时有可能出现各种各样的问题,例如,网络不稳定,网页打开出问题等,这样采集完一个栏目再采集一遍可以保证采集的数据不会丢失,即使第一次丢失了第二次采集时可以补上。
4)跳过采集过的数据
当第二次采集一个栏目时,如何跳过采集过的数据,最好的方法是在采集前先把当前栏目数据查询出来,然后放到文件中,当采集数据时先从文件中查询出数据库中已经存在的数据,把要采集的数据跟查询出来的数据对比,看看是否已经采集过,若采集过了则跳过。
5) 其它
要记住哪些重要信息为断点续爬服务,还需要根据自己爬虫项目来决定,不同的项目采集的目标网站不一样,具体要记住的数据也有区别,这里不一一列举了,只用上面几点来说明。
设计断点续爬
断点续爬方法:每次重启爬虫时,查询相应的文件,文件可以是txt,也可以是py格式的文件,根据这里面记住的信息定位到相应位置,然后接着采集数据。
爬虫之家是把要记住的信息都保存到了.txt文件里面,当下次再次爬取数据时,先查询这些文件看是否有值,若值为空或为0,则说明要从头开始爬数据。
具体方法:若type.txt文件中不空,而是保存了某个栏目则去找这个栏目,然后再看这个栏目对应的网页文件page.txt看里面是否为0,若不是零则在刚找到的这个栏目下面,一步步查找栏目对应的页数,一直定位到页数为止,这样就实现了断点续爬,当然,在查找栏目时可以先查询爬虫爬行次数文件times.txt看是否为1,若为1则说明此栏目已经爬完了,就去爬其它的栏目,若此文件内容为0则说明还没有采集,然后再看栏目文件和页数文件。
下面是我设计的代码,是从项目中直接抠出来的,无法直接运行,只做说明使用:
#定义文件:
self.title_file_name = './record/'+type_name+'/'+type_name+'_title.txt' self.type_file_name = './record/'+type_name+'/'+type_name+'_type.txt' self.page_file_name = './record/'+type_name+'/'+type_name+'_page.txt' self.year_file_name = './record/'+type_name+'/'+type_name+'_year.txt'
# 断点续爬判断
self.keep_type_name = db.getFromFile(self.type_file_name,False) self.keep_on = False if len(self.keep_type_name) >= 4: self.keep_on = True
通过keep_on是否为True来判断是否需要断续爬,这样后面第一次启动爬虫后在遍历栏目时,需要判断一下keep_on值是否为True,若是True则查询type.txt表中的栏目是哪一个,然后去找这个栏目。
遍历栏目时判断是从头开始,还是断点续爬
keep_type_name = db.getFromFile(self.type_file_name,False) if self.keep_on: #这里是代码 if keep_type == which_type: which_type = keep_type else: continue if which_type_len == type_len: self.keep_on = False
上面只是处理栏目伪代码,等到确定要爬哪个栏目后,再确定要爬取哪个页面,处理方法跟上面几乎完全一样,先从保存页数的文件page.txt里面查询出数据,看值是否为0,若不为0则在当前栏目下面点击页数,一直找到文件中保存的页数值,这样就相当定位到上次爬虫爬的位置了。
通过上面的方法就实现了断点续爬,当然项目中哪个地方要断点续爬要根据自己的需求而定,实际使用要复杂的多。
如果小项目需要手动去设计断点续爬,而大项目如果使用框架的话,很多爬虫框架都集成了这个功能,只要设置一下即可,而对于中小项目可能就需要我们手动来设计这个功能。
发表评论