python爬虫项目设置一个中断重连的程序的实现


Posted in Python onJuly 26, 2019

做爬虫项目时,我们需要考虑一个爬虫在爬取时会遇到各种情况(网站验证,ip封禁),导致爬虫程序中断,这时我们已经爬取过一些数据,再次爬取时这些数据就可以忽略,所以我们需要在爬虫项目中设置一个中断重连的功能,使其在重新运行时从之前断掉的位置重新爬取数据。

实现该功能有很多种做法,我自己就有好几种思路,但是真要自己写出来就要费很大的功夫,下面我就把自己好不容易拼凑出来的代码展示出来吧。

首先是来介绍代码的思路:

将要爬取的网站连接存在一个数组new_urls中,爬取一个网址就将它移入另一个数组old_urls中,爬取网站时,就看它是在哪一个数组中,然后再决定要不要爬取。

下面展示代码(从别处抄的):

class UrlManager(object):
  def __init__(self):  #定义两个数组
    self.new_urls=set()
    self.old_urls=set()

  def add_new_url(self, url): #将一个url加入到new_urls数组中
    if url is None:
      return
    if url not in self.new_urls and url not in self.old_urls:
      self.new_urls.add(url)

  def add_new_urls(self, urls): #将多个url加入到new_urls数组中
    if urls is None or len(urls)==0:
      return
    for url in urls :
      self.add_new_url(url)

  def has_new_url(self):  #判断url是否为空
    return len(self.new_urls)!=0

  def get_new_url(self):
    #list.pop()默认移除列表中最后一个元素对象
    new_url=self.new_urls.pop()
    self.old_urls.add(new_url)
    return new_url

这个类实现了中断重连的基本功能,但是当我们要爬取的网址非常的,那这就对我们电脑的内存要求非常大,所以我们要将数组保存到文档中,增加一个从文档中提取网址的过程。

下面看代码:

class UrlManager(object):
  def __init__(self):   #建立两个数组的文件
    with open('new_urls.txt','r+') as new_urls:
      self.new_urls = new_urls.read()
    with open('old_urls.txt','r+') as old_urls:
      self.old_urls = old_urls.read()

  def add_new_url(self, url):   #添加url到new_ulrs文件中
    if url is None:
      return
    if url not in self.new_urls and url not in self.old_urls:
      with open('new_urls.txt', 'a') as new_urls:
        new_urls.write(url)
    else:
      print('url had done')

  def add_new_urls(self, urls):  #添加多个url到new_ulrs文件中
    # if urls is None or (len(url) == 0 for url in urls):
    if urls is None:
      print('url is none')
      return
    for url in urls:
      if urls is None:
        print('url is none')
        return
      else:
        self.add_new_url(url)

  def has_new_url(self):
    return len(self.new_urls) != 0

  def get_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数组中
    return new_url

其中的get_last_line()函数有些复杂,这也是我卡时间最长的一块,

import os
def get_last_line(inputfile):
  filesize = os.path.getsize(inputfile)
  blocksize = 1024
  dat_file = open(inputfile, 'rb')

  last_line = b""
  lines = []
  if filesize > 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()
  elif filesize: # 文件大小不为空
    dat_file.seek(0, 0)
    lines = dat_file.readlines()
  if lines: # 列表不为空
    for i in range(len(lines) - 1, -1, -1):
      last_line = lines[i].strip()
      if (last_line != b''):
        break # 已经找到最后一个不是空行的
  dat_file.close()
  return last_line

def del_last_url(fname,part):
  with open(fname,'rb+') as f:
    a = f.read()
  a = a.replace(part,b'')
  with open(fname,'wb+') as f:
    f.write(a)
    
def add_old_urls(fname,new_url):
  line = new_url + b'\r'
  with open(fname,'ab') as f:
    f.write(line)

