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操作列表的常用方法分享
Feb 13 Python
python如何查看系统网络流量的信息
Sep 12 Python
python中pandas.DataFrame的简单操作方法(创建、索引、增添与删除)
Mar 12 Python
Python多线程爬虫实战_爬取糗事百科段子的实例
Dec 15 Python
Python模块的加载讲解
Jan 15 Python
python实现微信自动回复及批量添加好友功能
Jul 03 Python
Django  ORM 练习题及答案
Jul 19 Python
Python实现一个数组除以一个数的例子
Jul 20 Python
pyinstaller打包opencv和numpy程序运行错误解决
Aug 16 Python
python sorted方法和列表使用解析
Nov 18 Python
Python实现爬取网页中动态加载的数据
Aug 17 Python
python解压zip包中文乱码解决方法
Nov 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
PHP STRING 陷阱原理说明
2010/07/24 PHP
php中执行系统命令的方法
2015/03/21 PHP
浅析PHP中Session可能会引起并发问题
2015/07/23 PHP
PHP入门教程之自定义函数用法详解(创建,调用,变量,参数,返回值等)
2016/09/11 PHP
laravel框架使用极光推送消息操作示例
2020/02/15 PHP
php实现文件上传基本验证
2020/03/04 PHP
JS 强制设为首页的代码
2009/01/31 Javascript
javascript面向对象入门基础详细介绍
2012/09/05 Javascript
javascript移出节点removeChild()使用介绍
2014/04/03 Javascript
IE6-IE9中tbody的innerHTML不能赋值的解决方法
2014/06/05 Javascript
javascript实现简单的全选和反选功能
2016/01/05 Javascript
Bootstrap菜单按钮及导航实例解析
2016/09/09 Javascript
微信开发 微信授权详解
2016/10/21 Javascript
浅谈javascript中的事件冒泡和事件捕获
2016/12/28 Javascript
Vue.js路由vue-router使用方法详解
2017/03/20 Javascript
使用Bootstrap + Vue.js实现表格的动态展示、新增和删除功能
2017/11/27 Javascript
Node.Js中实现端口重用原理详解
2018/05/03 Javascript
vue做移动端适配最佳解决方案(亲测有效)
2018/09/04 Javascript
vue动态改变背景图片demo分享
2018/09/13 Javascript
使用jQuery动态设置单选框的选中效果
2018/12/06 jQuery
Vue 理解之白话 getter/setter详解
2019/04/16 Javascript
vue+element创建动态的form表单及动态生成表格的行和列
2019/05/20 Javascript
[19:26]TNC vs EG (BO3)
2018/06/07 DOTA
Python采用socket模拟TCP通讯的实现方法
2014/11/19 Python
Python多线程同步Lock、RLock、Semaphore、Event实例
2014/11/21 Python
Pandas GroupBy对象 索引与迭代方法
2018/11/16 Python
Python 实现子类获取父类的类成员方法
2019/01/11 Python
对Python3 pyc 文件的使用详解
2019/02/16 Python
Python能做什么
2020/06/02 Python
Python random模块的使用示例
2020/10/10 Python
英国最大的婴儿监视器网上商店:Baby Monitors Direct
2018/04/24 全球购物
英国马匹装备和马术用品购物网站:Equine Superstore
2019/03/03 全球购物
BSTN意大利:德国街头和运动文化高品质商店
2020/12/22 全球购物
房屋买卖授权委托书
2014/09/27 职场文书
详解Python+OpenCV绘制灰度直方图
2022/03/22 Python
openstack云计算keystone组件工作介绍
2022/04/20 Servers