目前公司做的爬虫,不管测试还是爬取都是从网络直接请求资源,在调试的时候个人感觉十分耗时间,效率太低。最近受到同事的启发,做一个本地缓存来提高速度。
添加中间件cache_middleware()
class cache_middleware(object):
conn_pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
def process_request(self, request, spider):
try:
c = self.get_conn()
md = hashlib.md5()
x = request.url.encode('utf-8')
md.update(x)
key = md.hexdigest()
result = c.get(key)
if result:
res = scrapy.http.TextResponse(url=request.url, status=200, headers=None, body=result, request=None, encoding='utf-8')
print '从本地缓存中取数据'
return res
except Exception as e:
print 'middleware:' + str(e)
pass
@classmethod
def get_conn(cls):
return redis.Redis(connection_pool=cls.conn_pool)
本地的缓存用的是redis,速度快哈,用了一个连接池,在程序启动的时候cache_middleware就会被实例化,所以将连接池的初始化放在了类里面,然后就是主要的函数process_request()这个函数,文档里面对于middleware的介绍是这样的
红色框的部分就是主要的,如果返回了一个response对象,它就不会去网络继续请求,而是直接返回,这里我就直接从redis中查询数据,如果查询到了数据,我就直接返回,这样就减少了网络请求的时间
接下来就是要在settings里面添加这个中间件
DOWNLOADER_MIDDLEWARES = {
'scrapy_crawler.middlewares.cache_middleware': 1,
}
最后就是在spider里面添加存储内容的代码,跑第一遍的时候还是会向网络请求(本地没有数据)
try:
c = cache_middleware.get_conn()
md = hashlib.md5()
x = original_url.encode('utf-8')
md.update(x)
key = md.hexdigest()
c.set(key, response.body)
except Exception as e:
print e
pass
大概的就是这样,那里有错误,或者可以优化的,欢迎大家指出!