值得拿出來 看看的
多進程 爬取 (生產) , 解析 (消費) 網頁 同時進行,能夠做爲之後項目擴展使用
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()