多程序抓取頁面
- 導入第三方thread包,定義一個程序池
- 将抓取的一級頁面放進程序池裡
- 啟動程序池,自定義用幾個程序來執行函數
- 在程序池中引入函數,定義download函數,執行二級抓取資料
- 退出線程
# import 先導入内置的庫,再導入第三方庫
import time
import threading
from queue import Queue
import lxml.etree
import requests
START_URL= 'http://qianmu.iguye.com/2018USNEWS世界大學排名'
# 啟動的線程數量
DOWNLOAD_LINE =
# 定義Queue,隊列,儲存等抓取的url
link_queue = Queue()
# 線程清單,儲存Thread對象
threads = []
download_pages =
def fetch(url, raise_err=True):
global download_pages
try:
# 使用requests抓取url
r = requests.get(url)
r.encoding = 'utf-8'
# 每讀取一個,加1,顯示已經讀取的資料
download_pages +=
return r.text
except Exception as e:
# 如果報錯則print出來
print(e)
else:
# 如果沒報錯,則檢查http的傳回碼是否正常
if raise_err:
r.raise_for_status()
def parse_university(html):
selector = lxml.etree.HTML(html)
title = selector.xpath('//*[@id="wikiContent"]/h1/text()')[]
# 列印大學名
print(title)
infobox = selector.xpath('//div[@class="infobox"]')[]
keys = infobox.xpath('./table//tr/td[1]/p//text()')
cols = infobox.xpath('./table//tr/td[2]')
values = [''.join(col.xpath('.//text()')) for col in cols]
# 用清單的形式循環出keys, values
for k, v in zip(keys, values):
print('%s:%s'%(k, v))
print('-' * )
# 線程執行這個函數,不退出,一直到link為空
def download():
while True:
# get阻塞方法
link = link_queue.get()
if link is None:
break
# 執行下載下傳、解析操作
parse_university(fetch(link))
# 向隊列發送完成任務的消息
link_queue.task_done()
print('remaining queue: %s' % link_queue.qsize())
if __name__ == '__main__':
start_time = time.time()
selector = lxml.etree.HTML(fetch(START_URL))
links = selector.xpath('//*[@id="content"]/table/tbody/tr/td/a/@href')
# 第一步,抓取第一個頁面放進Q裡面
for link in links:
# 加判斷,如果連結有錯,重新給附個連結
if not link.startswith('http://'):
link = 'http://qianmu.iguye.com/%s' % link
link_queue.put(link)
# 第二步,啟動線程
for i in range(DOWNLOAD_LINE):
t = threading.Thread(target=download)
t.start()
# 把讀入的内容
threads.append(t)
# 堵塞,前面的都執行完了之後,再執行他,然後退出程式
link_queue.join()
# 向隊列發送DOWNLOADER_NUM個None,以通知線程退出
for i in range(DOWNLOAD_LINE):
link_queue.put(None)
# 退出線程
for t in threads:
t.join()
# 計算抓取的耗時
cost_seconds = time.time() - start_time
print('download %s pages in %.2f seconds'%(download_pages, cost_seconds))