02-大规模异步新闻爬虫:实现功能强大、简洁易用的网址池(URL Pool)

你好,我是悦创。

对于比较大型的爬虫来说,URL 管理的管理是个核心问题,管理不好,就可能重复下载,也可能遗漏下载。这里,我们设计一个 URL Pool 来管理 URL 。
这个 URL Pool 就是一个 生产者-消费者模式

在这里插入图片描述
依葫芦画瓢,URLPool 就是这样的:
在这里插入图片描述

我们从网址池的使用目的出发来设计网址池的接口,它应该具有以下功能:

  • 往池子里面添加 URL;
  • 从池子里面取 URL 以下载;
  • 池子内部要管理 URL 状态;

前面我提到 URL 的状态有以下 4 中:

  • 已经下载成功
  • 下载多次失败无需再下载
  • 正在下载
  • 下载失败要再次尝试

前两个是永久状态,也就是已经下载成功的不再下载,多次尝试后仍失败的也就不再下载,它们需要永久存储起来,以便爬虫重启后,这种永久状态记录不会消失,已经成功下载的 URL 不再被重复下载。永久存储的方法有很多种:

  • 比如,直接写入文本文件,但它不利于查找某个 URL 是否已经存在文本中;
  • 比如,直接写入 MySQL 等关系型数据库,它利用查找,但是速度又比较慢;
  • 比如,使用 key-value 数据库,查找和速度都符合要求,是不错的选择!

我们这个 URL Pool 选用 redis 来作为 URL 状态的永久存储。

UrlDB 的实现

# -*- coding: utf-8 -*-
# @Time    : 2021/5/17 2:41 下午
# @Author  : AI悦创
# @FileName: UrlDB.py
# @Software: PyCharm
# @Blog    :https://www.aiyc.top
# @公众号   :AI悦创
from redis import Redis


class UrlDB(object):
    '''
    Use redis to store URLs what have been done(succeed or faile)
    '''
    status_failure = b'0'
    status_success = b'1'

    def __init__(self, db_name):
        self.name = db_name
        self.db = Redis(host='localhost', port=6379, db=self.name)

    def set_success(self, url):
        """
        请求成功的 url
        """
        if isinstance(url, str):
            url = url.encode('utf8')
        try:
            self.db.set(url, self.status_success)
            s = True
        except:
            s = False
        return s

    def set_failure(self, url):
        """
        请求失败的 url
        """
        if isinstance(url, str):
            url = url.encode('utf8')
        try:
            self.db.set(url, self.status_failure)
            s = True
        except:
            s = False
        return s

    def has(self, url):
        """
        判断我们的 url 是否存在
        """
        if isinstance(url, str):
            url = url.encode('utf8')
        try:
            # attr = self.db.get(url)
            attr = self.db.exists(url)
            return attr
        except:
            pass
        return False

UrlDB 将被 UrlPool 使用,主要有三个方法被使用:

  • has(url) 查看是否已经存在某 url
  • set_success(url) 存储 url 状态为成功
  • set_failure(url) 存储 url 状态为失败

UrlPool 的实现

而正在下载和下载失败次数这两个 URL 的状态只需暂时保存在内容即可,我们把它们放到 UrlPool 这个类中进行管理。接着我们来实现网址池:

AI悦创·推出辅导班啦,包括「Python 语言辅导班、C++辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发」,全部都是一对一教学:一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。QQ、微信在线,随时响应!V:Jiabcdefh
AI悦创 » 02-大规模异步新闻爬虫:实现功能强大、简洁易用的网址池(URL Pool)

2 评论

发表评论