Python中装饰器的一个妙用


Posted in Python onFebruary 08, 2015

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

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

代码如下:

def get_dump_data(dir_name, url):

    m = hashlib.md5(url)

    filename = m.hexdigest()

    full_file_name = \'dumps/%s/%s\' % (dir_name,filename)

 

    if os.path.isfile(full_file_name):

        return eval(file(full_file_name,\'r\').read())

    else:

        return None

 

 

def set_dump_data(dir_name, url, data):

    if not os.path.isdir(\'dumps/\'+dir_name):

        os.makedirs(\'dumps/\'+dir_name)

 

    m = hashlib.md5(url)

    filename = m.hexdigest()

    full_file_name = \'dumps/%s/%s\' % (dir_name,filename)

 

    f = file(full_file_name, \'w+\')

    f.write(repr(data))

    f.close()

 

 

def deco_dump_data(func):

    def func_wrapper(url):

        data = get_dump_data(func.__name__,url)

        if data is not None:

            return data

 

        data = func(url)

        if data is not None:

            set_dump_data(func.__name__,url,data)

        return data

 

    return func_wrapper

然后,我们只需要在每个func_top,func_sub,func_bottom都加上deco_dump_data这个装饰器即可~~

搞定!这样做最大的好处在于,因为top,sub,bottom,每一层都会dump数据,所以比如某个sub层数据dump之后,是根本不会走到他所对应的bottom层的,减少了大量的开销!

OK,就这样~ 人生苦短,我用python!

Python 相关文章推荐
Python中urllib2模块的8个使用细节分享
Jan 01 Python
Python新手实现2048小游戏
Mar 31 Python
对numpy中array和asarray的区别详解
Apr 17 Python
Django框架登录加上验证码校验实现验证功能示例
May 23 Python
解决pycharm运行程序出现卡住scanning files to index索引的问题
Jun 27 Python
详解Python利用random生成一个列表内的随机数
Aug 21 Python
Django模板标签{% for %}循环,获取制定条数据实例
May 14 Python
python实现b站直播自动发送弹幕功能
Feb 20 Python
彻底解决pip下载pytorch慢的问题方法
Mar 01 Python
详解Python中下划线的5种含义
Jul 15 Python
Python pandas之求和运算和非空值个数统计
Aug 07 Python
在python中读取和写入CSV文件详情
Jun 28 Python
Python中使用HTMLParser解析html实例
Feb 08 #Python
Pyhton中防止SQL注入的方法
Feb 05 #Python
Windows系统下安装Python的SSH模块教程
Feb 05 #Python
Python 冒泡,选择,插入排序使用实例
Feb 05 #Python
Python中使用Flask、MongoDB搭建简易图片服务器
Feb 04 #Python
Python os模块中的isfile()和isdir()函数均返回false问题解决方法
Feb 04 #Python
Python中使用socket发送HTTP请求数据接收不完整问题解决方法
Feb 04 #Python
You might like
JAVA/JSP学习系列之四
2006/10/09 PHP
php_xmlhttp 乱码问题解决方法
2009/08/07 PHP
基于PHP array数组的教程详解
2013/06/05 PHP
php实现多维数组中每个单元值(数字)翻倍的方法
2015/02/16 PHP
ThinkPHP3.2.3数据库设置新特性
2015/03/05 PHP
js用Date对象的setDate()函数对日期进行加减操作
2014/09/18 Javascript
JavaScript实现拖拽网页内元素的方法
2015/04/15 Javascript
angularJS与bootstrap结合实现动态加载弹出提示内容
2015/10/16 Javascript
JavaScript编程中window的location与history对象详解
2015/10/26 Javascript
JavaScript的MVVM库Vue.js入门学习笔记
2016/05/03 Javascript
js获取元素的外链样式的简单实现方法
2016/06/06 Javascript
[原创]jQuery常用的4种加载方式分析
2016/07/25 Javascript
老生常谈JavaScript面向对象基础与this指向问题
2017/10/16 Javascript
vue双花括号的使用方法 附练习题
2017/11/07 Javascript
Vue.directive 自定义指令的问题小结
2018/03/04 Javascript
原生js实现移动端Touch轮播图的方法步骤
2019/01/03 Javascript
在vue中使用防抖和节流,防止重复点击或重复上拉加载实例
2019/11/13 Javascript
javascript设计模式 ? 迭代器模式原理与用法实例分析
2020/04/17 Javascript
uni-app使用微信小程序云函数的步骤示例
2020/05/22 Javascript
Python读写Redis数据库操作示例
2014/03/18 Python
python实现求解列表中元素的排列和组合问题
2018/03/15 Python
python 异或加密字符串的实例
2018/10/14 Python
Python实现的序列化和反序列化二叉树算法示例
2019/03/02 Python
django 微信网页授权认证api的步骤详解
2019/07/30 Python
Django 后台获取文件列表 InMemoryUploadedFile的例子
2019/08/07 Python
python实现异常信息堆栈输出到日志文件
2019/12/26 Python
Python读取表格类型文件代码实例
2020/02/17 Python
Python json模块与jsonpath模块区别详解
2020/03/05 Python
想学画画?python满足你!
2020/12/24 Python
python爬取抖音视频的实例分析
2021/01/19 Python
学校门卫岗位职责
2014/03/16 职场文书
团结就是力量演讲稿
2014/05/21 职场文书
毕业证代领委托书
2014/09/26 职场文书
无工作证明怎么写
2015/06/15 职场文书
2016年校园社会综合治理宣传月活动总结
2016/03/16 职场文书
PyTorch 如何自动计算梯度
2021/05/23 Python