1. 程式人生 > >爬取分析拉勾網招聘資訊

爬取分析拉勾網招聘資訊

[TOC]

愛寫bug(ID:icodebugs)

作者:愛寫bug

前言:

​ 看了很多網站,只發現獲取拉勾網招聘資訊是隻用post方式就可以得到,應當是非常簡單了。推薦剛接觸資料分析和爬蟲的朋友試一下。

在python3.7、acaconda3環境下執行通過

資料爬取篇:

1、偽造瀏覽器訪問拉勾網

開啟Chrome瀏覽器,進入拉勾網官網,右鍵->檢查,調出開發者模式。

然後在拉勾網搜尋關鍵詞 演算法工程師 回車,然後點選下一頁、下一頁,此時開發者工具裡的NetworkXHR(表示該網站是以Ajax方式獲取重新整理資訊的)應當如下圖(圖中已標明瞭一些關鍵資訊): request_info.png

每次點選下一頁圖中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 構造請求頭偽造成瀏覽器訪問:

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表示當前頁數:

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)

連線成功!

2、獲取招聘資料

然後解析返回的 json 物件。我們先在開發者工具裡把 PositionAjax 項的 Headers 改到 Preview 看一下Chrome幫我們格式化好的 json 內容: job_info

出現了,我們想要的資料 在 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')

資料圖片:

lagou_data_mod.png

資料分析篇:

1、資料清洗:

​ 我們獲得的資料都是以字串形式儲存的,而且像工資(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檔案(你需要先存到本地才能看得到)會多兩列 平均經驗 和 平均工資:

lagou_data_mod.png

2、資料視覺化:

由於本篇為基礎篇只畫兩個最簡單的圖且不做過多渲染美化,資料視覺化都是一些簡單的繪圖,只有一箇中文顯示亂碼問題,其他並沒有什麼坑,所以不做過多描述。

解決中文亂碼問題:

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()

lagou_algorithm_salary.jpg

平均工作經驗要求直方圖(程式碼與上面相似,省略):

lagou_algorithm_work_year.jpg

學歷要求餅狀圖:

# 繪製學歷要求餅圖
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()

china_map.jpg

繪製福利待遇詞雲:

這裡要注意一下,上面設定的全域性顯示字型僅對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()

這裡詞雲背景指定為中國地圖: china_map.jpg

公司福利詞雲最終效果圖: 愛寫bug.png

總結:

​ 本文面向新手,文中不可避免有一些設定不合理的問題(資料量過少、工資取平均值代表不了實際情況),但還是可以從一定程度上反映出這個崗位的待遇和工資水平。

工資絕大部分集中在 2萬到3萬之間真的是相當高了。不過要求也不低,在多年的工作經驗要求下,依然要求碩士畢業學歷的公司依然佔比 33%。相信過不了多久,本科和碩士的學歷要求佔比就會換一下位置了。五(六)險一金是開的最多的福利待遇,算是公司準則了。現在公司都流行用彈性工作、氛圍什麼的精神福利來招人了麼。

所有原始碼及地圖素材:https://github.com/zhangzhe532/icodebugs/tree/master/DataAnalysis/lagou_data_Analysis

注:

文章主要參考:

網站反爬機制日新月異,所以本文有較強的時效性,無法保證您在實踐時是否還可行.

所有資料、操作僅作學習交流,不會用於商業用途。