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的网络编程库Gevent的安装及使用技巧
Jun 24 Python
Python 含参构造函数实例详解
May 25 Python
Django使用详解:ORM 的反向查找(related_name)
May 30 Python
Django管理员账号和密码忘记的完美解决方法
Dec 06 Python
Python 文本文件内容批量抽取实例
Dec 10 Python
Python中那些 Pythonic的写法详解
Jul 02 Python
python中pygame安装过程(超级详细)
Aug 04 Python
python+selenium 点击单选框-radio的实现方法
Sep 03 Python
Python SSL证书验证问题解决方案
Jan 13 Python
5行Python代码实现图像分割的步骤详解
May 25 Python
python Matplotlib数据可视化(2):详解三大容器对象与常用设置
Sep 30 Python
使用python-cv2实现Harr+Adaboost人脸识别的示例
Oct 27 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
Smarty结合Ajax实现无刷新留言本实例
2007/01/02 PHP
PHP实现多条件查询实例代码
2010/07/17 PHP
PHP实现仿Google分页效果的分页函数
2015/07/29 PHP
PHP编程实现脚本异步执行的方法
2017/08/09 PHP
PHP强制转化的形式整理
2020/05/22 PHP
jQuery 锚点跳转滚动条平滑滚动一句话代码
2010/04/30 Javascript
jquery无刷新验证邮箱地址实现实例
2014/02/19 Javascript
jquery+json实现分页效果
2016/03/07 Javascript
Extjs4.0 ComboBox如何实现三级联动
2016/05/11 Javascript
Nodejs之TCP服务端与客户端聊天程序详解
2017/07/07 NodeJs
Vue.js实现按钮的动态绑定效果及实现代码
2017/08/21 Javascript
JavaScript实现职责链模式概述
2018/01/25 Javascript
vue实现个人信息查看和密码修改功能
2018/05/06 Javascript
可能被忽略的一些JavaScript数组方法细节
2019/02/28 Javascript
基于vue实现一个禅道主页拖拽效果
2019/05/27 Javascript
Vue实战教程之仿肯德基宅急送App
2019/07/19 Javascript
[01:02:03]2014 DOTA2华西杯精英邀请赛 5 24 NewBee VS VG
2014/05/26 DOTA
Python HTMLParser模块解析html获取url实例
2015/04/08 Python
python3利用smtplib通过qq邮箱发送邮件方法示例
2017/12/03 Python
Python实现将照片变成卡通图片的方法【基于opencv】
2018/01/17 Python
Python元组及文件核心对象类型详解
2018/02/11 Python
浅谈Python反射 & 单例模式
2019/03/21 Python
python面试题Python2.x和Python3.x的区别
2019/05/28 Python
python单线程下实现多个socket并发过程详解
2019/07/27 Python
详解Selenium 元素定位和WebDriver常用方法
2020/12/04 Python
一款恶搞头像特效的制作过程 利用css3和jquery
2014/11/21 HTML / CSS
html5的画布canvas——画出简单的矩形、三角形实例代码
2013/06/09 HTML / CSS
精油和天然健康美容产品:Art Naturals
2018/01/27 全球购物
以色列的身体护理及家居香薰品牌:Sabon NYC
2018/02/23 全球购物
Noon埃及:埃及在线购物
2019/11/26 全球购物
英国领先的在线高尔夫设备零售商:Golfgeardirect
2020/12/11 全球购物
如何用Java判断一个文件或目录是否存在
2012/11/19 面试题
毕业生的自我鉴定
2013/10/29 职场文书
《数星星的孩子》教学反思
2014/04/11 职场文书
餐饮投资计划书
2014/04/25 职场文书
Nest.js参数校验和自定义返回数据格式详解
2021/03/29 Javascript