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抓取京东商城手机列表url实例代码
Dec 18 Python
python 写的一个爬虫程序源码
Feb 28 Python
Python语言生成水仙花数代码示例
Dec 18 Python
Selenium chrome配置代理Python版的方法
Nov 29 Python
Django model select的多种用法详解
Jul 16 Python
python如何统计代码运行的时长
Jul 24 Python
flask 使用 flask_apscheduler 做定时循环任务的实现
Dec 10 Python
Python时间差中seconds和total_seconds的区别详解
Dec 26 Python
python自动下载图片的方法示例
Mar 25 Python
Python3.9 beta2版本发布了,看看这7个新的PEP都是什么
Jun 10 Python
对Python 字典元素进行删除的方法
Jul 31 Python
基于Python组装jmx并调用JMeter实现压力测试
Nov 03 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
在mysql数据库原有字段后增加新内容
2009/11/26 PHP
php实现用户在线时间统计详解
2011/10/08 PHP
测试php连接mysql是否成功的代码分享
2014/01/24 PHP
Win7下手动安装apache2.2、php5.4笔记
2015/04/03 PHP
php爬取天猫和淘宝商品数据
2018/02/23 PHP
GridView中获取被点击行中的DropDownList和TextBox中的值
2013/07/18 Javascript
关于js里的this关键字的理解
2015/08/17 Javascript
jquery实现浮动在网页右下角的彩票开奖公告窗口代码
2015/09/04 Javascript
Jquery Ajax Error 调试错误的技巧
2015/11/20 Javascript
浅谈JS正则表达式的RegExp对象和括号的使用
2016/07/28 Javascript
Seajs是什么及sea.js 由来,特点以及优势
2016/10/13 Javascript
JavaScript自动点击链接 防止绕过浏览器访问的方法
2017/01/19 Javascript
JavaScript限制在客户区可见范围的拖拽(解决scrollLeft和scrollTop的问题)(2)
2017/05/17 Javascript
jQuery实现获取table中鼠标click点击位置行号与列号的方法
2017/10/09 jQuery
Vue自定义过滤器格式化数字三位加一逗号实现代码
2018/03/23 Javascript
深入解析Vue源码实例挂载与编译流程实现思路详解
2019/05/05 Javascript
详解vue-cli中使用rem,vue自适应
2019/05/06 Javascript
微信小程序调用天气接口并且渲染在页面过程详解
2019/06/24 Javascript
手写Vue2.0 数据劫持的示例
2021/03/04 Vue.js
[01:51]2014DOTA2国际邀请赛 这个赛场没有失败者VGTi5再见
2014/07/23 DOTA
[56:17]NB vs Infamous 2019国际邀请赛淘汰赛 败者组 BO3 第三场 8.22
2019/09/05 DOTA
python中bisect模块用法实例
2014/09/25 Python
python 拷贝特定后缀名文件,并保留原始目录结构的实例
2018/04/27 Python
Django实现登录随机验证码的示例代码
2018/06/20 Python
浅谈pyqt5中信号与槽的认识
2019/02/17 Python
Python如何爬取微信公众号文章和评论(基于 Fiddler 抓包分析)
2019/06/28 Python
Tory Burch英国官方网站:美国时尚生活品牌
2017/12/06 全球购物
工商管理毕业生推荐信
2013/12/24 职场文书
平安建设实施方案
2014/03/19 职场文书
岗位聘任书范文
2014/03/29 职场文书
初中班主任经验交流材料
2014/05/16 职场文书
知识改变命运演讲稿
2014/05/21 职场文书
2015年爱国卫生月活动总结
2015/03/26 职场文书
英文产品推荐信
2015/03/27 职场文书
教师病假条范文
2015/08/17 职场文书
Java org.w3c.dom.Document 类方法引用报错
2021/08/07 Java/Android