數(shù)據(jù)分析師薪酬?拉勾網(wǎng)職位爬取+分析

我是封面

——2018.06.01——
最近幾天看到了很多文章寫拉勾網(wǎng)職位爬取幢踏,那些基本是基于requests + json,但是貌似所給url打不開许师,還有可能被封ip的風(fēng)險房蝉。
本文主要用selenium + BautifulSoup + xpath工具,爬取不同城市的數(shù)據(jù)分析師薪酬微渠,閑話不多說搭幻,上菜。

  • 爬蟲 selenium + BautifulSoup + xpath
  • 儲存數(shù)據(jù) MySQL
  • 數(shù)據(jù)清理
  • 薪酬和職位需求分析 seaborn + pyecharts
    ——
    編譯環(huán)境:Python 3.5
    IDE:jupyter notebook

1.網(wǎng)頁爬取

第一步逞盆,導(dǎo)入所需的模塊:

import re
import time
import random
#爬蟲工具
from selenium import webdriver 
from selenium.webdriver.chrome.options import Options
#解析工具
from bs4 import BeautifulSoup
from lxml import etree

第二步檀蹋,設(shè)置瀏覽器參數(shù):

#設(shè)置無頭的chrome瀏覽器參數(shù)
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
#運(yùn)行瀏覽器
driver = webdriver.Chrome(chrome_options=chrome_options)
#備注::selenium 3.0+版本已不支持PhantomJS,所以這里使用無頭的chrome brower

第三步纳击,找到合適url開始爬蟲续扔,這里以長沙為例:

url = "https://www.lagou.com/jobs/list_數(shù)據(jù)分析師?px=default&city={}#filterBox".format('長沙')
driver.get(url)
time.sleep(3) #設(shè)置等待時間,強(qiáng)烈建議

第四步焕数,解析網(wǎng)頁

# BeautifulSoup解析獲取職位的福利和標(biāo)簽
s = BeautifulSoup(driver.page_source,'lxml')
labels=[]
treatment=[]
for i in s.findAll('div','list_item_bot'):
    labels.append(i.text.split('“')[0].strip().replace('\n',','))
    treatment.append(i.text.split('“')[1].strip().replace('”',''))
    
# xpath 工具獲取公司名稱、鏈接刨啸、id等其他數(shù)據(jù)
selector=etree.HTML(driver.page_source)
company_link=selector.xpath('//div[@class="company_name"]/a/@href')
company_name=selector.xpath('//div[@class="company_name"]/a/text()')
job_name =selector.xpath('//a[@class="position_link"]/h3/text()')
job_link = selector.xpath('//a[@class="position_link"]/@href')
address =selector.xpath('//span[@class="add"]/em/text()')
temp_1 =selector.xpath('//div[@class="p_bot"]/div[@class="li_b_l"]/text()')
salary = selector.xpath('//span[@class="money"]/text()')
temp_2 = selector.xpath('//div[@class="industry"]/text()')
treatment = selector.xpath('//div[@class="li_b_r"]/text()')
    
#利用自定義的分隔函數(shù)堡赔,得到所需的值
def spt(temp):
    list1,list2 = [],[]
    for i in temp:
        if i.strip():
            list1.append(i.split('/')[0].strip())
            list2.append(i.split('/')[1].strip())
    return list1,list2
experience,education = spt(temp_1)
industry,scale = spt(temp_2)
    
#從鏈接中獲取職位ID和所屬公司的ID
companyID = list(map(lambda x:re.findall(r'\d+',x)[0],company_link))
jobID = list(map(lambda x:re.findall(r'\d+',x)[0],job_link))

2.將數(shù)據(jù)存入MySQL數(shù)據(jù)庫中

在Python鏈接之前,已在MySQL數(shù)據(jù)庫设联,創(chuàng)建數(shù)據(jù)庫lagou,數(shù)據(jù)表job,company

#導(dǎo)入模塊 pymysql
import pymysql  

db = pymysql.connect("localhost", "root", "123456", "lagou",use_unicode=True, charset="utf8")
cursor = db.cursor()

#定義一個插入到數(shù)據(jù)庫的函數(shù)
def insert(x_zip,table):    
    for m in x_zip:
        sql = '''INSERT INTO {} values {}'''.format(table,m)
        try:
            cursor = db.cursor()
            cursor.execute(sql)
            db.commit()
        except Exception as error:
            db.rollback()
            print(error)
#將數(shù)據(jù)插入到數(shù)據(jù)庫中
companys = zip(companyID,company_name,company_link,industry,scale)
insert(companys,"company")
jobs = zip(jobID,job_name,address,experience,salary,treatment,job_link,companyID,education,labels,['長沙']*len(jobID))
insert(jobs,"job")

