URL管理器的实现
新建一个python软件包文件夹,名为utils,意为一些常用的工具,并在该文件夹下新建一个名为url_manager的python脚本。
输入以下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
class Url_Manager():
"""
URL管理器的实现
"""
def __init__(self):
self.new_urls = set()
self.old_urls = set()
def add_new_url(self, url):
if url is None or len(url) == 0:
return
if url in self.new_urls or url in self.old_urls:
return
self.new_urls.add(url)
def add_new_urls(self, urls):
if urls is None or len(urls) == 0:
return
for url in urls:
self.add_new_url(url)
def get_url(self):
if self.has_new_url():
new_url = self.new_urls.pop()
self.old_urls.add(new_url)
return new_url
else:
return None
def has_new_url(self):
return len(self.new_urls) > 0
if __name__ == "__main__":
url_manager = Url_Manager()
url_manager.add_new_url("http://www.baidu.com")
url_manager.add_new_url("http://www.sina.com")
print(url_manager.new_urls, url_manager.old_urls)
print("#"*30)
print(url_manager.has_new_url())
print("#" * 30)
print(url_manager.get_url())
print("#" * 30)
print(url_manager.get_url())
print("#" * 30)
print(url_manager.get_url())
print("#" * 30)
print(url_manager.has_new_url())
print("#" * 30)
print(url_manager.new_urls, url_manager.old_urls)
简单解释一下各个函数的功能:
1
2
3
def __init__(self):
self.new_urls = set() # 待爬取URL
self.old_urls = set() # 已爬取URL
这个函数是Python类的初始化构造函数,我们这里为这个类创建两个新的set容器,分别用于已爬取和未爬取的URL。
1
2
3
4
5
6
def add_new_url(self, url):
if url is None or len(url) == 0:
return
if url in self.new_urls or url in self.old_urls:
return
self.new_urls.add(url)
这个函数是新增一条URL。但是注意,我们为了实现防止重复爬取、循环爬取,需要对新来的URL进行判断,看看它是否在待爬取或已爬取的URL的集合中。
1
2
3
4
5
def add_new_urls(self, urls):
if urls is None or len(urls) == 0:
return
for url in urls:
self.add_new_url(url)
这个函数是新增多条URL。其实现是使用for-each循环遍历urls里面的所有URL,并一条一条调用add_new_url()的方法,这样提高了代码的复用性。
1
2
def has_new_url(self):
return len(self.new_urls) > 0
这个函数是用于判断是否还有未爬取的URL,只需判断待爬取URL集合的长度是否大于0即可。该函数返回一个布尔变量。
1
2
3
4
5
6
7
def get_url(self):
if self.has_new_url():
new_url = self.new_urls.pop()
self.old_urls.add(new_url)
return new_url
else:
return None
这个函数是取出一条URL,但是在此之前我们需要先判定待爬取的URL中不为空,我们才能取出一条返回。取出后,我们要在待爬取URL的集合中删去这个URL,并将其添加到已爬取URL的集合中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
if __name__ == "__main__":
url_manager = Url_Manager()
url_manager.add_new_url("http://www.baidu.com")
url_manager.add_new_url("http://www.sina.com")
print(url_manager.new_urls, url_manager.old_urls)
print("#"*30)
print(url_manager.has_new_url())
print("#" * 30)
print(url_manager.get_url())
print("#" * 30)
print(url_manager.get_url())
print("#" * 30)
print(url_manager.get_url())
print("#" * 30)
print(url_manager.has_new_url())
print("#" * 30)
print(url_manager.new_urls, url_manager.old_urls)
最后段代码是测试用例,仅在该文件(url_manager.py)是作为主程序入口时才运行的一段程序。输出结果如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
{'http://www.baidu.com', 'http://www.sina.com'} set()
##############################
True
##############################
http://www.baidu.com
##############################
http://www.sina.com
##############################
None
##############################
False
##############################
set() {'http://www.baidu.com', 'http://www.sina.com'}
可以看到,执行两次get_url()方法后,我们两条待爬取的URL都被移动到已爬取URL集合中。