python爬虫项目设置一个中断重连的程序的实现
做爬虫项目时,我们需要考虑一个爬虫在爬取时会遇到各种情况(网站验证,ip封禁),导致爬虫程序中断,这时我们已经爬取过一些数据,再次爬取时这些数据就可以忽略,所以我们需要在爬虫项目中设置一个中断重连的功能,使其在重新运行时从之前断掉的位置重新爬取数据。
实现该功能有很多种做法,我自己就有好几种思路,但是真要自己写出来就要费很大的功夫,下面我就把自己好不容易拼凑出来的代码展示出来吧。
首先是来介绍代码的思路:
将要爬取的网站连接存在一个数组new_urls中,爬取一个网址就将它移入另一个数组old_urls中,爬取网站时,就看它是在哪一个数组中,然后再决定要不要爬取。
下面展示代码(从别处抄的):
classUrlManager(object): def__init__(self):#定义两个数组 self.new_urls=set() self.old_urls=set() defadd_new_url(self,url):#将一个url加入到new_urls数组中 ifurlisNone: return ifurlnotinself.new_urlsandurlnotinself.old_urls: self.new_urls.add(url) defadd_new_urls(self,urls):#将多个url加入到new_urls数组中 ifurlsisNoneorlen(urls)==0: return forurlinurls: self.add_new_url(url) defhas_new_url(self):#判断url是否为空 returnlen(self.new_urls)!=0 defget_new_url(self): #list.pop()默认移除列表中最后一个元素对象 new_url=self.new_urls.pop() self.old_urls.add(new_url) returnnew_url
这个类实现了中断重连的基本功能,但是当我们要爬取的网址非常的,那这就对我们电脑的内存要求非常大,所以我们要将数组保存到文档中,增加一个从文档中提取网址的过程。
下面看代码:
classUrlManager(object): def__init__(self):#建立两个数组的文件 withopen('new_urls.txt','r+')asnew_urls: self.new_urls=new_urls.read() withopen('old_urls.txt','r+')asold_urls: self.old_urls=old_urls.read() defadd_new_url(self,url):#添加url到new_ulrs文件中 ifurlisNone: return ifurlnotinself.new_urlsandurlnotinself.old_urls: withopen('new_urls.txt','a')asnew_urls: new_urls.write(url) else: print('urlhaddone') defadd_new_urls(self,urls):#添加多个url到new_ulrs文件中 #ifurlsisNoneor(len(url)==0forurlinurls): ifurlsisNone: print('urlisnone') return forurlinurls: ifurlsisNone: print('urlisnone') return else: self.add_new_url(url) defhas_new_url(self): returnlen(self.new_urls)!=0 defget_new_url(self): new_url=get_last_line('new_urls.txt')#读取new_urls文件中最后一个url del_last_url('new_urls.txt',new_url)#删除new_urls文件中最后一个url add_old_urls('old_urls.txt',new_url)#将读取出来的url添加入old_urls数组中 returnnew_url
其中的get_last_line()函数有些复杂,这也是我卡时间最长的一块,
importos defget_last_line(inputfile): filesize=os.path.getsize(inputfile) blocksize=1024 dat_file=open(inputfile,'rb') last_line=b"" lines=[] iffilesize>blocksize: maxseekpoint=(filesize//blocksize)#这里的除法取的是floor maxseekpoint-=1 dat_file.seek(maxseekpoint*blocksize) lines=dat_file.readlines() while((len(lines)<2)|((len(lines)>=2)&(lines[1]==b'\r\n'))):#因为在Windows下,所以是b'\r\n' #如果列表长度小于2,或者虽然长度大于等于2,但第二个元素却还是空行 #如果跳出循环,那么lines长度大于等于2,且第二个元素肯定是完整的行 maxseekpoint-=1 dat_file.seek(maxseekpoint*blocksize) lines=dat_file.readlines() eliffilesize:#文件大小不为空 dat_file.seek(0,0) lines=dat_file.readlines() iflines:#列表不为空 foriinrange(len(lines)-1,-1,-1): last_line=lines[i].strip() if(last_line!=b''): break#已经找到最后一个不是空行的 dat_file.close() returnlast_line defdel_last_url(fname,part): withopen(fname,'rb+')asf: a=f.read() a=a.replace(part,b'') withopen(fname,'wb+')asf: f.write(a) defadd_old_urls(fname,new_url): line=new_url+b'\r' withopen(fname,'ab')asf: f.write(line)
好了,爬虫的中断重连的功能就实现了,下面要做的就是将该功能接入爬虫项目中,比较简单。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。