一、并發(fā)爬取數(shù)據(jù)
當我們需要爬取的 url 鏈接非常多的時候腿准,用 for 循環(huán)對所有鏈接進行訪問顯然是非常耗時的。
怎么提高爬蟲效率呢?
我們可以使用并發(fā)來對URL進行訪問以爬取數(shù)據(jù)翅溺。
有以下三種并發(fā)方式
- 多線程(threading)
- 多進程(multiprocessing)
- 協(xié)程(gevent)
先來試試多進程
二、 多線程example
import requests
import time
from multiprocessing.dummy import Pool
def get_url(url):
html = requests.get(url)
#print(html.url)
urls = ["http://www.mmjpg.com/home/{}".format(i) for i in range(1,40)]
time1 = time.time()
for url in urls:
get_url(url)
time2 = time.time()
print('單線程耗時' + str(time2 - time1))
pool = Pool(4)
time3 = time.time()
results = pool.map(get_url, urls)
pool.close()
pool.join()
time4 = time.time()
print('多線程耗時' + str(time4 - time3))
先來試試請求 40 個網(wǎng)頁分別的耗時
>>>
=================== RESTART: E:\Python項目\爬阿爬\多線程髓抑,進程\多進程.py ===================
單線程耗時3.8298497200012207
多線程耗時3.5330474376678467
差別不是太大咙崎,但請求100呢。把 range 的范圍改到 100吨拍,再運行試試
=================== RESTART: E:\Python項目\爬阿爬\多線程褪猛,進程\多進程.py ===================
單線程耗時16.267414093017578
多線程耗時4.5447304248809814
>>>
差距已經(jīng)很大了
三、多線程爬取
我們以爬取 實驗樓 的課程為例羹饰。
分析下url伊滋,可以發(fā)現(xiàn)改變 page 的參數(shù)就可以切換頁數(shù)了,那么共有幾頁呢队秩,我們只需爬取頁面下方的這個系列的數(shù)值新啼,倒二個就是最大的頁面數(shù)。
代碼如下
>>> link = 'https://www.shiyanlou.com/courses/?course_type=all&tag=all&fee=all&page=1'
>>> r = requests.get(link)
>>> bs0bj = BeautifulSoup(r.text, 'lxml')
>>> pages = bs0bj.select('body > div.container.layout-hasside.layout-margin-top > div.row > div.col-md-9.layout-body > div.content.position-relative > nav > ul > li')
>>> page = int(pages[-2].text.strip())
>>> print('共{}頁'.format(page))
共24頁
我們來爬取所有課程的名稱 title刹碾, 說明 introduce 燥撞,熱度 num。
如果要爬取別的課程只需改下 url 的 tag 參數(shù)就行
總的代碼如下
import requests
from bs4 import BeautifulSoup
from multiprocessing.dummy import Pool
def get_html(page):
url = 'https://www.shiyanlou.com/courses/?course_type=all&tag=all&fee=all&page={}'.format(page)
print('第{}頁'.format(page))
html = requests.get(url)
soup = BeautifulSoup(html.text, 'lxml')
titles = soup.find_all(class_='course-name')
introduces = soup.find_all(class_='course-desc')
nums = soup.find_all(class_='course-per-num pull-left')
for title, num, introduce in zip(titles, nums, introduces):
data = {
'title' : title.get_text(),
'num' : num.get_text().strip(),
'introduce' : introduce.get_text()
}
print(data)
if __name__ == '__main__':
link = 'https://www.shiyanlou.com/courses/?course_type=all&tag=all&fee=all&page=1'
r = requests.get(link)
bs0bj = BeautifulSoup(r.text, 'lxml')
pages = bs0bj.select('body > div.container.layout-hasside.layout-margin-top > div.row > div.col-md-9.layout-body > div.content.position-relative > nav > ul > li')
page = int(pages[-2].text.strip())
print('共{}頁'.format(page))
pool = Pool(4)
pool.map(get_html, range(1, page+1))
#pool.map_async(get_html, range(1, page+1))
#for i in range(page+1):
#pool.apply(func=get_html, args=(i,))
pool.close()
pool.join()
運行下試試看
>>>
================== RESTART: C:\Users\Why Me\Desktop\爬實驗樓.py ==================
共24頁
第1頁第3頁第5頁第7頁
{'num': '536', 'introduce': '本課將介紹 json 和一些常見的 json 庫迷帜,并用 C++ 編寫一個 json 生成器物舒,生成 json 數(shù)據(jù),并學習編寫測試用例戏锹。', 'title': 'C++ 編寫 json 生成器'}{'num': '112', 'introduce': '本訓練營主要講后門技術(shù)實戰(zhàn)冠胯,偏重于滲透成功后的維持訪問。該課程共包含 10 個實驗锦针,每個實驗都提供詳細的步驟和截圖荠察,其中會有專門的三節(jié)實驗,專門用來講解木馬的制作奈搜,以及對生成的后門木馬的源碼分析 悉盆。', 'title': 'Kali 滲透測試 - 后門技術(shù)實戰(zhàn)(10個實驗)'}
{'num': '467', 'introduce': '在這個人人自拍的年代,每個人的智能手機中至少都裝了一款美顏相機或者美圖軟件馋吗,而這些軟件實現(xiàn)美圖功能又主要是靠濾鏡來實現(xiàn)的焕盟。而這門課程將帶領(lǐng)大家使用 Python 編寫一個簡單的濾鏡程序。', 'title': 'Python 實現(xiàn)簡單濾鏡'}{'num': '1381', 'introduce': '出租車是我們生活中經(jīng)常乘坐的一種交通工具宏粤,但打車難的問題也限制了我們更好地利用這種交通方式脚翘。在哪些地方出租車更容易打到灼卢?在什么時候更容易打到出租車?本課程將基于某市的出租車行駛軌跡數(shù)據(jù)来农,帶你學習如何應用Spark SQL和機器學習相關(guān)技巧鞋真,并且通過數(shù)據(jù)可視化手段展現(xiàn)分析結(jié)果。', 'title': '大數(shù)據(jù)帶你挖掘打車的秘籍'}
...
...