python 生產者 --- 消費者

值得拿出來 看看的

多進程 爬取 (生產) , 解析 (消費) 網頁 同時進行,能夠做爲之後項目擴展使用

from bs4 import BeautifulSoup
import requests
import time
import multiprocessing as mp
import re
from multiprocessing import Queue
# from multiprocessing import JoinableQueue as Queue

base_url = 'https://morvanzhou.github.io/'

def crawl(url):
    html = requests.get(url).text
    # 模擬請求時間消耗 0.1 s
    time.sleep(0.1)
    return html

def parse(html):
    soup = BeautifulSoup(html,'lxml')
    all_anchors = soup.find_all('a',{'href':re.compile(r'^/.+?/$')})
#     title = soup.find('meta',{'property':'og:title'})
    page_urls = {anchor.get_text().strip():base_url+anchor['href'] for anchor in all_anchors}
    main_url = soup.find('meta',{'property':'og:url'})['content']
    return main_url,page_urls
    
# print(html)

def main():
    # unseen 本能夠定義多個
    unseen = (base_url,)
    seen = ()
    
    # 爲了讓 html 爬取 與 html 解析 同步進行,因此這裏使用 生產者--消費者 模式
    html_queue = Queue()
    # 開啓進程池
    # 生產者 即 html 爬取
    crawl_pool = mp.Pool(2)
    # 消費者 即 html 解析
    parse_pool = mp.Pool(2)
    
    
    for url in unseen:
        # 若一直 有 要被爬取的 html 則 一直進行
        html_queue.put(crawl_pool.apply_async(crawl,args=(url,)).get()) 
    else:
        # 已經爬取完成全部 頁面
        html_queue.put(None) # 此處向隊列發送 生產完成信號,否則方法一直被阻塞
    
    results = []
    
    # 開啓循環 消費生產出的 html,對其進行解析
    while True:
        html=html_queue.get()
        if html:
            results.append(parse_pool.apply_async(parse,args=(html,)).get())
        else:
#             html_queue.task_done()
            break
        
    print(results)
    
if __name__ == '__main__':
    main()
相關文章
相關標籤/搜索