0
点赞
收藏
分享

微信扫一扫

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

sullay 2022-02-16 阅读 23


你好,我是悦创。

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

这个 URL Pool 就是一个 生产者-消费者模式

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

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


依葫芦画瓢,URLPool 就是这样的:

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

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


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


  • 往池子里面添加 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 这个类中进行管理。接着我们来实现网址池:



举报

相关推荐

0 条评论