在Python中,队列(Queue)是一种常用的数据结构,用于在多线程或多进程之间高效地传递数据。在网络爬虫的开发中,队列可以帮助我们管理待抓取的URL,实现生产者消费者模型,以提高爬虫的效率和稳定性。 以下是一个简单的使用队列实现生产者消费者模型的网络爬虫例子:

import threading
import time
from queue import Queue
from urllib.parse import urljoin
import requests
from bs4 import BeautifulSoup
# 生产者线程函数
def worker_producer(queue):
    base_url = "http://example.com/"
    # 生产一些URL放入队列中
    for i in range(10):
        url = urljoin(base_url, f'page_{i}')
        queue.put(url)
        print(f"生产者放入URL: {url}")
    queue.put(None)  # 表示生产结束,使用None作为特殊标记
# 消费者线程函数
def worker_consumer(queue):
    while True:
        url = queue.get()
        if url is None:
            break
        try:
            response = requests.get(url)
            soup = BeautifulSoup(response.text, 'html.parser')
            # 这里可以添加代码提取数据,打印或者保存
            print(f"消费者处理URL: {url}")
        except Exception as e:
            print(f"处理URL {url} 时出错: {e}")
        finally:
            queue.task_done()  # 标记任务完成
# 队列初始化
queue = Queue()
# 创建并启动生产者线程
producer_thread = threading.Thread(target=worker_producer, args=(queue,))
producer_thread.start()
# 创建多个消费者线程
consumer_threads = []
for i in range(3):  # 假设我们有三个消费者
    consumer_thread = threading.Thread(target=worker_consumer, args=(queue,))
    consumer_thread.start()
    consumer_threads.append(consumer_thread)
# 等待生产者线程完成任务
producer_thread.join()
# 通知消费者线程结束
for _ in consumer_threads:
    queue.put(None)
for consumer_thread in consumer_threads:
    consumer_thread.join()
print("爬虫结束")

在这个例子中:

  • worker_producer 函数是生产者线程的函数,它负责生成初始的URL并将它们放入队列中。
  • worker_consumer 函数是消费者线程的函数,它从队列中取出URL并模拟爬取网页的过程。
  • 使用threading.Thread创建多线程,分别启动生产者和消费者。
  • queue.get()用于从队列中获取URL,queue.put(None)用于标识生产结束。
  • 在消费者函数中,使用try-except块处理可能出现的异常,并在每个任务完成后调用queue.task_done()。 请根据实际情况调整爬虫逻辑和异常处理,确保遵守相关的法律法规和网站的robots.txt协议。