首先说明这篇文章的数据来源,为前程无忧中所有“数据分析师”这一职位信息所得来的。并且主要分析了数据分析师在全国不同地区的需求情况、总体薪酬情况、不同城市薪酬分布、不同学历薪酬分布、不同地区学历要求情况、不同经验需求与薪酬分布情况。
本文行文思路:
数据采取
数据清洗
数据分析
分析结论
思考总结
1.数据采集
定位数据位置
首先进入前程无忧首页,然后在职位搜索中检索数据分析师,不加其他限定条件,点击搜索可得到以下结果:
可以看到关于数据分析师的岗位信息一共10263条。
爬虫代码调试及运行
本文代码参照Python网络爬虫爬取智联招聘职位,之前不会爬虫,花了半天时间研究了一下,自己改了改,调试了一番,最后能勉强运行了。代码见下:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import urllib2,re,sys,pandas as pd
reload(sys)
sys.setdefaultencoding( "utf-8" )
result11=[]
result21=[]
result31=[]
result41=[]
result51=[]
result61=[]
result71=[]
headers = {'User-agent' : 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0'}
def zhuanhuan(y):
result=[]
for i in y:
result.append(i.decode("gbk"))
return result
for k in range(1,208):
html=urllib2.urlopen("http://search.51job.com/jobsearch/search_result.php?fromJs=1&jobarea=000000%2C00&district=000000&funtype=0000&industrytype=00&issuedate=9&providesalary=99&keyword=%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E5%B8%88&keywordtype=2&curr_page="+str(k)+"&lang=c&stype=1&postchannel=0000&workyear=99&cotype=99°reefrom=99&jobterm=99&companysize=99&lonlat=0%2C0&radius=-1&ord_field=0&list_type=0&dibiaoid=0&confirmdate=9").read()
pat1 = '<a target="_blank" title=(.*?) οnmοusedοwn='
pat1_a ='"(.*?)" href="'
pat1_b ='" href="(.*?)"'
pat2 = '<span class="t2"><a target="_blank" title="(.*?)" href="'
pat3 = '<span class="t3">(.*?)</span>'
pat4 = '<span class="t4">(.*?)</span>'
pat5 = '<span class="sp4"><em class="i1"></em>(.*?)</span>'
pat6 = 'ass="sp4"><em class="i2"></em>(.*?)</span>'
a=''
result1 = re.compile(pat1).findall(html)
for i in result1:
a=a+str(i)
result1 = re.compile(pat1_a).findall(a)
result2 = re.compile(pat2).findall(html)
result3 = re.compile(pat3).findall(html)[1:]
result4 = re.compile(pat4).findall(html)[1:]
result5 = re.compile(pat1_b).findall(a)
for i in result5:
request = urllib2.Request(i, headers = headers)
try:
response = urllib2.urlopen(request,timeout=20).read()
html1 = response
if re.compile(pat5).findall(html1):
result61.extend(re.compile(pat5).findall(html1))
else:
result61.extend([''])
if re.compile(pat6).findall(html1):
result71.extend(re.compile(pat6).findall(html1))
else:
result71.extend([''])
except:
result61.extend([''])
result71.extend([''])
result11.extend(result1)
result21.extend(result2)
result31.extend(result3)
result41.extend(result4)
result51.extend(result5)
if len(result1)!=len(result2):
print k
break
print k
result11=zhuanhuan(result11)
result21=zhuanhuan(result21)
result31=zhuanhuan(result31)
result41=zhuanhuan(result41)
result51=zhuanhuan(result51)
result61=zhuanhuan(result61)
result71=zhuanhuan(result71)
print len(result11)
print len(result21)
print len(result31)
print len(result41)
print len(result51)
print len(result61)
print len(result71)
df2=pd.DataFrame({u"职位名":result11,u"公司名":result21,u"工作地":result31,u"薪资":result41,u"工作经验":result61,u"学历要求":result71}) #
df2.to_excel('foo.xlsx', sheet_name='Sheet1')
对于写过爬虫的,上面代码可能比较简单,主要涉及反爬伪造http头部,正则表达,Python中文编码,pandas库运用,和一些基本的循环之类东西。
代码缺点也很明显:1.运行时间慢,需要1个多小时,因为要爬取1万多个页面。2.爬取信息过少,因为本人正则表达和Python字符串处理不精通,行业信息、企业规模、企业性质未能匹配出来。
最后爬出10163行岗位数据,与原网页10263相差100行数据,结果存储为一个名为foo.xlsx的excel文件。
2.数据清洗
本案例要进行清洗的要点主要涉及以下几点:
重复数据的删除
空值的填充
工作地点重置为市级
薪资单位转换及去区间化
重复数据删除
本案例要进行清洗的要点主要涉及以下几点:
重复数据的删除
空值的填充
工作地点重置为市级
薪资单位转换及去区间化
重复数据删除
import pandas as pd
my = pd.DataFrame(pd.read_excel('foo.xlsx'))
my = my.drop_duplicates()
HR经常会因为招聘压力,发布重复招聘信息,这里需要删除重复数据,经过去重操作后,总数据量由10163变为8696。看来hr们压力挺大的,也是蛮拼。
空值处理
首先需要查看空值分布在那几列中
a = [u"公司名",u"学历要求",u"工作地",u"工作经验",u"职位名",u"薪资"]
for i in a:
my[i].isnull().value_counts()
可以得到以下输出
False 8696
Name: 公司名, dtype: int64
False 6256
True 2440
Name: 学历要求, dtype: int64
False 8696
Name: 工作地, dtype: int64
False 8505
True 191
Name: 工作经验, dtype: int64
False 8696
Name: 职位名, dtype: int64
False 8275
True 421
Name: 薪资, dtype: int64
以上数据可以看出,学历要求中2440条空值、工作经验中191条空值、薪资中421条空值。
学历空值填充为不限,工作经验填充为无经验要求、薪资空值删除整行。
my[u"学历要求"] = my[u"学历要求"].fillna(u"不限")
my[u"工作经验"] = my[u"工作经验"].fillna(u"无工作经验")
my = my.dropna(axis = 0)
工作地重置为市级
将市级与区级的工作地,统一为市级工作地,以统一标准。
def cut_word(word):
position=word.find('-')
length=len(word)
if position !=-1:
new_city = word[:position]
else:
new_city = word
return new_city
my[u"市级_工作地"] = my[u"工作地"].apply(cut_word)
薪资单位转换及去区间化
薪资数据中,单位不一致,元/天、千/月、万/月、万/年,这里全部统一为千/月。
而很多数据都是区间存在的,这里取平均值代替区间。代码见下:
def cut_salary(word):
position=word.find('-')
length=len(word)
if u"月" in word and u"千" in word:
danwei = 1
if u"月" in word and u"万" in word:
danwei = 10
if u"年" in word and u"万" in word:
danwei = 10.0/12
if u"天" in word and u"元" in word:
danwei = 0.02175
num_position = max(word.find(u'元'),word.find(u'千'),word.find(u'万'))
if position !=-1:
b_salary=word[:position]
t_salary=word[position+1:num_position]
else:
b_salary = t_salary = word[:num_position]
return (float(b_salary)+float(t_salary))*danwei/2.0
my[u"新_薪资"] = my[u"薪资"].apply(cut_salary)
my.to_excel('foo.xlsx',sheet_name='Sheet1')
至此,数据清洗完毕,将数据保存至本地,然后开始分析之旅吧。
3.数据分析
需求人数城市分布
pandas的数据透视调试半天都是错误,这里就用这个excel制作的柱形图凑合一下。
可以看到,北上两座城市明显超过其他城市,深广只能算第二梯队。
薪资总体分布
import matplotlib.pyplot as plt
salary = my[u"新_薪资"]
bins = [0,5,10,15,20,25,30,35,40,45,50,55,60]
plt.hist(salary, bins, histtype='g', rwidth=0.8)
plt.xlabel('salary')
plt.show()
从上表可以看出,大部分岗位的薪资位于5-15之间,其中5-10之间最多,只有极少数岗位提供较高薪资,另一方面,也存在部分0-5之间的岗位,且岗位数占到近18%。由此来看,大多数数据分析岗,拿着一般般的薪资,而并非网上那般,被炒得虚高。
城市薪资分布
my_1=my[my[u"市级_工作地"]==u"北京"]
my_2=my[my[u"市级_工作地"]==u"上海"]
my_3=my[my[u"市级_工作地"]==u"广州"]
my_4=my[my[u"市级_工作地"]==u"深圳"]
my_5=my[my[u"市级_工作地"]==u"武汉"]
my_6=my[my[u"市级_工作地"]==u"成都"]
my_7=my[my[u"市级_工作地"]==u"杭州"]
my_8=my[my[u"市级_工作地"]==u"天津"]
my_9=my[my[u"市级_工作地"]==u"南京"]
my_10=my[my[u"市级_工作地"]==u"长沙"]
frames = [my_1,my_2,my_3,my_4,my_5,my_6,my_7,my_8,my_9,my_10]
result=pd.concat(frames)
ax=result.boxplot(column=u'新_薪资',by=u'市级_工作地',figsize=(9,7))
ax.title(u"哈哈")
for label in ax.get_xticklabels():
label.set_fontproperties(zh_font)
plt.show()
城市薪资分布
可以看到,各大城市中位数均未超过10k,北上最高约9k,深圳、南京、杭州紧随其后。
但在top区域,可以看到,一线城市和二线城市就拉的比较开,天津、武汉、长沙在20k以上的样本几乎没有,所以,对于那些经验比较丰富,且寻求高薪的人士,上海,北京和深圳是求职的好去处。
不同学历的薪酬分布
ax=result.boxplot(column=u'新_薪资',by=u'学历要求',figsize=(9,7))
for label in ax.get_xticklabels():
label.set_fontproperties(zh_font)
plt.savefig("ed.png")
博士的薪资的中位数和众数一马当先,硕士、本科紧随其后,但是在top端,博士表现不佳,原因可能是,极高薪的数据反而对学历要求没那么高,大专在top区域都有比较亮眼的数据表现。但是在中端的数据岗,对学历有一定的要求。
相同工作年限不同城市薪资分布
df_bj_sh=result[result['city'].isin([u'上海',u'北京'])]
ax=df_bj_sh.boxplot(column=u'新_薪资',by=[u'工作经验','city'],figsize=(19,6))
for label_x in ax.get_xticklabels():
label_x.set_fontproperties(zh_font)
plt.savefig("ed.png")
可以看到,相同工作经验下,上海薪资要略高于北京,但是在8-9年工作经验一块,出现了一个异常数据,上海的8-9年岗位薪资水平不足10k,显然是异常数据,后期需要核对一下。
分析结论
从需求城市上看,北京和上海是两座对数据分析人才需求量最大两座城市,约占全国的1/3
,深圳、广州各占10%左右。数据分析方面的求职者可多关注四座城市。
从总体薪资构成来看,大多数数据分析师的薪资水平不超过10k,此岗位并非网上被炒的过热那般。
从城市薪资构成来看,一二线城市薪资中位数和众数并未拉开,但是看极值表现,二线城市在top岗位上稍显欠缺。
而单看学历、薪资图,会发现,中等偏上水平薪资的岗位更倾向于寻求博士生,而top水平薪资的岗位则青睐本科、硕士、专科。
上海与北京相同工作年限的对比可以看出,要求同等经验的岗位,上海的薪资高于北京。