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制作数据导入导出工具
Jul 31 Python
深入理解python中的闭包和装饰器
Jun 12 Python
python+opencv轮廓检测代码解析
Jan 05 Python
python购物车程序简单代码
Apr 18 Python
实用自动化运维Python脚本分享
Jun 04 Python
实践Vim配置python开发环境
Jul 02 Python
对python xlrd读取datetime类型数据的方法详解
Dec 26 Python
Django集成搜索引擎Elasticserach的方法示例
Jun 04 Python
pytorch torch.nn.AdaptiveAvgPool2d()自适应平均池化函数详解
Jan 03 Python
python except异常处理之后不退出,解决异常继续执行的实现
Apr 25 Python
PyTorch-GPU加速实例
Jun 23 Python
Python NumPy灰度图像的压缩原理讲解
Aug 04 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初学者最感迷茫的问题小结
2010/03/27 PHP
php 搜索框提示(自动完成)实例代码
2012/02/05 PHP
解析php file_exists无效的解决办法
2013/06/26 PHP
PHP的foreach中使用引用时需要注意的一个问题和解决方法
2014/05/29 PHP
初识php MVC
2014/09/10 PHP
PHP防止注入攻击实例分析
2014/11/03 PHP
PHP实现一个简单url路由功能实例
2016/11/05 PHP
php创建多级目录与级联删除文件的方法示例
2019/09/12 PHP
保证JavaScript和Asp、Php等后端程序间传值编码统一
2009/04/17 Javascript
document.getElementById为空或不是对象的解决方法
2010/01/24 Javascript
JS代码放在head和body中的区别分析
2011/12/01 Javascript
了解jQuery技巧来提高你的代码(个人觉得那个jquery的手册很不错)
2012/02/10 Javascript
JS控件的生命周期介绍
2012/10/22 Javascript
为JS扩展Array.prototype.indexOf引发的问题探讨及解决
2013/04/24 Javascript
探讨JQUERY JSON的反序列化类 using问题的解决方法
2013/12/19 Javascript
将HTML的左右尖括号等转义成实体形式的两种实现方式
2014/05/04 Javascript
基于javascript实现图片左右切换效果
2016/01/25 Javascript
在Web项目中引入Jquery插件报错的完美解决方案(图解)
2016/09/19 Javascript
vue+mockjs模拟数据实现前后端分离开发的实例代码
2017/08/08 Javascript
ajax与jsonp的区别及用法
2018/10/16 Javascript
jQuery实现的鼠标拖动浮层功能示例【拖动div等任何标签】
2018/12/29 jQuery
vue 动态添加的路由页面刷新时失效的原因及解决方案
2021/02/26 Vue.js
[51:43]OG vs LGD 2018国际邀请赛淘汰赛BO3 第五场 8.26
2018/08/30 DOTA
轻松实现python搭建微信公众平台
2016/02/16 Python
异步任务队列Celery在Django中的使用方法
2018/06/07 Python
Python零基础入门学习之输入与输出
2019/04/03 Python
详解Python sys.argv使用方法
2019/05/10 Python
CSS3教程(8):CSS3透明度指南
2009/04/02 HTML / CSS
HTML5 与 XHTML2
2008/10/17 HTML / CSS
严选全球尖货,立足香港:Bonpont宝盆
2018/07/24 全球购物
PatPat阿根廷:妈妈们的购物平台
2019/05/30 全球购物
标准导师推荐信(医学类)
2013/10/28 职场文书
教师求职自荐书
2014/06/14 职场文书
导游欢送词
2015/01/31 职场文书
学校中层领导培训心得体会
2016/01/11 职场文书
2019年思想汇报
2019/06/20 职场文书