用装饰器实现了一个为现有爬虫实现本地缓存功能的模块,只需要引入这个spidercache.py文件,然后在爬虫下载文件的方法顶部添加@cache(cachetime=3600)
即可,唯一的参数就是缓存过期时间(秒)。代码兼容py2和py3。
爬虫下载文件的方法必须是传入一个地址,输出文本或者字节内容,下面案例方法是返回的是处理后的title,那么缓存的也同样是title。如果直接返回的是html,那么就是缓存整个html文件。
爬虫运行后会自动在当前目录下创建.cache文件夹存放缓存。
使用案例:
spider.py
import requests
import re
from spidercache import cache
@cache(cachetime=3600)
def get_html(url):
r = requests.get(url)
r.encoding = 'utf8'
html = r.text
reg = re.compile(r'<title>(.*?)</title>',re.S)
title = reg.search(html).group(1)
return title
title = get_html('http://www.baidu.com')
print(title)
spidercache.py
# -*- coding: utf-8 -*-
# Copyright (c) 2017 - walker <cail1844@gmail.com>
import hashlib
import os
from functools import wraps
import codecs
import time
def cache(cachetime):
def decorator(func):
@wraps(func)
def wrapper(*args):
url = args[0]
hash = hashlib.md5()
hash.update(url.encode('utf8'))
md5 = hash.hexdigest()
cachedir = os.path.join('.cache',md5[0:2],md5[2:4])
cachepath = os.path.join('.cache',md5[0:2],md5[2:4],md5)
try:
mtime = os.path.getmtime(cachepath)
if time.time() - mtime > cachetime:
raise Exception('cache time expired')
else:
print(url,'read cache')
with codecs.open(cachepath,'r','utf8') as f:
data = f.read()
return data
except Exception as e:
print(url,'get content from internet',e)
if not os.path.exists(cachedir):
os.makedirs(cachedir)
data = func(url)
with codecs.open(cachepath,'w+','utf8') as f:
f.write(data)
return data
return wrapper
return decorator