好吧,我知道是大半夜……,但我还是觉得赶紧花上半个小时,把这最新的想法分享出来是值得的~直接进入正题~

我们来模拟一个场景,需要你去抓去一个页面,然后这个页面有好多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也是同样。

如果正常情况下,这样确实已经满足需求了,但是偏偏这个你要抓取的网站可能极不稳定,经常链接不上,导致数据拿不到。

于是这个时候你有两个选择:

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

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

对第一种方案基本无法实现,因为如果别人网站的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. 开课吧python课程-Python教父廖雪峰加入开课吧 打造技术品类黄金内容班底

    近日,刚刚宣布获得D轮融资的慧科集团再添喜讯--开源教程开发者Python教父廖雪峰作为内容合伙人和战略顾问加入慧科集团旗下互联网人学习成长社群开课吧,全面统筹和规划开课吧Python.Java.区块 ...

  2. python爬虫教程-Python教父|廖雪峰老师官方爬虫教程,13个案例带你全面入门!

    原标题:Python教父|廖雪峰老师官方爬虫教程,13个案例带你全面入门! Python简直就是万能的,你用Python都做过哪些事? 用网页看各大网站的VIP视频,用python下载? 用Pytho ...

  3. 廖雪峰python教程-福利 | 廖雪峰官方Python教程,拿走不谢!

    原标题:福利 | 廖雪峰官方Python教程,拿走不谢! Python简直就是万能的,你用Python都做过哪些事? 用网页看各大网站的VIP视频,用python下载? 用Python玩跳一跳,跳到5 ...

  4. 廖雪峰python视频教程-福利 | 廖雪峰官方Python教程,拿走不谢!

    原标题:福利 | 廖雪峰官方Python教程,拿走不谢! Python简直就是万能的,你用Python都做过哪些事? 用网页看各大网站的VIP视频,用python下载? 用Python玩跳一跳,跳到5 ...

  5. Python学习笔记---------廖雪峰(基础和函数)

    Python学习笔记---------廖雪峰(基础和函数)

  6. 【笔记】Python学习(廖雪峰)笔记①——Python基础知识

    Python学习(廖雪峰)笔记①--Python基础知识 Python 基础知识 字符串与编码 ASCII.Unicode.UTF-8 Python字符串 格式化 使用list和tuple list( ...

  7. python装饰器与闭包_Python 装饰器和闭包

    Python 装饰器和闭包 装饰器是 Python 中常见的语法糖,这篇文章讲了闭包和装饰器的原理,并且分析了函数中变量的作用域,以及尝试总结了常见的坑. 装饰器基础 首先来看看装饰器的定义:装饰器本 ...

  8. python中装饰器的作用_Python装饰器详解,详细介绍它的应用场景

    装饰器的应用场景附加功能 数据的清理或添加:函数参数类型验证 @require_ints 类似请求前拦截数据格式转换 将函数返回字典改为 JSON/YAML 类似响应后篡改为函数提供额外的数据 moc ...

  9. python重复字符串n次_python装饰器听了N次也没印象,读完这篇你就懂了

    装饰器其实一直是我的一个"老大难".这个知识点就放在那,但是拖延症... 其实在平常写写脚本的过程中,这个知识点你可能用到不多 但在面试的时候,这可是一个高频问题. 一.什么是装饰 ...

最新文章

  1. 02.规划过程组表格-需求管理计划
  2. 「后端小伙伴来学前端了」CSS 做三角边框,必会的基础操作之一
  3. Android源码分析--MediaServer源码分析(二)
  4. Hibernate配置属性详解
  5. HEVC---CompressCU 函数解析
  6. 敏捷软件开发VS传统软件开发
  7. 《零基础学算法 第3版》PDF 免费
  8. python制作词云图
  9. kdj买卖指标公式源码_KDJ胜率极高的买入机会,死记一个指标(附KDJ背离指标源码)...
  10. CocosCreator学习示例合集v3.4.2
  11. 微信支付 H5端 和小程序端 统一下单接口 4个JAVA源码文件代码
  12. web前端HTML和CSS3常见面试题
  13. 从键盘上输入两个字符串,将两个字符串首尾相连接后,再输出新的字符串(c语言)
  14. 正斜杠(/)与反斜杠(\)总结
  15. 数据库连接池 ( 二 ) 连接池概念
  16. IPv6 NDP邻居发现协议 1
  17. CSR8675的DSP学习笔记——a2dp_sink工程的matlab仿真
  18. 网络通信上手项目(网络画图板)
  19. Android:设计一个在屏幕上移动的小球程序
  20. python的两种计时方式

热门文章

  1. S3TC IAP15F2K61S2点亮一个发光二极管keil和stc-isp软件操作
  2. 第一篇:你不一定了解的推荐系统
  3. SQL递归查询知多少
  4. Java并发和多线程3:线程调度和有条件取消调度
  5. boost asio异步通信
  6. HelloWorld Windows Live Writer
  7. XML命名空间和相关类简介
  8. Android6.0显示系统(五) SurfaceFlinger服务
  9. Android Audio System 架构初探(好文)
  10. Python调用shell命令方式