Python实现生产者消费者模式(多线程爬虫)
1.多组件的Pipeline技术架构
复杂的事情一般都不会一下子做完,而是会分很多中间步骤一步步完成。
2.生产者消费者爬虫的架构
3.多线程数据通信的 queue.Queue
queue.Queue
可以用于多线程之间的、线程安全的数据通信。简单来说,线程安全指的是多个线程并发同时访问数据不会出现数据冲突。
# 导入import queue# 创建q = queue.Queue()# 添加元素q.put(item)# 获取元素item = q.get()# 查看元素的多少q.qsize()# 判空q.empty()# 判满q.full()
4.代码编写实现生产者消费者爬虫
基础版:blog_spider.py
import requestsfrom bs4 import BeautifulSoupurls = [f'/#{page}' for page in range(1, 51)]# 生产者def craw(url):r = requests.get(url)return r.text# 消费者def parse(html):soup = BeautifulSoup(html, "html.parser")links = soup.find_all("a", class_="post-item-title")return [(link["href"], link.get_text()) for link in links]if __name__ == "__main__":for result in parse(craw(urls[2])):print(result)
开始多线程爬虫。
import queueimport blog_spiderimport timeimport randomimport threading
生产者:将每一个连接获取的html文本
存入html_queue
。
def do_craw(url_queue: queue.Queue, html_queue: queue.Queue):while True:url = url_queue.get()html = blog_spider.craw(url)html_queue.put(html)# 打印相关日志print(threading.current_thread().name, f"craw {url}","url_queue.size=", url_queue.qsize())time.sleep(random.randint(1, 2))
消费者:解析html_queue
中的每一个html文本
,获取文章链接和标题,并存入文档中。
def do_parse(html_queue: queue.Queue, fout):while True:html = html_queue.get()results = blog_spider.parse(html)for result in results:fout.write(str(result) + "\n")# 打印当前线程名字print(threading.current_thread().name, f"results.size", len(results),"html_queue.size=", html_queue.qsize())time.sleep(random.randint(1, 2))
生产-消费:设置 3 个生产者进程,2 个消费者进程。
if __name__ == "__main__":url_queue = queue.Queue()html_queue = queue.Queue()for url in blog_spider.urls:url_queue.put(url)for idx in range(3):t = threading.Thread(target=do_craw, args=(url_queue, html_queue), name=f"craw{idx}")t.start()fout = open("02.data.txt", 'w')for idx in range(2):t = threading.Thread(target=do_parse, args=(html_queue, fout), name=f"parse{idx}")t.start()
控制台上的打印信息。
最后看一下写入到文本中的内容。