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 14 Python
Swift 3.0在集合类数据结构上的一些新变化总结
Jul 11 Python
Python 用Redis简单实现分布式爬虫的方法
Nov 23 Python
名片管理系统python版
Jan 11 Python
python对于requests的封装方法详解
Jan 03 Python
postman模拟访问具有Session的post请求方法
Jul 15 Python
python通过http下载文件的方法详解
Jul 26 Python
Python for循环及基础用法详解
Nov 08 Python
python使用beautifulsoup4爬取酷狗音乐代码实例
Dec 04 Python
python GUI库图形界面开发之PyQt5下拉列表框控件QComboBox详细使用方法与实例
Feb 27 Python
python 删除excel表格重复行,数据预处理操作
Jul 06 Python
python​格式化字符串
Apr 20 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
2020年4月放送决定!第2期TV动画《邪神酱飞踢》视觉图&主题曲情报公开!
2020/03/06 日漫
PHP开发中常用的三个表单验证函数使用小结
2010/03/03 PHP
php后台如何避免用户直接进入方法实例
2013/10/15 PHP
WebQQ最新登陆协议的用法
2014/12/22 PHP
php使用ffmpeg向视频中添加文字字幕的实现方法
2016/05/23 PHP
Thinkphp事务操作实例(推荐)
2017/04/01 PHP
php实现的PDO异常处理操作分析
2018/12/27 PHP
PHP实现获取ip地址的5种方法,以及插入用户登录日志操作示例
2019/02/28 PHP
javascript中的几个运算符
2007/06/29 Javascript
js 深拷贝函数
2008/12/04 Javascript
JavaScript 捕获窗口关闭事件
2009/07/26 Javascript
jquery中.add()的使用分析
2013/04/26 Javascript
jquery.validate的使用说明介绍
2013/11/12 Javascript
Javascript Ajax异步读取RSS文档具体实现
2013/12/12 Javascript
jQuery中的$.ajax()方法应用
2014/05/06 Javascript
javascript数据结构之二叉搜索树实现方法
2015/11/25 Javascript
浅谈js中的in-for循环
2016/06/28 Javascript
Bootstrap源码解读网格系统(3)
2016/12/22 Javascript
nodejs服务搭建教程 nodejs访问本地站点文件
2017/04/07 NodeJs
浅谈手写node可读流之流动模式
2018/06/01 Javascript
vue+element实现表单校验功能
2019/05/20 Javascript
Vue js with语句原理及用法解析
2020/09/03 Javascript
在vue中实现某一些路由页面隐藏导航栏的功能操作
2020/09/21 Javascript
python连接字符串的方法小结
2015/07/13 Python
python日期时间转为字符串或者格式化输出的实例
2018/05/29 Python
python抓取需要扫微信登陆页面
2019/04/29 Python
使用 python pyautogui实现鼠标键盘控制功能
2019/08/04 Python
解决python ThreadPoolExecutor 线程池中的异常捕获问题
2020/04/08 Python
Python常用数据分析模块原理解析
2020/07/20 Python
css3通过scale()、rotate()实现放大、旋转
2020/03/19 HTML / CSS
移动端开发HTML5页面点击按钮后出现闪烁或黑色背景的解决办法
2018/09/19 HTML / CSS
什么时候用assert
2015/05/08 面试题
计算机软件专业求职信
2014/06/10 职场文书
医院领导班子整改方案
2014/10/01 职场文书
2015年后备干部工作总结
2015/05/15 职场文书
Python可变与不可变数据和深拷贝与浅拷贝
2022/04/06 Python