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 相关文章推荐
用yum安装MySQLdb模块的步骤方法
Dec 15 Python
Python实现嵌套列表及字典并按某一元素去重复功能示例
Nov 30 Python
解决Ubuntu pip 安装 mysql-python包出错的问题
Jun 11 Python
python爬虫URL重试机制的实现方法(python2.7以及python3.5)
Dec 18 Python
Python自动抢红包教程详解
Jun 11 Python
python实现比对美团接口返回数据和本地mongo数据是否一致示例
Aug 09 Python
pytorch 在sequential中使用view来reshape的例子
Aug 20 Python
python爬虫爬取监控教务系统的思路详解
Jan 08 Python
Python改变对象的字符串显示的方法
Aug 01 Python
Python私有属性私有方法应用实例解析
Sep 15 Python
通俗易懂了解Python装饰器原理
Sep 17 Python
用python-webdriver实现自动填表的示例代码
Jan 13 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
ThinkPHP权限认证Auth实例详解
2014/07/22 PHP
PHP实现抓取Google IP并自动修改hosts文件
2015/02/12 PHP
PHP生成随机字符串(3种方法)
2015/09/25 PHP
thinkphp多表查询两表有重复相同字段的完美解决方法
2016/09/22 PHP
yii2中LinkPager增加总页数和总记录数的实例
2017/08/28 PHP
PHP调用全国天气预报数据接口查询天气示例
2019/02/20 PHP
Yii框架where查询用法实例分析
2019/10/22 PHP
javascript replace方法与正则表达式
2008/02/19 Javascript
初学Jquery插件制作 在SageCRM的查询屏幕隐藏部分行的功能
2011/12/26 Javascript
jQuery模拟超链接点击效果代码
2013/04/21 Javascript
jquery实现的一个导航滚动效果具体代码
2013/05/27 Javascript
简单的两种Extjs formpanel加载数据的方式
2013/11/09 Javascript
详解JavaScript数组和字符串中去除重复值的方法
2016/03/07 Javascript
js实现放大镜特效
2017/05/18 Javascript
纯js实现的积木(div层)拖动功能示例
2017/07/19 Javascript
html+jQuery实现拖动滑块图片拼图验证码插件【移动端适用】
2019/09/10 jQuery
javascript实现前端分页效果
2020/06/24 Javascript
Vue+element+cookie记住密码功能的简单实现方法
2020/09/20 Javascript
[03:55]2014DOTA2国际邀请赛 Fnatic经理采访赢DK在情理之中
2014/07/10 DOTA
python实现带声音的摩斯码翻译实现方法
2015/05/20 Python
python os用法总结
2018/06/08 Python
python如何爬取个性签名
2018/06/19 Python
使用python 打开文件并做匹配处理的实例
2019/01/02 Python
对python PLT中的image和skimage处理图片方法详解
2019/01/10 Python
pytorch中的inference使用实例
2020/02/20 Python
python GUI库图形界面开发之pyinstaller打包python程序为exe安装文件
2020/02/26 Python
用python实现一个简单计算器(完整DEMO)
2020/10/14 Python
The North Face北面德国官网:美国著名户外品牌
2018/12/12 全球购物
JENNIFER BEHR官网:各种耳环和发饰
2020/06/07 全球购物
教学实验楼管理制度
2014/02/01 职场文书
2014年客服工作总结与计划
2014/12/09 职场文书
安全教育片观后感
2015/06/17 职场文书
四则混合运算教学反思
2016/02/23 职场文书
看完这篇文章获得一些java if优化技巧
2021/07/15 Java/Android
使用redis实现延迟通知功能(Redis过期键通知)
2021/09/04 Redis
mysql聚集索引、辅助索引、覆盖索引、联合索引的使用
2022/02/12 MySQL