好了,爬虫的中断重连的功能就实现了,下面要做的就是将该功能接入爬虫项目中,比较简单。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python在windows下实现备份程序实例
Jul 04 Python
用Python制作简单的朴素基数估计器的教程
Apr 01 Python
python正常时间和unix时间戳相互转换的方法
Apr 23 Python
Python3实现Web网页图片下载
Jan 28 Python
python实现按行切分文本文件的方法
Apr 18 Python
python爬虫入门教程--HTML文本的解析库BeautifulSoup(四)
May 25 Python
matplotlib.pyplot画图 图片的二进制流的获取方法
May 24 Python
浅析python 中大括号中括号小括号的区分
Jul 29 Python
Flask 上传自定义头像的实例详解
Jan 09 Python
Python Selenium自动化获取页面信息的方法
Aug 31 Python
python自动化办公操作PPT的实现
Feb 05 Python
Python移位密码、仿射变换解密实例代码
Jun 27 Python
python通过http下载文件的方法详解
Jul 26 #Python
快速解决vue.js 模板和jinja 模板冲突的问题
Jul 26 #Python
Python调用C语言的实现
Jul 26 #Python
Python实现的企业粉丝抽奖功能示例
Jul 26 #Python
对Django外键关系的描述
Jul 26 #Python
python绘图模块matplotlib示例详解
Jul 26 #Python
详解Python中正则匹配TAB及空格的小技巧
Jul 26 #Python
You might like
php实现比较全的数据库操作类
2015/06/18 PHP
PHP将数据导出Excel表中的实例(投机型)
2017/07/31 PHP
PDO::exec讲解
2019/01/28 PHP
JQuery 动态扩展对象之另类视角
2010/05/25 Javascript
jQuery学习笔记[1] jQuery中的DOM操作
2010/12/03 Javascript
JavaScript NaN和Infinity特殊值 [译]
2012/09/20 Javascript
浅谈javascript回调函数
2014/12/07 Javascript
javascript之with的使用(阿里云、淘宝使用代码分析)
2016/10/11 Javascript
JS实现焦点图轮播效果的方法详解
2016/12/19 Javascript
RequireJs的使用详解
2017/02/19 Javascript
nodejs中向HTTP响应传送进程的输出
2017/03/19 NodeJs
微信JS SDK接入的几点注意事项(必看篇)
2017/06/23 Javascript
VUE element-ui 写个复用Table组件的示例代码
2017/11/18 Javascript
jquery点击回车键实现登录效果并默认焦点的方法
2018/03/09 jQuery
JavaScript控制浏览器全屏显示简单示例
2018/07/05 Javascript
Vue开发Html5微信公众号的步骤
2019/04/11 Javascript
webpack 如何同时输出压缩和未压缩的文件的实现步骤
2020/06/05 Javascript
vue中使用腾讯云Im的示例
2020/10/23 Javascript
浅谈Vue使用Cascader级联选择器数据回显中的坑
2020/10/31 Javascript
从源码角度来回答keep-alive组件的缓存原理
2021/01/18 Javascript
javascript实现简单页面倒计时
2021/03/02 Javascript
[51:00]Secret vs VGJ.S 2018国际邀请赛淘汰赛BO3 第一场 8.24
2018/08/25 DOTA
如何在sae中设置django,让sae的工作环境跟本地python环境一致
2017/11/21 Python
Python实现数据可视化看如何监控你的爬虫状态【推荐】
2018/08/10 Python
使用python判断你是青少年还是老年人
2018/11/29 Python
详解Python装饰器
2019/03/25 Python
Python中的Socket 与 ScoketServer 通信及遇到问题解决方法
2019/04/01 Python
亿阳信通股份有限公司C#笔试题
2016/12/06 面试题
大学生的应聘自我评价
2013/12/13 职场文书
军人违纪检讨书
2014/02/04 职场文书
高三学生评语大全
2014/04/25 职场文书
2014年仓库工作总结
2014/11/20 职场文书
Pytorch反向传播中的细节-计算梯度时的默认累加操作
2021/06/05 Python
sql server删除前1000行数据的方法实例
2021/08/30 SQL Server
Java 深入探究讲解简单工厂模式
2022/04/07 Java/Android
Python使用MapReduce进行简单的销售统计
2022/04/22 Python