Python爬蟲實戰入門六:提高爬蟲效率—併發爬取智聯招聘(轉載)
之前文章中所介紹的爬蟲都是對單個URL進行解析和爬取,url數量少不費時,但是如果我們需要爬取的網頁url有成千上萬或者更多,那怎麼辦?
使用for迴圈對所有的url進行遍歷訪問?
嗯,想法很好,但是如果url過多,爬取完所有的資料會不會太過於耗時了?
對此我們可以使用併發來對URL進行訪問以爬取資料。
一般而言,在單機上我們使用三種併發方式:
- 多執行緒(threading)
- 多程序(multiprocessing)
- 協程(gevent)
對於以上三種方法的具體概念解釋和說明,各位可以自行網上搜索瞭解,相信會比我解釋得清楚,所以在此就不對它們進行解釋說明了。
本系列文章有兩個重點,一個是實戰,一個是入門,既為實戰,理論性的東西就描述得比較少;既為入門,所講述的都是簡單易懂易操作的東西,高深的技術還請入門之後自行探索,那樣也會成長得更快。
那麼下面,開始併發爬取的實戰入門,以多程序為例,併發爬取智聯招聘的招聘資訊。
一、分析URL和頁面結構
1、搜尋全國範圍內職位名包含“Python”的職位招聘
我們不分職業類別、不分行業類別,工作地點選為全國,職位名為“Python”,對招聘資訊進行搜尋,結果如下圖:
我們注意圖中三個紅框的資訊:
- 搜尋結果的url結構;(構造url地址進行for迴圈遍歷)
- 搜尋結果的條數;(判斷url的數量)
- 採集的資訊的主體;(解析資料)
通過篩選url引數,我們確定了需要爬取的基本URL為:
http://sou.zhaopin.com/jobs/searchresult.ashx?jl=全國&kw=python&kt=3&p=2
其中
http://sou.zhaopin.com/jobs/searchresult.ashx 為請求地址和目錄
jl:工作地點引數
kw:搜尋的關鍵字
kt:以職位名搜尋
p:頁數
我們可以發現,除了頁數會變化之外,其餘的引數值都是固定的值。我們來確定一下搜尋結果的總頁數。
因為網頁上有提示一共有多少個職位滿足條件,我們拿總職位數除以單頁顯示的職位數量即可知道搜尋結果的頁數。
# coding:utf-8 import requests from bs4 import BeautifulSoup import re url = 'http://sou.zhaopin.com/jobs/searchresult.ashx?jl=全國&kw=python&p=1&kt=3' wbdata = requests.get(url).content soup = BeautifulSoup(wbdata, 'lxml') items = soup.select("div#newlist_list_content_table > table") count = len(items) - 1 # 每頁職位資訊數量 print(count) job_count = re.findall(r"共<em>(.*?)</em>個職位滿足條件", str(soup))[0] # 搜尋結果頁數 pages = (int(job_count) // count) + 1 print(pages)
結果返回每頁60條職位資訊,一共有14頁。
那麼我們的待爬取的url地址就有14個,url地址中引數p的值分別從1到14,這麼少的url,使用for迴圈也可以很快完成,但在此我們使用多程序進行演示。
二、在爬蟲中使用多程序
先上程式碼:
# coding:utf-8 import requests from bs4 import BeautifulSoup from multiprocessing import Pool def get_zhaopin(page): url = 'http://sou.zhaopin.com/jobs/searchresult.ashx?jl=全國&kw=python&p={0}&kt=3'.format(page) print("第{0}頁".format(page)) wbdata = requests.get(url).content soup = BeautifulSoup(wbdata,'lxml') job_name = soup.select("table.newlist > tr > td.zwmc > div > a") salarys = soup.select("table.newlist > tr > td.zwyx") locations = soup.select("table.newlist > tr > td.gzdd") times = soup.select("table.newlist > tr > td.gxsj > span") for name, salary, location, time in zip(job_name, salarys, locations, times): data = { 'name': name.get_text(), 'salary': salary.get_text(), 'location': location.get_text(), 'time': time.get_text(), } print(data) if __name__ == '__main__': pool = Pool(processes=2) pool.map_async(get_zhaopin,range(1,pages+1)) pool.close() pool.join()
結果如下:
因為除了使用了多程序之外,其他的程式碼與之前文章介紹的方法大同小異,所以在此只介紹一下多程序的核心程式碼:
from multiprocessing import Pool
multiprocessing是Python自帶的一個多程序模組,在此我們使用其Pool方法。
if __name__ == '__main__': pool = Pool(processes=2) pool.map_async(get_zhaopin,range(1,pages+1)) pool.close() pool.join()
- 例項化一個程序池,設定程序為2;
- 呼叫程序池的map_async()方法,接收一個函式(爬蟲函式)和一個列表(url列表)
如此,在爬蟲中使用多程序進行併發爬取就搞定了,更多高階、複雜強大的方法,還請各位參考其他文件資料。
文章版權所有:州的先生部落格,轉載必須保留出處及原文連結
原文地址:https://zmister.com/archives/90.html
智聯招聘已不能這樣取,本文給出了一個分析原始碼,取有用值的方法。