——
翻頁問題:
拉勾上的職位內(nèi)容基于js動態(tài)加載善已,所以點(diǎn)擊下一頁后,地址仍不生變化离例。但是仔細(xì)觀察elements,最后一頁會存在標(biāo)簽:<span …… class = 'pager_next pager_next_disabled' 换团,我們可以利用這個標(biāo)簽來定位。

if s.findAll('span','pager_next pager_next_disabled'):
    break
else:
    submitBtn = driver.find_element_by_class_name("pager_next")
    driver.execute_script("arguments[0].scrollIntoView()", submitBtn) # js滾動加載宫蛆,缺少此步艘包,action無法生效
    submitBtn.click()
    time.sleep(random.randint(3,20)) #爬蟲禮儀,減少訪問服務(wù)器的頻率

以上就是拉勾數(shù)據(jù)分析師職位數(shù)據(jù)爬取和儲存耀盗,這里為了顯得整潔想虎,分別存儲在job,company兩個表中。為了便于閱讀叛拷,完整代碼放在文末鏈接中舌厨,有需要可以自己去fork。

3.數(shù)據(jù)清理

首先忿薇,導(dǎo)入數(shù)據(jù):

import pandas as pd
from sqlalchemy import create_engine
import pymysql

#創(chuàng)建engine
engine = create_engine('mysql://root:123456@localhost:3306/lagou?charset=utf8') 

#從數(shù)據(jù)庫讀取數(shù)據(jù)
#由于python 3 不支持MySQLdb,所以這里將文件中的MySQLdb,改為pymysql便可運(yùn)行
job = pd.read_sql('job',engine)
company = pd.read_sql('company',engine)

第二步裙椭,數(shù)據(jù)基本情況查看

job.head()  #前幾條數(shù)據(jù)查看
image
job.shape   #查看形狀
image
sum(job.duplicated())   #查看重復(fù)情況
image
job.info() #查看數(shù)據(jù)類型躏哩,空值存在情況
image

從以上的基本情況上,可以看到以下問題:

  1. 職位名稱中含有實(shí)習(xí)等因素揉燃,為了方便統(tǒng)計扫尺,這里去除實(shí)習(xí)職位的影響。
  2. experience你雌、salary都是一個區(qū)間器联,后續(xù)探討experience、salary 和education 的關(guān)系需要將具體數(shù)值提取出來婿崭,轉(zhuǎn)換為float型數(shù)據(jù)
  3. 含有重復(fù)職位數(shù)據(jù)拨拓,這里需要剔除。

第三步氓栈,清洗數(shù)據(jù)

#完全復(fù)制原dataframe中不重復(fù)的數(shù)據(jù),方便后續(xù)的數(shù)據(jù)修改
job_df = job.drop_duplicates().copy()
#去除實(shí)習(xí)數(shù)據(jù)
job_df.drop(job_df[job_df.name.str.contains('實(shí)習(xí)')].index,inplace=True)
#新建工資水平high\low
job_df['lowS'] = job_df['salary'].apply(lambda x: x.lower().split('-')[0].replace('k','')).astype(int)
job_df['highS'] = job_df['salary'].apply(lambda x: x.lower().split('-')[1].replace('k','')).astype(int)
#為了更符合實(shí)際渣磷,取工資的區(qū)間前25%
job_df['avgS'] = job_df['lowS']+(job_df['highS']-job_df['lowS'])/4 
#新建一個工作年限,處理經(jīng)驗(yàn)問題
#若為不限/應(yīng)屆畢業(yè)生授瘦,值為0醋界;
#若為1年以下或10年以上,值分別為1提完,10形纺;
#若為1到3年之類的,值取二者均值
job_df['workyear'] = job_df['experience'].str.findall(r'\d+')
def avg_year(i):
    m = 0
    if len(i) == 0:
        m = 0
    elif len(i) == 1:
        m = int(i[0])
    else:
        m = sum(list(map(int,i)))/2
    return m
job_df['workyear'] = job_df['workyear'].apply(avg_year)

4.薪酬和職位分析

from pyecharts import Geo
import seaborn as sns
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline

matplotlib.rc('font', **{'family' : 'SimHei'}) #解決中文亂碼問題徒欣,必選
plt.style.use("ggplot")
#這里若不加plt.style.use("ggplot")逐样,中文仍然亂碼
  • 薪酬整體分布狀況
plt.figure(figsize=(10,5))
sns.distplot(job_df['avgS'],color="r",kde=False)
plt.title('整體薪酬分布狀況');
image

薪酬集中在12000附近,整體上呈偏右分布打肝。

  • 不同城市之間的薪水差異脂新?
