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入门教程3. 列表基本操作【定义、运算、常用函数】
Oct 30 Python
python2和python3在处理字符串上的区别详解
May 29 Python
python flask框架实现传数据到js的方法分析
Jun 11 Python
Python用字典构建多级菜单功能
Jul 11 Python
对django layer弹窗组件的使用详解
Aug 31 Python
python读取tif图片时保留其16bit的编码格式实例
Jan 13 Python
Python解析多帧dicom数据详解
Jan 13 Python
解决Jupyter Notebook开始菜单栏Anaconda下消失的问题
Apr 13 Python
python中查看.db文件中表格的名字及表格中的字段操作
Jul 07 Python
简单了解如何封装自己的Python包
Jul 08 Python
python更新数据库中某个字段的数据(方法详解)
Nov 18 Python
selenium+headless chrome爬虫的实现示例
Jan 08 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
开源SNS系统-ThinkSNS
2008/05/18 PHP
php查看请求头信息获取远程图片大小的方法分享
2013/12/25 PHP
PHP生成唯一订单号的方法汇总
2015/04/16 PHP
PHP实现bitmap位图排序与求交集的方法
2016/07/28 PHP
PHP实现生成带背景的图形验证码功能
2016/10/03 PHP
总结PHP代码规范、流程规范、git规范
2018/06/18 PHP
PHP使用OB缓存实现静态化功能示例
2019/03/23 PHP
XAMPP升级PHP版本实现步骤解析
2020/09/04 PHP
Yii 实现数据加密和解密
2021/03/09 PHP
JS input 数字验证代码
2009/07/30 Javascript
jQuery 核心函数以及jQuery对象
2010/03/23 Javascript
JAVASCRIPT实现的WEB页面跳转以及页面间传值方法
2010/05/13 Javascript
jquery不会自动回收xmlHttpRequest对象 导致了内存溢出
2012/06/18 Javascript
javascript 手动给表增加数据的小例子
2013/07/10 Javascript
基于jQuery实现自动轮播旋转木马特效
2015/11/02 Javascript
JavaScript中校验银行卡号的实现代码
2016/12/19 Javascript
IE11下使用canvas.toDataURL报SecurityError错误的解决方法
2017/11/19 Javascript
AngularJS2 与 D3.js集成实现自定义可视化的方法
2017/12/01 Javascript
jQuery+Cookie实现切换皮肤功能【附源码下载】
2018/03/25 jQuery
在小程序中集成redux/immutable/thunk第三方库的方法
2018/08/12 Javascript
基于vue与element实现创建试卷相关功能(实例代码)
2020/12/07 Vue.js
[03:08]迎霜节狂欢!2018年迎霜节珍藏Ⅰ一览
2018/12/25 DOTA
简述Python中的面向对象编程的概念
2015/04/27 Python
python交互式图形编程实例(一)
2017/11/17 Python
浅谈python中str字符串和unicode对象字符串的拼接问题
2018/12/04 Python
Python3 实现串口两进程同时读写
2019/06/12 Python
python批量处理文件或文件夹
2020/07/28 Python
Windows 下python3.8环境安装教程图文详解
2020/03/11 Python
PyCharm Anaconda配置PyQt5开发环境及创建项目的教程详解
2020/03/24 Python
python文件操作seek()偏移量,读取指正到指定位置操作
2020/07/05 Python
迪奥美国官网:Dior美国
2019/12/07 全球购物
办公室驾驶员岗位职责
2013/11/15 职场文书
房地产销售员的自我评价分享
2013/12/04 职场文书
导游词之山东红叶谷
2019/10/31 职场文书
vue引入Excel表格插件的方法
2021/04/28 Vue.js
Python开发之QT解决无边框界面拖动卡屏问题(附带源码)
2021/05/27 Python