利用python分析2018智聯招聘全國各個城市的職位數排名
新年快到了,工作了一年你,躺在床上,退下一身的疲怠,是否也曾嚮往去到一個新的城市工作和生活呢?
那中國除了公認的北上廣深工作機會最多以外,還有那些城市也相對不錯呢?
這時候我們可能會開啟招聘網站開始選擇城市然後來了解這個城市的職位情況.
那麼一直秉持著人生苦短,我學python的我們,為什麼不能用python來寫一個分析2018全國各個城市的職位數排名的爬蟲指令碼呢?
這麼一想十分可行啊,我們只需要找到一個目標招聘平臺,然後通過用程式碼get到它的html正文,通過BeautifulSoup分析html來得到我們想要的資料,然後用matplotlib畫出圖表就可以了. (完整程式碼見本文末尾.)
於是立馬動手,首先,既然我們是要分析全國範圍內的所有城市的職位數,那麼我們肯定首先要把所有的城市先列出來.然而這裡想必地理學的再好的同學也不可能能把全國範圍內所有的城市都能背下來吧,所以這一步,我們也是用python來爬取到全國範圍內所有的城市名稱.
1.爬取全國範圍內所有的城市列表
乍一看好像所有的城市名都是加粗的,右鍵檢視一下原始碼,果然,所有的城市名都被加上了<strong>
標籤,類似於這樣
那就簡單了,我們直接獲取該網頁所有<strong>
標籤裡面的內容,就是標籤名了.程式碼:
def getCitys(citys) :
urlPath = "http://www.zhaopin.com/citymap.html"
print("開始爬取所有城市:")
r = requests.get(urlPath)
if r.ok:
r.raise_for_status()
r.encoding = 'utf-8'
data = r.text
print("目標url:", urlPath)
soup = BeautifulSoup(data, 'html.parser')
a = soup.find_all('strong' )
for i in a:
try:
citys.append(i.contents[0])
except:
continue
else:
print("城市獲取失敗!")
這樣我們就獲取到了所有的城市名,下一步我們就是要通過遍歷這些城市名來查詢某一個職業的職位數了.
2.遍歷城市名,爬取對應城市的職位數.
這時候我們先開啟智聯的搜工作頁面,輸入職位名”android”,地址選擇”煙臺”,然後點選搜工作,這時候注意到,瀏覽器的位址列變成了:
http://sou.zhaopin.com/jobs/searchresult.ashx?jl=煙臺&kw=android&p=1&isadv=0
原來,智聯的找工作這個按鈕是執行了一個get請求而已,其中jl=和&kw=
即分別代表要查詢的城市和職位關鍵字,這時候先不要著急寫程式碼,我們先來像上面說的一樣來分析一下這個頁面.
首先第一眼直接就找到了這樣的字眼
上面赫然顯示著共84個職位滿足條件,一切總是那麼完美,不需要多餘的任何操作,彷彿傳到橋頭自然直一樣,這不正是我們想要找的職位數嗎.然後右鍵選擇檢視原始碼.恩,不得不說相當完美!
但這次資料格式好像比較複雜一點,我們如果僅僅簡單用<em>84</em>
標籤包裹的內容來獲取職位數的話好像已經行不通了,因為該網頁很多的地方也使用了<em>
標籤,那怎麼辦呢,這時候我們只能使用正則表示式來匹配了.
修修改改,最終的正則表示式是這樣的:(?!共<em>)[0-9]+(?=</em>個職位滿足條件)
,其中的?!和?=則是讓其所在的括號內的內容不放入匹配緩衝區裡.
好,接下來我們就可以結合以上的內容來寫程式碼了.
import re
import requests
zhilianUrl = "http://sou.zhaopin.com/jobs/searchresult.ashx?jl=煙臺&kw=android&p=1&isadv=0"
r = requests.get(zhilianUrl)
if r.ok:
r.raise_for_status()
r.encoding = 'utf-8'
rr = r'(?!共<em>)[0-9]+(?=</em>個職位滿足條件)'
a = re.findall(rr, r.text, 0)
print(a)
else:
print("職位數獲取失敗!")
寫完趕緊興沖沖的run一下,…然而…
結果是執行沒有報錯也沒有任何輸出,左邊的紅色方塊顯示程式還在執行中,是的,它卡住了,停止執行再重新start還是會卡主,檢查一下程式也沒問題啊,what?辛辛苦苦才到達了這步救過竟然卡住了?這個時候我們不要著急,身為一個整天跟各種BUG打交道的程式設計師,一定要鎮定,努力分析問題可能的原因,然後解決問題.
繼續回到我們的這個問題上,排除我們程式本身的問題,會不會是對方的網站早知道我們會寫python爬取,故意給我們加了限制呢?於是我們給我們的這次訪問加上一個請求頭試試,讓我們的這次請求偽裝成來自瀏覽器的訪問.
ok,改程式碼,給這次get請求加上一個請求頭:
import re
import requests
headers = {
'Host': 'blog.csdn.net',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
'Accept-Encoding': 'gzip, deflate',
'Referer': 'http://www.baidu.com',
'Connection': 'keep-alive',
'Cache-Control': 'max-age=0',
}
zhilianUrl = "http://sou.zhaopin.com/jobs/searchresult.ashx?jl=煙臺&kw=android&p=1&isadv=0"
r = requests.get(zhilianUrl, headers=headers)
if r.ok:
r.raise_for_status()
r.encoding = 'utf-8'
rr = r'(?!共<em>)[0-9]+(?=</em>個職位滿足條件)'
a = re.findall(rr, r.text, 0)
print(a)
else:
print("城市獲取失敗!")
執行:
F:\PythonPoj\PythonLearn\venv\Scripts\python.exe F:/PythonPoj/PythonLearn/test.py
['84']
Process finished with exit code 0
果然這下就沒問題了,程式瞬間就成功獲取到了職位數為 84
繼續改動一下程式,遍歷所有的城市列表,並根據key=城市名,value=職位數
的格式將所有的城市職位數都獲取來存到一個字典(Dictionary)裡.
def getData(citys, data):
for city in citys:
headers = {
'Host': 'blog.csdn.net',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
'Accept-Encoding': 'gzip, deflate',
'Referer': 'http://www.baidu.com',
'Connection': 'keep-alive',
'Cache-Control': 'max-age=0',
}
zhilianUrl = "http://sou.zhaopin.com/jobs/searchresult.ashx?jl=" + city + "&kw=" + zhiwei + "&p=1&isadv=0"
r = requests.get(zhilianUrl, headers=headers)
if r.ok:
r.raise_for_status()
r.encoding = 'utf-8'
rr = r'(?!共<em>)[0-9]+(?=</em>個職位滿足條件)'
a = re.findall(rr, r.text, 0)
if int(a[0]) >= 50 and hasCity(r):
print(city, zhiwei, a[0])
data[city] = int(a[0])
else:
print("城市獲取失敗!")
這樣我們就得到了這樣的資料:
{'北京': 4205, '上海': 2702, '廣州': 1442, '深圳': 1872, '天津': 536 ...}
使用matplotlib根據資料畫出圖表
通過上面我們獲取完了資料之後,直接用matplotlib庫畫出圖表來就可以直觀的看到各個城市的職位數情況了.
def draw(keys, values):
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用來正常顯示中文標籤
plt.rcParams['axes.unicode_minus'] = False # 用來正常顯示負號
time = i = datetime.datetime.now()
plt.title(str(time.year) + "/" + str(time.month) + "/" + str(time.day) + zhiwei + "職位數分佈圖")
plt.bar(keys, values, label="職位數")
plt.legend()
plt.show()
結果展示
程式執行:
執行結果:
還可以修改一下指令碼中的職位名,查詢其他職業:
本文出自: http://imaster.top
完整程式碼點此獲取
本文為作者原創,轉載請註明出處.