plt.figure(figsize=(14,5))
sns.boxplot(x='city',y='avgS',data=job_df,color="r")
plt.title('不同城市之間的平均薪水差異');
image

放在中國地圖上:

data_x = job_df.groupby('city')['avgS'].mean().reset_index()
geot = Geo("全國數(shù)據(jù)分析師平均薪酬分布", "數(shù)據(jù)來源:拉勾", title_color="#fff",
          title_pos="center", width=1200,
          height=600, background_color='#404a59')
attr= data_x['city'].values.tolist()
value = data_x['avgS'].values.tolist()
geot.add("",attr,value,type="heatmap", is_visualmap=True, visual_range=[0, 300],visual_text_color='#fff')
geot.render()
image

在地域分布的薪酬方面,北京粗梭、杭州和深圳的中位數(shù)薪酬牢牢的占據(jù)第一梯隊高于15k争便,其次就是上海、成都断医、武漢等城市滞乙,中位數(shù)薪酬也在11k左右,最低的是天津孩锡,這有可能是于需求上人才都轉(zhuǎn)移到北京去了酷宵。

  • 學(xué)歷對薪酬的影響?
plt.figure(figsize=(14,5))
sns.boxplot(x='education',y='avgS',data=job_df,color="r")
plt.title('不同學(xué)歷之間的薪水差異');
image

學(xué)歷越高躬窜,獲得高薪的機(jī)會也就越高浇垦,這說明讀書發(fā)家還是有機(jī)會的。

  • 工作經(jīng)驗(yàn)對薪酬的影響荣挨?
plt.figure(figsize=(14,5))
sns.boxplot(x="experience", y="avgS", data=job_df)
sns.stripplot(x='experience',y='avgS',data=job_df,jitter=True, color ='.3')
plt.title('不同工作經(jīng)驗(yàn)之間的薪水差異');
image

擬合來看:

sns.regplot(x='workyear',y='avgS',data=job_df,x_jitter=.1,)
plt.title('工作年限與薪酬的擬合關(guān)系')
image

整體上來看男韧,隨著工作經(jīng)驗(yàn)的增加朴摊,薪酬也在不斷上升。低的工作經(jīng)驗(yàn)有也高薪的機(jī)會此虑,但可能需要更高的技能要求(如普通業(yè)務(wù)運(yùn)營數(shù)據(jù)分析師和大數(shù)據(jù)挖掘工程師)甚纲,不斷提升自我的能力才是王道。

  • 數(shù)據(jù)分析師的工作福利和技能
#定義詞云制作函數(shù)
def wordclouds(s):
    text = ''
    for line in job_df[s]:
        text = text+' '+line.strip().replace(',',' ')
    color_mask = imread('qqq.png')
    wordcloud = WordCloud(
                width=1000,height=600,
                font_path = 'simhei.ttf',
                background_color = 'white',
                mask = color_mask,
                max_words = 1000,
                max_font_size = 100, 
                collocations=False
                ).generate(text)
    wordcloud.to_file('{}.png'.format(s))
    plt.imshow(wordcloud)
    plt.axis("off")
    plt.show()

#調(diào)用定義的詞云制作函數(shù)
wordclouds('labels')
wordclouds('treatment')
image
image

在職位標(biāo)簽上朦前,更多的是數(shù)據(jù)挖掘類的工作介杆,當(dāng)然像金融、大數(shù)據(jù)韭寸、業(yè)務(wù)運(yùn)營春哨、機(jī)器學(xué)習(xí)這幾塊也必不可少的。
五險一金作為基本的福利牢牢站在第一福利關(guān)鍵詞恩伺,有些公司給出了六險一金(補(bǔ)充商業(yè)險)的待遇也很不錯的赴背,帶薪年假彈性工作、周末雙休牢牢吸引著眼球吧晶渠。
最后凰荚,我們探討一下,數(shù)據(jù)分析師的需求問題:

  • 數(shù)據(jù)分析師的主要分布行業(yè)褒脯?
#合并工作職位和企業(yè)
df = company_df[['id','name','industry','scale']].merge(job_df[['id','company_id','avgS']],left_on='id',right_on='company_id')

#將industy里面的關(guān)鍵詞取出來
industry_df = pd.DataFrame(df.industry.apply(lambda x: x.replace(' ,',' ').replace(',',' ').replace('便瑟、',' ').strip().split(' ')).tolist())
industry_df_new = industry_df.stack().reset_index().rename(columns={'level_0':'df_index',0:'industry_name'})
industry_df_new.drop('level_1', axis=1, inplace=True)

t = df.merge(industry_df_new,right_on='df_index',left_index=True)
tt['industry_name'].value_counts().plot.bar(figsize =(10,4),title=('數(shù)據(jù)分析師的需求行業(yè)分布'));
image

