好吧,我知道是大半夜……,但我还是觉得赶紧花上半个小时,把这最新的想法分享出来是值得的~直接进入正题~ 我们来模拟一个场景,需要你去抓去一个页面,然后这个页面有好多url也要分别去抓取,而进入这些子url后,还有数据要抓取。简单点,我们就按照三层来看,那我们的代码就是如下:

def func_top(url):

data_dict= {}

#在页面上获取到子url

sub_urls = xxxx

data_list = []

for it in sub_urls:

data_list.append(func_sub(it))

data_dict['data'] = data_list

return data_dict

def func_sub(url):

data_dict= {}

#在页面上获取到子url

bottom_urls = xxxx

data_list = []

for it in bottom_urls:

data_list.append(func_bottom(it))

data_dict['data'] = data_list

return data_dict

def func_bottom(url):

#获取数据

data = xxxx

return data

func_top是上层页面的处理函数,func_sub是子页面的处理函数,func_bottom是最深层页面的处理函数,func_top会在取到子页面url后遍历调用func_sub,func_sub也是同样。 如果正常情况下,这样确实已经满足需求了,但是偏偏这个你要抓取的网站可能极不稳定,经常链接不上,导致数据拿不到。 于是这个时候你有两个选择:

1.遇到错误就停止,之后重新从断掉的位置开始重新跑

2.遇到错误继续,但是要在之后重新跑一遍,这个时候已经有的数据不希望再去网站拉一次,而只去拉没有取到的数据

对第一种方案基本无法实现,因为如果别人网站的url调整顺序,那么你记录的位置就无效了。那么只有第二种方案,说白了,就是要把已经拿到的数据cache下来,等需要的时候,直接从cache里面取。 OK,目标已经有了,怎么实现呢? 如果是在C++中的,这是个很麻烦的事情,而且写出来的代码必定丑陋无比,然而庆幸的是,我们用的是python,而python对函数有装饰器。 所以实现方案也就有了: 定义一个装饰器,如果之前取到数据,就直接取cache的数据;如果之前没有取到,那么就从网站拉取,并且存入cache中. 代码如下:

import os

import hashlib

def deco_args_recent_cache(category='dumps'):

'''

装饰器,返回最新cache的数据

'''

def deco_recent_cache(func):

def func_wrapper(*args, **kargs):

sig = _mk_cache_sig(*args, **kargs)

data = _get_recent_cache(category, func.__name__, sig)

if data is not None:

return data

data = func(*args, **kargs)

if data is not None:

_set_recent_cache(category, func.__name__, sig, data)

return data

return func_wrapper

return deco_recent_cache

def _mk_cache_sig(*args, **kargs):

'''

通过传入参数,生成唯一标识

'''

src_data = repr(args) + repr(kargs)

m = hashlib.md5(src_data)

sig = m.hexdigest()

return sig

def _get_recent_cache(category, func_name, sig):

full_file_path = '%s/%s/%s' % (category, func_name, sig)

if os.path.isfile(full_file_path):

return eval(file(full_file_path,'r').read())

else:

return None

def _set_recent_cache(category, func_name, sig, data):

full_dir_path = '%s/%s' % (category, func_name)

if not os.path.isdir(full_dir_path):

os.makedirs(full_dir_path)

full_file_path = '%s/%s/%s' % (category, func_name, sig)

f = file(full_file_path, 'w+')

f.write(repr(data))

f.close()

然后,我们只需要在每个func_top,func_sub,func_bottom都加上deco_args_recent_cache这个装饰器即可~~ 搞定!这样做最大的好处在于,因为top,sub,bottom,每一层都会dump数据,所以比如某个sub层数据dump之后,是根本不会走到他所对应的bottom层的,减少了大量的开销! OK,就这样~ 人生苦短,我用python!

