Python爬虫读书笔记——下载缓存(5)

为了支持缓存,需要修改之前编写的download函数,使其在URL下载前进行缓存检查。另外,需要把限速功能移至函数内部,只有在真正发生下载时才会触发限速,而在加载缓存时不会触发。

为了避免每次下载都要传入多个参数,我们借此机会将download函数重构为一个类,这样参数只需在构造方法中设置一次,就能在后续下载时多次复用。

支持缓存功能的代码实现:

class Downloader:
    def __init__(self,delay=5,user_agent='wswp',proxies=None,num_retries=1,cache=None):
        self.throttle=Throttle(delay)
        self.user_agent=user_agent
        self.proxies=proxies
        self.num_retries=num_retries
        self.cache=cache

    def __call__(self,url):
        result=None
        if self.cache:
            try:
                result=self.cache[url]
            except KeyError:
                #url不可以利用在cache中
                pass
            else:
                if self.num_retries>0 and 500<=result['code']<600:
                    #server error so ignore result from cache and re-download
                    result=None
        if result is None:
            #没有从cache中下载结果,所以仍然需要下载
            self.throttle.wait(url)
            proxy=random.choice(self.proxies) if self.proxies
                else None
            headers={'User-agent':self.user_agent}
            result=self.download(url,headers,proxy,self.num_retries)
            if self.cache:
                #在cache中保存结果
                self.cache[url]=result
            return result['html']
    def download(self,url,headers,proxy,num_retries,data=None):
        ...
    return{'html':html,'code':code}

前面代码中的Download类有一个比较有意思的部分,那就是 __call__ 特殊方法,在该方法中我们实现了下载前检查缓存的功能。 该方法首先会检查缓存是否已经定义。如果已经定义,则检查之前是否已经缓存了该URL。 如果该URL己被缓存,则检查之前的下载中是否遇到了服务端错误。最后,如果也没有发生过服务端错误,则表明该缓存结果可用。如果上述检查中的 任何一项失败,都需要正常下载该URL,然后将得到的结果添加到缓存中。

这里的 download方法和之前的download 函数基本一样, 只是在返回下载 的HTML 时额外返回了HTTP 状态码, 以便在缓存中存储错误码。 当然,如果你只需要一个简单的下载功能, 而不需要限速或缓存的话, 可以直接调用该方法, 这样就不会通过 __call__ 方法调用了。

而对于 cache 类, 我们可以通过调用 result= cache [url]从cache中加载数据,并通过 cache[url] =result 向cache中保存结果。 大家应该很熟悉这种便捷的接口写法, 因为这也是Python 内建字典数据类型的使用方式。为了支持该接口 ,我们的 cache 类需要定义__getitem__()和 __setitem__()这两个特殊的类方法。

此外,为了支持缓存功能, 链接爬虫的代码也需要进行一些微调,包括添加 cache 参数、 移除限速以及将 download 函数替换为新的类等, 如下面的 代码所示。

def link_crawler(...,cache=None):
    crawl_queue=[seed_url]
    seen={seed_url:0}
    num_urls=0
    rp=get_robots(seed_url)
    D=Downloader(delay=delay,user_agent=user_agent,proxies=proxies,num_retires=num_retries,cache=cache)
    while crawl_queue:
        url=crawl_queue.pop()
        depth=seen[url]
        #检查url通过robot.txt限制
        if rp.can_fetch(user_agent,url):
            html=D(url)
            links=[]

到目前为止, 这个网络爬虫的基本架构已经准备好了,下面就要开始构建实际的缓存了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值