[TOC]javascript
愛寫bug(ID:icodebugs)做者:愛寫bughtml
看了不少網站,只發現獲取拉勾網招聘信息是隻用post方式就能夠獲得,應當是很是簡單了。推薦剛接觸數據分析和爬蟲的朋友試一下。java
在python3.七、acaconda3環境下運行經過python
打開Chrome瀏覽器,進入拉勾網官網,右鍵->檢查,調出開發者模式。git
而後在拉勾網搜索關鍵詞 算法工程師
回車,而後點擊下一頁、下一頁,此時開發者工具裏的Network
下XHR
(表示該網站是以Ajax方式獲取刷新信息的)應當以下圖(圖中已標明瞭一些關鍵信息):
github
每次點擊下一頁圖中XHR下以PositionAjax
開頭的請求就會多一條,圖下方 Form Data
裏 page numberpn
就會增長1,網站地址:https://www.lagou.com/jobs/list_
+ 搜索關鍵詞 city=
+ 城市名稱 +&cl=false&fromSearch=true&labelWords=&suginput=
正則表達式
固然搜索關鍵詞是中文的話必定要 unicode 轉碼。這裏咱們以關鍵字爲算法工程師,地區爲全國 爲例,因此URL:算法
轉碼前: https://www.lagou.com/jobs/list_算法工程師?city=全國&cl=false&fromSearch=true&labelWords=&suginput= 轉碼後: https://www.lagou.com/jobs/list_%E7%AE%97%E6%B3%95%E5%B7%A5%E7%A8%8B%E5%B8%88?city=%E5%85%A8%E5%9B%BD&cl=false&fromSearch=true&labelWords=&suginput=
根據圖中 Request Headers
構造請求頭僞形成瀏覽器訪問:json
headers = { 'Accept': "application/json, text/javascript, */*; q=0.01", 'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36", 'Referer': "https://www.lagou.com/jobs/list_%E7%AE%97%E6%B3%95%E5%B7%A5%E7%A8%8B%E5%B8%88?city=%E5%85%A8%E5%9B%BD&cl=false&fromSearch=true&labelWords=&suginput=" }
而後根據圖中 Form Data
來構造表單,只有pn表示的當前所在頁數須要不斷改變,因此 pn
定義一個變量num表示當前頁數:api
form_data = { 'first': 'true', 'pn': num, 'kd': '算法工程師' }
而後試一下:
request=requests.post(url,data=form_data,headers=headers) print(request.text)
可是尷尬的是這個時候post請求得到的回覆是:
{"status":false,"msg":"您操做太頻繁,請稍後再訪問","clientIp":"182.245.65.138","state":2402}
因爲該網站的反爬措施,此時不管把請求頭構造的多好都沒用,哪怕用本地的Cookie。
因此咱們採用 Seesion 對話方式:
s = requests.Session() # 建立一個session對象 s.get(url_start, headers=headers, timeout=3) # 使用session維持同一個會話 cookie = s.cookies # 使用該會話的cookie response = s.post(url, data=form_data, headers=headers, cookies=cookie, timeout=3)
鏈接成功!
而後解析返回的 json 對象。咱們先在開發者工具裏把 PositionAjax
項的 Headers 改到 Preview 看一下Chrome幫咱們格式化好的 json 內容:
出現了,咱們想要的數據 在 content -> positionResult -> result
, 一共從0到14共15條信息,這對應了網站每頁現實的信息數。而最下面還有 totalCount: 16945
這是搜索該關鍵詞 算法工程師
下的總條目數。能夠根據這個算出一共有多頁的信息(16945 / 15)而不是網站上顯示的只有30頁。因爲時間關係,本次示例只獲取29頁數據。本次示例只獲取29頁數據。
def parse_page(job_json): job_list = job_json['content']['positionResult']['result'] company_info = [] for job in job_list: job_info = [] job_info.append(job['companyFullName'])#公司全稱 job_info.append(job['companySize'])#規模 job_info.append(job['financeStage'])#融資狀況 job_info.append(job['district'])#位置 job_info.append(job['positionName'])#職位 job_info.append(job['workYear'])#工做經驗要求 job_info.append(job['education'])#學歷 job_info.append(job['salary'])#工資 job_info.append(job['positionAdvantage'])#福利待遇 company_info.append(job_info)#把全部職位狀況添加到網頁信息page_info return company_info
咱們就把每一個公司的各種招聘狀況存儲在 company_info
裏了。
最後把全部 company_info
彙總在一塊兒:
result = parse_page(job_json) all_company += result # 全部公司招聘信息匯在一塊兒
接着以CSV格式存儲在本地:
path = 'A:\Temp\\' # 指定csv數據存儲路徑 df.to_csv(path + 'lagou_algorithm_data.csv', index=False) print('保存路徑:' + path + 'lagou_algorithm_data.csv')
數據圖片:
](https://upload-images.jianshu...
咱們得到的數據都是以字符串形式存儲的,並且像工資(20k—30k)、工做經驗(3—5年)都是以區間的形式表現出來的,應該求其平均值(工資25k,工做經驗4年)。另外像工做經驗 不限、應屆畢業生等,咱們應該把該公司要求年限 改成0。
pattern = '\d+' # 正則表達式-匹配連續數字 # 統計每一個公司的平均經驗要求 lagou_data['平均經驗'] = lagou_data['經驗'].str.findall( pattern) # findall查找全部['經驗']下的數字字符串 avg_work_year = [] for i in lagou_data['平均經驗']: if len(i) == 0: # 長度爲0則意爲着沒數字,既工做經驗爲不限、應屆畢業生等,即沒有工做經驗要求 avg_work_year.append(0) else: # 匹配的是兩個數值的工做經驗區間 幾年到幾年,, year_list = [int(j) for j in i] # 獲得每個數轉爲int型 avg_year = sum(year_list)/2 # 求工做區間的平均值,平均年限 avg_work_year.append(avg_year) lagou_data['平均經驗'] = avg_work_year # 統計每一個公司給出的平均工資 lagou_data['平均工資'] = lagou_data['工資'].str.findall(pattern) avg_salary = [] for k in lagou_data['平均工資']: salary_list = [int(n) for n in k] salary = sum(salary_list)/2 avg_salary.append(salary) lagou_data['平均工資'] = avg_salary # 新列一項平均工資
存儲的csv文件(你須要先存到本地才能看獲得)會多兩列 平均經驗 和 平均工資:
因爲本篇爲基礎篇只畫兩個最簡單的圖且不作過多渲染美化,數據可視化都是一些簡單的繪圖,只有一箇中文顯示亂碼問題,其餘並無什麼坑,因此不作過多描述。
解決中文亂碼問題:
plt.rcParams['font.sans-serif'] = ['SimHei'] # 替換sans-serif字體顯示中文 plt.rcParams['axes.unicode_minus'] = False # 解決座標軸負數的負號顯示問題
# 繪製工資頻率直方圖 plt.hist(lagou_data['平均工資'], alpha=0.8, color='steelblue') plt.xlabel('工資/千元') plt.ylabel('頻數') plt.title("算法工程師平均工資直方圖") plt.savefig(path+'lagou_algorithm_salary.jpg') # 指定保存路徑 plt.show()
# 繪製學歷要求餅圖 count = lagou_data['學歷'].value_counts() plt.pie(count, labels=count.keys(), shadow=True,autopct='%2.2f%%') plt.savefig(path+'lagou_algorithm_education.jpg') plt.show()
這裏要注意一下,上面設置的全局顯示字體僅對matplotlib
,有效,因此這裏要指定一下字體防止中文亂碼。
# 繪製福利待遇詞雲 color_mask = imread(path+'china_map.jpg') strs = '' for line in lagou_data['福利']: strs += line # 鏈接全部字符串 cut_strs = ' '.join(jieba.cut(strs)) # 使用中文分詞jieba,將字符串分割成列表 word_cloud = WordCloud(font_path='C:\Windows\Fonts\微軟雅黑\msyh.ttc',mask=color_mask,background_color='white').generate(cut_strs) # 指定顯示字體避免中文亂碼 word_cloud.to_file(path+'lagou_algorithm_wordcloud.jpg') # 存儲圖片 plt.imshow(word_cloud) plt.show()
這裏詞雲背景指定爲中國地圖:
公司福利詞雲最終效果圖:
本文面向新手,文中不可避免有一些設置不合理的問題(數據量過少、工資取平均值表明不了實際狀況),但仍是能夠從必定程度上反映出這個崗位的待遇和工資水平。
工資絕大部分集中在 2萬到3萬之間真的是至關高了。不過要求也不低,在多年的工做經驗要求下,依然要求碩士畢業學歷的公司依然佔比 33%。相信過不了多久,本科和碩士的學歷要求佔比就會換一下位置了。五(六)險一金是開的最多的福利待遇,算是公司準則了。如今公司都流行用彈性工做、氛圍什麼的精神福利來招人了麼。
全部源代碼及地圖素材:https://github.com/zhangzhe532/icodebugs/tree/master/DataAnalysis/lagou_data_Analysis
文章主要參考:
網站反爬機制突飛猛進,因此本文有較強的時效性,沒法保證您在實踐時是否還可行.
全部數據、操做僅做學習交流,不會用於商業用途。