python三层装饰器-python装饰器的一个妙用相关推荐

  1. python3层装饰器_python三层装饰器python字符串,数值计算

    Python是一种面向对象的语言,但它不像C++一样把标准类都封装到库中,而是进行了进一步的封装,语言本身就集成一些类和函数,比如print,list,dict etc. 给编程带来很大的便捷 Pyt ...

  2. python三层装饰器-python三大神器===》装饰器

    1.认识装饰器 如果你经常看我的博客,你已经学会了python的前两大"神器'(迭代器,生成器),那么什么是装饰器呢?就如字面意义装饰器是对某个事物(通常指函数)进行装饰,让其在不修改任何内 ...

  3. python三层装饰器-python3装饰器

    python装饰器 预备知识 首先我们要知道在python,一切皆对象,函数也是一个对象 >>> def test(): ... return "Hello World&q ...

  4. python三层装饰器-Python自动化开发学习4-装饰器

    装饰器 通过装饰器可以为函数添加附加功能.通过修改函数本身也可以实现增加功能,但是通过装饰器还有下面2个好处.装饰器的2个原则:不改变被装饰函数的源代码 不改变被装饰函数的调用方式 遵循了上面2个原则 ...

  5. Python 闭包、单个装饰器、多个装饰器、装饰器修饰类、应用场景

    1. 闭包 在 Python 中,函数也可以作为参数.我们可以执行下面的代码: def func(a, b):return a + bprint(func) 我们直接输出函数名,而没有加括号.输出结果 ...

  6. Python的神奇功能——函数装饰器MetaClass

    Python中的装饰器,会让很多人望而却步.不要被它吓跑,啃下它,其实超有用,也没有想象中难. 所谓的装饰器,其实就是通过装饰器函数,来修改原函数的一些功能,使得原函数不需要修改. Python的装饰 ...

  7. python描述器做权限控制_Python装饰器14-描述器

    描述器 这是Python一个重要的概念,英文名:Descriptor descriptor是对象的一个属性,只不过它存在于类的dict中并且有特殊方法get(可能还有set和__delete)而具有一 ...

  8. Python 进阶_闭包 amp; 装饰器

    目录 目录 闭包 函数的实质和属性 闭包有什么好处 小结 装饰器 更加深入的看看装饰器的执行过程 带参数的装饰器 装饰器的叠加 小结 装饰器能解决什么问题 小结 闭包 Closure: 如果内层函数引 ...

  9. python基础知识-11-函数装饰器

    python其他知识目录 1.装饰器学习前热身准备 1.1装饰器简介 1.2装饰器热身分析 1) def func():pass v1 = 10 v2 = func #将函数名赋予一个变量,就和变量赋 ...

  10. Python(三)对装饰器的理解

    装饰器是 Python 的一个重要部分,也是比较难理解和使用好的部分.下面对装饰器做一下简单整理 1. 前言 装饰器实际上是应用了设计模式里,装饰器模式的思想: 在不概念原有结构的情况下,添加新的功能 ...

最新文章

  1. 宏定义中的#、##操作符和... 、 _ _VA_ARGS_ _解析
  2. PAT甲级1017 Queueing at Bank:[C++题解]字符串、结构体、最小堆
  3. android中占容器比例,Android中的容器
  4. C#中集合接口关系笔记
  5. TensorFlow实现单隐层神经网络
  6. 各种排序算法比较--2015年7月23日22:33:43v1.0版
  7. 2016.3.16(Java图形用户界面)
  8. Spring Boot 菜鸟教程 application.properties 常用配置
  9. Oracle_11g_R2数据库在Windows_Server_2008_R2企业版中安装
  10. ANC降噪耳机量产测试方案
  11. 计算机术语CPI是什么意思,cpi是什么意思
  12. 微信app用户及市场调研
  13. 计算机服务器加载失败,win10系统打开windows Media player听歌提示“服务器运行失败”的详细步骤...
  14. 金蝶EAS DEP脚本(1)—— 基本概念
  15. MacOS Ventura 13.0 Beta2 (22A5286j) 带 OC 0.8.2 三分区原版黑苹果镜像
  16. excel学习-制作斜线表头
  17. Sentinel-2(哨兵-2)L1C数据辐亮度(辐射定标)和TOA反射率的获取说明
  18. 前端报错Unknown custom element
  19. 继电器逻辑在控制系统中的应用
  20. CVPR2022新作:P图不会,深度学习来帮忙,基于GAN逆映射的图像编辑(中)

热门文章

  1. C#字符串格式化说明(String.Format) (zz.IS2120)
  2. Lambda表达式介绍
  3. [原创] 为Visio添加公式编辑器工具栏按钮
  4. activeMQ 安装部署文档
  5. charles 抓包 (二)
  6. 数据仓库与数据集市建模
  7. ES6之Promise
  8. 安防工程商必须知道的PoE供电真相
  9. 运用C#生成docx格式的报表
  10. c#v2.0 扩展特性 翻译(1)