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 translator使用实例
Sep 06 Python
布同自制Python函数帮助查询小工具
Mar 13 Python
动态规划之矩阵连乘问题Python实现方法
Nov 27 Python
python: line=f.readlines()消除line中\n的方法
Mar 19 Python
python+flask实现API的方法
Nov 21 Python
python 使用matplotlib 实现从文件中读取x,y坐标的可视化方法
Jul 04 Python
python Shapely使用指南详解
Feb 18 Python
pycharm运行程序时看不到任何结果显示的解决
Feb 21 Python
Python with语句用法原理详解
Jul 03 Python
python脚本使用阿里云slb对恶意攻击进行封堵的实现
Feb 04 Python
详解python的内存分配机制
May 10 Python
Requests什么的通通爬不了的Python超强反爬虫方案!
May 20 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编实现程动态图像的创建代码
2008/09/28 PHP
php异常处理使用示例
2014/02/25 PHP
PHP进制转换实例分析(2,8,16,36,64进制至10进制相互转换)
2017/02/04 PHP
PHP isset()与empty()的使用区别详解
2017/02/10 PHP
PHP里面把16进制的图片数据显示在html的img标签上(实现方法)
2017/05/02 PHP
全面解析PHP面向对象的三大特征
2017/06/10 PHP
thinkPHP5分页功能实现方法分析
2017/10/25 PHP
JavaScript高级程序设计 扩展--关于动态原型
2010/11/09 Javascript
基于jQuery的自动完成插件
2011/02/03 Javascript
javascript真的不难-回顾一下基础知识
2013/01/15 Javascript
早该知道的7个JavaScript技巧
2013/03/27 Javascript
JS实现文档加载完成后执行代码
2015/07/09 Javascript
javascript弹性运动效果简单实现方法
2016/01/08 Javascript
基于node实现websocket协议
2016/04/25 Javascript
JS实现显示带倒影的图片横排居中放大展示特效实例【测试可用】
2016/08/23 Javascript
浅谈react+es6+webpack的基础配置
2017/08/09 Javascript
ES6学习教程之模板字符串详解
2017/10/09 Javascript
Vue 过滤器filters及基本用法
2017/12/26 Javascript
vue2.0 父组件给子组件传递数据的方法
2018/01/15 Javascript
浅谈vue的几种绑定变量的值 防止其改变的方法
2018/03/01 Javascript
使用vue-router beforEach实现判断用户登录跳转路由筛选功能
2018/06/25 Javascript
JS面试题中深拷贝的实现讲解
2020/05/07 Javascript
Vue-cli 移动端布局和动画使用详解
2020/08/10 Javascript
[58:29]DOTA2-DPC中国联赛 正赛 Phoenix vs XG BO3 第一场 1月31日
2021/03/11 DOTA
Python 自动刷博客浏览量实例代码
2017/06/14 Python
python实现微信自动回复功能
2018/04/11 Python
Python将一个CSV文件里的数据追加到另一个CSV文件的方法
2018/07/04 Python
python  Django中的apps.py的目的是什么
2018/10/15 Python
使用TensorFlow实现二分类的方法示例
2019/02/05 Python
Python qrcode 生成一个二维码的实例详解
2020/02/12 Python
python实现最速下降法
2020/03/24 Python
html5手机端页面可以向右滑动导致样式受影响的问题
2018/06/20 HTML / CSS
西班牙伏林航空公司:Vueling
2016/08/05 全球购物
班主任工作实习计划
2015/01/16 职场文书
《金钱的魔力》教学反思
2016/02/20 职场文书
九大龙王魂骨,山龙王留下躯干骨,榜首死的最憋屈(被捏碎)
2022/03/18 国漫