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 解析XML python模块xml.dom解析xml实例代码
Feb 07 Python
Python获取文件ssdeep值的方法
Oct 05 Python
Python实现复杂对象转JSON的方法示例
Jun 22 Python
Python爬虫通过替换http request header来欺骗浏览器实现登录功能
Jan 07 Python
Windows下安装Django框架的方法简明教程
Mar 28 Python
python 除法保留两位小数点的方法
Jul 16 Python
numpy下的flatten()函数用法详解
May 27 Python
Django利用cookie保存用户登录信息的简单实现方法
May 27 Python
matplotlib 生成的图像中无法显示中文字符的解决方法
Jun 10 Python
Python 多进程、多线程效率对比
Nov 19 Python
python 制作网站小说下载器
Feb 20 Python
python学习之使用Matplotlib画实时的动态折线图的示例代码
Feb 25 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
PHP5 安装方法
2007/01/15 PHP
url decode problem 解决方法
2011/12/26 PHP
PHP JS Ip地址及域名格式检测代码
2013/09/27 PHP
php获取bing每日壁纸示例分享
2014/02/25 PHP
php数组中删除元素之重新索引的方法
2014/09/16 PHP
PHP设计模式之工厂模式(Factory Pattern)的讲解
2019/03/21 PHP
脚本吧 - 幻宇工作室用到js,超强推荐expand.js
2006/12/23 Javascript
几款极品的javascript压缩混淆工具
2007/05/16 Javascript
慎用 somefunction.prototype 分析
2009/06/02 Javascript
javascript测试题练习代码
2012/10/10 Javascript
Javascript表格翻页效果实现思路及代码
2013/08/23 Javascript
JS获取客户端IP地址、MAC和主机名的7个方法汇总
2014/07/21 Javascript
javascript的tab切换原理与效果实现方法
2015/01/10 Javascript
Javascript中String的常用方法实例分析
2015/06/13 Javascript
jQuery检测滚动条是否到达底部
2015/12/15 Javascript
如何解决easyui自定义标签 datagrid edit combobox 手动输入保存不上
2015/12/26 Javascript
基于JavaScript实现树形下拉框
2016/08/10 Javascript
利用node.js实现自动生成前端项目组件的方法详解
2017/07/12 Javascript
vue项目中的webpack-dev-sever配置方法
2017/12/14 Javascript
vue使用中的内存泄漏【推荐】
2018/07/10 Javascript
说说如何使用Vuex进行状态管理(小结)
2019/04/14 Javascript
Vue filter 过滤当前时间 实现实时更新效果
2019/12/20 Javascript
js+canvas绘制图形验证码
2020/09/21 Javascript
WebStorm中如何将自己的代码上传到github示例详解
2020/10/28 Javascript
[04:44]显微镜下的DOTA2第二期——你所没有注意到的细节
2014/06/20 DOTA
使用Python写个小监控
2016/01/27 Python
python 定时修改数据库的示例代码
2018/04/08 Python
opencv实现静态手势识别 opencv实现剪刀石头布游戏
2019/01/22 Python
HTML5 文件域+FileReader 分段读取文件并上传到服务器
2017/10/23 HTML / CSS
美国摩托车头盔、零件、齿轮及配件商店:Cycle Gear
2019/06/12 全球购物
Stio官网:男女、儿童户外服装
2019/12/13 全球购物
英语专业应届生求职信范文
2013/11/15 职场文书
大学生翘课检讨书范文
2014/10/06 职场文书
保护校园环境倡议书
2015/04/28 职场文书
房屋买卖定金协议书
2016/03/21 职场文书
使用goaccess分析nginx日志的详细方法
2021/07/09 Servers