移動互聯(lián)網(wǎng)需求獨(dú)占鰲頭,其次就是金融番川、數(shù)據(jù)服務(wù)類胳徽、電子商務(wù)類公司需求較大,當(dāng)然可能會有部分企業(yè)行業(yè)標(biāo)簽重合爽彤。

  • 全國各地職位需求數(shù)分布問題?
#提取每個城市的職位數(shù)
data = job_df.groupby('city')['name'].count().reset_index()

#作圖scatter
geo = Geo("全國數(shù)據(jù)分析師的需求分布", "數(shù)據(jù)來源:拉勾", title_color="#fff",
          title_pos="center", width=1200,
          height=600, background_color='#404a59')
attr= data['city'].values.tolist()
value = data['name'].values.tolist()
geo.add("",attr,value,type="scatter", is_visualmap=True, visual_range=[50, 2000],visual_text_color='#fff',visual_type='size', visual_range_size=[20, 80])
geo.render()
image

求職機(jī)會上缚陷,雖然說一線城市機(jī)會多适篙,但一些準(zhǔn)一線城市也在蓬勃發(fā)展中。

結(jié)論?

  1. 數(shù)據(jù)分析師的平均薪水集中在12k附近箫爷,整體上呈右分布
  2. 隨著經(jīng)驗(yàn)和學(xué)歷的增加嚷节,整體上來看數(shù)據(jù)分析師的薪酬在不斷上升中。
  3. 目前市場上數(shù)據(jù)分析師的人才缺口虎锚,更多的是需要掌握數(shù)據(jù)挖掘的技能硫痰。
  4. 數(shù)據(jù)分析師的需求方面,移動互聯(lián)網(wǎng)需求獨(dú)占鰲頭窜护,其次就是金融效斑、數(shù)據(jù)服務(wù)類、電子商務(wù)類公司需求較大
  5. 數(shù)據(jù)分析師的求職方面柱徙,雖然說一線城市機(jī)會多缓屠,但一些準(zhǔn)一線城市也在蓬勃發(fā)展中奇昙。
    ?

局限性:

  1. 事實(shí)上,一線城市北上廣深杭的職位可能會遠(yuǎn)多于其他城市敌完,因?yàn)槔磧H限獲取前30頁储耐,這些城市的職位或多或少大于30頁的。
  2. 數(shù)據(jù)分析師的技能是影響薪酬的重要因素滨溉,但本次分析并沒有體現(xiàn)出來什湘。

——
爬蟲+分析完整代碼:https://github.com/mimicolois/lagou

PS:
1.git 是非常強(qiáng)大的工具,學(xué)會使用git晦攒,從注冊一個github賬號開始
2.嫌棄國內(nèi)訪問速度闽撤,代碼托管國內(nèi)有碼云
3.git 入門指南:廖雪峰老師的Git教程

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市勤家,隨后出現(xiàn)的幾起案子腹尖,更是在濱河造成了極大的恐慌,老刑警劉巖伐脖,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件热幔,死亡現(xiàn)場離奇詭異,居然都是意外死亡讼庇,警方通過查閱死者的電腦和手機(jī)绎巨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蠕啄,“玉大人场勤,你說我怎么就攤上這事〖吒” “怎么了和媳?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長哈街。 經(jīng)常有香客問我留瞳,道長,這世上最難降的妖魔是什么骚秦? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任她倘,我火速辦了婚禮,結(jié)果婚禮上作箍,老公的妹妹穿的比我還像新娘硬梁。我一直安慰自己,他們只是感情好胞得,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布荧止。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪罩息。 梳的紋絲不亂的頭發(fā)上嗤详,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天,我揣著相機(jī)與錄音瓷炮,去河邊找鬼葱色。 笑死,一個胖子當(dāng)著我的面吹牛娘香,可吹牛的內(nèi)容都是我干的苍狰。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼烘绽,長吁一口氣:“原來是場噩夢啊……” “哼淋昭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起安接,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤翔忽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后盏檐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體歇式,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年胡野,在試婚紗的時候發(fā)現(xiàn)自己被綠了材失。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡硫豆,死狀恐怖龙巨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情熊响,我是刑警寧澤旨别,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站汗茄,受9級特大地震影響昼榛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜剔难,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望奥喻。 院中可真熱鬧偶宫,春花似錦、人聲如沸环鲤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至吵冒,卻和暖如春纯命,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背痹栖。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工亿汞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人揪阿。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓疗我,卻偏偏與公主長得像,于是被迫代替她去往敵國和親南捂。 傳聞我的和親對象是個殘疾皇子吴裤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容