python
复制代码
import threading
import time
import random
import queue
import blog_spider
# 定义生产者线程要执行的函数,用于从URL队列中获取URL,爬取网页内容并放入HTML队列
def do_craw(url_queue: queue.Queue, html_queue: queue.Queue):#url_queue: 存储待爬取URL的队列, html_queue: 用于存储爬取到的网页HTML内容的队列
"""
这个函数是生产者线程要执行的函数。
不断从URL队列中获取URL,调用blog_spider.craw函数爬取网页的内容,
然后将爬取到的HTML内容放入HTML队列中,并打印相关的内容。
"""
while True:
# 从URL队列中获取一个URL
url = url_queue.get()
# 调用blog_spider模块中的craw函数爬取该URL对应的网页内容
html = blog_spider.craw(url)
# 将爬取到的网页内容放入HTML队列
html_queue.put(html)
# 打印当前线程的名称、正在爬取的URL以及URL队列剩余的大小
print(threading.current_thread().name, f"craw {url}", "url_queue.size=", url_queue.qsize())
time.sleep(random.randint(1, 2))#休眠一段时间
# 定义消费者线程要执行的函数,用于从HTML队列中获取网页内容
def do_parse(html_queue: queue.Queue, fout):#html_queue: 存储网页HTML内容的队列
"""
此函数是消费者线程要执行的任务函数。
它会不断从HTML队列中获取网页内容,调用blog_spider.parse函数对其进行解析,fout: 用于写入解
析结果的文件对象
将解析结果写入到指定的文件中,并打印相关的内容。
"""
while True:
# 从HTML队列中获取一个网页内容
html = html_queue.get()
# 调用blog_spider模块中的parse函数对网页内容进行解析,得到解析结果
results = blog_spider.parse(html)
for result in results:
fout.write(str(result) + "\n")
# 打印当前线程的名称、解析结果的数量以及HTML队列剩余的大小
print(threading.current_thread().name, f"results.size", len(results), "html_queue_size=", html_queue.qsize())
time.sleep(random.randint(1, 2))#休眠一段时间
# 主程序入口,当脚本直接运行时执行以下代码
if __name__ == '__main__':
# 创建一个用于存储待爬取URL的队列
url_queue = queue.Queue()
# 创建一个用于存储爬取到的网页HTML内容的队列
html_queue = queue.Queue()
# 将blog_spider模块中定义的所有URL放入URL队列
for url in blog_spider.urls:
url_queue.put(url)
# 开启生产者线程
for idx in range(3):
# 创建一个新的线程,指定其执行的任务函数为do_craw,并传入相应的参数
t = threading.Thread(target=do_craw, args=(url_queue, html_queue), name=f"craw{idx}")
t.start()
# 开启消费者线程和创建用于存储解析结果的文本文件
fout = open("spider_data.txt", "w")
for idx in range(2):
# 创建一个新的线程,指定其执行的任务函数为do_parse,并传入相应的参数
t = threading.Thread(target=do_parse, args=(html_queue, fout), name=f"parse{idx}")
t.start()