0%

BOSS直聘“自动驾驶”岗位信息爬取与分析

  这是我个人博客的第一篇文章,是全新的开始。希望未来在这里记录更多有趣的探索。

  自动驾驶随着人工智能技术的成熟,人才需求在不断增加,为了对我国自动驾驶人才需求进行了解,本文选择BOSS直聘招聘网站获取自动驾驶相关职位信息,分析数据,根据分析结果确定人才需求、为以后的学习制定计划。

本文开发环境:python3.7anconda3

一、数据爬取

1.1 分析目标页,构造URL

  首先,进入网站输入关键字“自动驾驶”查询得到职位的列表页面,对目标页面的URL分析https://www.zhipin.com/c101010100/?query=自动驾驶&page=1&ka=page-1,发现关键的字段有:querypage分别代表了要查询的关键字页面c101010100代表了城市的编号,当选择了全国时编号为c101010100,所以通过控制这三个参数,实现对全国所有职位列表页的信息的爬取。

图1-1 目标页面

  其次,构建headers cookie,通过尝试发现爬取Boss直聘必须添加cookie,构建的请求头如下。

header = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', 'Cookie': '_uab_collina=156967238793885639512262;bannerClose_wanmeishijie=true; lastCity=101010100; _bl_uid=q5k7F1m8aOIjLLybtrIhbILink0X; __c=1570153169; __g=-;Hm_lvt_194df3105ad7148dcf2b98a91b5e727a=1569912508,1569985933,1570068443,1570153169;__l=l=%2Fwww.zhipin.com%2F&r=&friend_source=0&friend_source=0;toUrl=https%3A%2F%2Fwww.zhipin.com%2Fjob_detail%2F%3Fquery%3D%25E8%2587%25AA%25E5%258A%25A8%25E9%25A9%25BE%25E9%25A9%25B6%26city%3D101020100%26industry%3D%26position%3D;__zp_stoken__=eaf4AHdTnnRrM4tosXCE%2FCPA2IBqs%2BoMIR%2FkL2KsnUmYiwLERJs40PPb8KIurKugecg3l0jmgV1zyN86oQkjtd81dw%3D%3D;Hm_lpvt_194df3105ad7148dcf2b98a91b5e727a=1570159163;__a=64007787.1569672388.1570068443.1570153169.178.6.23.172;__zp_sseed__=4qNlVc1nPWG9Y7G66QfbgtQFW6iSHevalYp+HzrGFH4=; __zp_sname__=9d9e2c78;__zp_sts__=1570159388399' }

1.2 爬取、解析数据并保存

1.2.1 确定要爬取的信息

  F12打开开发者工具,审查网页元素,需要获取的信息包括“工作名、薪资、工作地点、工作经验、学历要求、企业名、企业所属行业”。

图1-2 分析目标页面

1.2.2 发送请求、解析数据、保存数据

  对目标页面发送请求后,解析返回的html并提取所需要的信息,这里主要用到的包有:urllibrequestsBeautifulSouplxml。函数的主要步骤为:

  • 第一步,请求目标页面html
  • 第二步,使用lxmlbs4解析目标信息
  • 第三步,随机等待几秒,防止ip被封

循环完成对所有页面岗位信息的提取,当完成数据的解析后,将数据保存到Excel表格中。下面的代码实现上述发送请求、解析数据、保存数据步骤。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
def get_all_detial(total_page_count):
#循环所有页面,
#第一步,构造URL获取html
#第二步,使用bs4解析详情页的超链接,保存到数组中
key_words = "自动驾驶"
key = urllib.parse.quote(key_words) #将中文进行转码
jobs_title_list = []
area_list = []
work_exp_list = []
edu_list = []
company_list = []
salary_list = []
industry_list = []
financing_stage_list = []
company_scale_list = []
for i in range(1,total_page_count+1): #查看页面有10页职位列表
print("正在爬取第 %s 页列表页..." % i)
url ='https://www.zhipin.com/c100010000/?query='+key+'&page='+str(i)+'&ka=page-'+str(i)
#获取每页的列表html
per_page_html = get_job_html(url)
#解析提取详情页超的数据
jobs_title,area,work_exp,edu,company,salary,industry\
= parse_job_detial(per_page_html) #,company_scale,financing_stage
# 将每页30个数据尾加到总的数组
jobs_title_list,area_list,work_exp_list,edu_list,company_list,salary_list,industry_list\
= append_job_detial(jobs_title_list,area_list,work_exp_list,edu_list,company_list,salary_list,industry_list,\
jobs_title,area,work_exp,edu,company,salary,industry)
#随机等待,防止封ip
span=round(random.random()*6,1)
time.sleep(span)
print("爬取列表页完成!")
# 将爬取的数据保存到Excel
jobs_data = list(zip(jobs_title_list,area_list,work_exp_list,edu_list,company_list,salary_list,industry_list))
jobs_data.insert(0, ("岗位","工作地点","工作经验要求","学历要求","招聘公司","工资","所属行业"))
save_to_excel("jobData", "AutoDriving", jobs_data) #fileName,SheetName,数据
print("保存数据成功,打开jobData.xls查看")

  get_job_html(url)函数实现请求目标url,代码实现如下。

1
2
3
4
5
6
7
8
9
10
11
12
def get_job_html(url):
header = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36',
'Cookie':'_uab_collina=156967238793885639512262; bannerClose_wanmeishijie=true; lastCity=101010100; _bl_uid=q5k7F1m8aOIjLLybtrIhbILink0X; __c=1570153169; __g=-; Hm_lvt_194df3105ad7148dcf2b98a91b5e727a=1569912508,1569985933,1570068443,1570153169; __l=l=%2Fwww.zhipin.com%2F&r=&friend_source=0&friend_source=0; toUrl=https%3A%2F%2Fwww.zhipin.com%2Fjob_detail%2F%3Fquery%3D%25E8%2587%25AA%25E5%258A%25A8%25E9%25A9%25BE%25E9%25A9%25B6%26city%3D101020100%26industry%3D%26position%3D; __zp_stoken__=eaf4AHdTnnRrM4tosXCE%2FCPA2IBqs%2BoMIR%2FkL2KsnUmYiwLERJs40PPb8KIurKugecg3l0jmgV1zyN86oQkjtd81dw%3D%3D; Hm_lpvt_194df3105ad7148dcf2b98a91b5e727a=1570159163; __a=64007787.1569672388.1570068443.1570153169.178.6.23.172; __zp_sseed__=4qNlVc1nPWG9Y7G66QfbgtQFW6iSHevalYp+HzrGFH4=; __zp_sname__=9d9e2c78; __zp_sts__=1570159388399'
}
try:
html = requests.get(url,headers = header)
if html.status_code == 200:
return html.text #返回列表页的html
return None
except RequestException:
return None

  获取到网页html后解析想要的数据,实现代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
def parse_job_detial(per_page_html):
if per_page_html=='' or len(per_page_html)==0:
print("未请求到列表页的html!")
return None
else:
jobs_title = []
area = []
work_exp = []
edu = []
company = []
salary = []
industry = []
financing_stage = []
company_scale = []
# 初始化 标准化html
html = etree.HTML(per_page_html)
# 工作名
jobs_title = html.xpath('//div[@class="job-title"]/text()')
#print(jobs_title)
#a = 1
# 工作地点
area = html.xpath('//div[@class="info-primary"]//p/text()[1]')
#print(area)
#a = 1
#工作经验要求
work_exp = html.xpath('//div[@class="info-primary"]//p/text()[2]')
#print(work_exp)
#a = 1
#学历要求
edu = html.xpath('//div[@class="info-primary"]//p/text()[3]')
#print(edu)
#a = 1
#公司名
company = html.xpath('//div[@class="company-text"]//a/text()')
#print(company)
#a = 1
# 工资
salary = html.xpath('//div[@class="info-primary"]//span[@class="red"]/text()')
#print(salary)
#a = 1
#所属行业
industry = html.xpath('//div[@class="info-company"]//p/text()[1]')
return jobs_title,area,work_exp,edu,company,salary,industry

  每次获取的是一页职位列表信息,需要将每次的数据尾加到总的数据list中,代码实现如下。

1
2
3
4
5
6
7
8
9
10
def append_job_detial(jobs_title_list,area_list,work_exp_list,edu_list,company_list,salary_list,industry_list,jobs_title,area,work_exp,edu,company,salary,industry):
for i,info in enumerate(jobs_title):
jobs_title_list.append(jobs_title[i])
area_list.append(area[i])
work_exp_list.append(work_exp[i])
edu_list.append(edu[i])
company_list.append(company[i])
salary_list.append(salary[i])
industry_list.append(industry[i])
return jobs_title_list,area_list,work_exp_list,edu_list,company_list,salary_list,industry_list

  当所有页面的数据获取解析完成后,将数据保存为Excel的形式,代码实现:

1
2
3
4
5
6
7
8
9
10
def save_to_excel(filename,sheet_name,data):
f = xlwt.Workbook(encoding='utf-8') #创建一个Workbook 设置编码
# 第二参数表示是否可以覆盖单元格 其实是 Workbook实例化的一个参数,默认值为False
sheet = f.add_sheet(sheet_name,cell_overwrite_ok=True)
# enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,
# 同时列出数据和数据下标,一般用在 for 循环当中。
for row,row_data in enumerate(data): #处理行
for column,column_data in enumerate(row_data): #处理列
sheet.write(row,column,str(column_data))
f.save(filename + ".xls")

  对整个过程的代码集成如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import urllib
import requests
import time
import random
from bs4 import BeautifulSoup
from lxml import etree #xpath
from requests.exceptions import RequestException
import xlwt #excel操作

def get_job_html(url):
header = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36',
'Cookie':'_uab_collina=156967238793885639512262; bannerClose_wanmeishijie=true; lastCity=101010100; _bl_uid=q5k7F1m8aOIjLLybtrIhbILink0X; __c=1570153169; __g=-; Hm_lvt_194df3105ad7148dcf2b98a91b5e727a=1569912508,1569985933,1570068443,1570153169; __l=l=%2Fwww.zhipin.com%2F&r=&friend_source=0&friend_source=0; toUrl=https%3A%2F%2Fwww.zhipin.com%2Fjob_detail%2F%3Fquery%3D%25E8%2587%25AA%25E5%258A%25A8%25E9%25A9%25BE%25E9%25A9%25B6%26city%3D101020100%26industry%3D%26position%3D; __zp_stoken__=eaf4AHdTnnRrM4tosXCE%2FCPA2IBqs%2BoMIR%2FkL2KsnUmYiwLERJs40PPb8KIurKugecg3l0jmgV1zyN86oQkjtd81dw%3D%3D; Hm_lpvt_194df3105ad7148dcf2b98a91b5e727a=1570159163; __a=64007787.1569672388.1570068443.1570153169.178.6.23.172; __zp_sseed__=4qNlVc1nPWG9Y7G66QfbgtQFW6iSHevalYp+HzrGFH4=; __zp_sname__=9d9e2c78; __zp_sts__=1570159388399'
}
try:
html = requests.get(url,headers = header)
if html.status_code == 200:
return html.text #返回列表页的html
return None
except RequestException:
return None

def parse_job_detial(per_page_html):
if per_page_html=='' or len(per_page_html)==0:
print("未请求到列表页的html!")
return None
else:
jobs_title = []
area = []
work_exp = []
edu = []
company = []
salary = []
industry = []
financing_stage = []
company_scale = []
# 初始化 标准化html
html = etree.HTML(per_page_html)
# 工作名
jobs_title = html.xpath('//div[@class="job-title"]/text()')
#print(jobs_title)
#a = 1
# 工作地点
area = html.xpath('//div[@class="info-primary"]//p/text()[1]')
#print(area)
#a = 1
#工作经验要求
work_exp = html.xpath('//div[@class="info-primary"]//p/text()[2]')
#print(work_exp)
#a = 1
#学历要求
edu = html.xpath('//div[@class="info-primary"]//p/text()[3]')
#print(edu)
#a = 1
#公司名
company = html.xpath('//div[@class="company-text"]//a/text()')
#print(company)
#a = 1
# 工资
salary = html.xpath('//div[@class="info-primary"]//span[@class="red"]/text()')
#print(salary)
#a = 1
#所属行业
industry = html.xpath('//div[@class="info-company"]//p/text()[1]')
return jobs_title,area,work_exp,edu,company,salary,industry

def append_job_detial(jobs_title_list,area_list,work_exp_list,edu_list,company_list,salary_list,industry_list,jobs_title,area,work_exp,edu,company,salary,industry):
for i,info in enumerate(jobs_title):
jobs_title_list.append(jobs_title[i])
area_list.append(area[i])
work_exp_list.append(work_exp[i])
edu_list.append(edu[i])
company_list.append(company[i])
salary_list.append(salary[i])
industry_list.append(industry[i])
return jobs_title_list,area_list,work_exp_list,edu_list,company_list,salary_list,industry_list

def save_to_excel(filename,sheet_name,data):
f = xlwt.Workbook(encoding='utf-8') #创建一个Workbook 设置编码
# 第二参数表示是否可以覆盖单元格 其实是 Workbook实例化的一个参数,默认值为False
sheet = f.add_sheet(sheet_name,cell_overwrite_ok=True)
# enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,
# 同时列出数据和数据下标,一般用在 for 循环当中。
for row,row_data in enumerate(data): #处理行
for column,column_data in enumerate(row_data): #处理列
sheet.write(row,column,str(column_data))
f.save(filename + ".xls")

def get_all_detial(total_page_count):
#循环所有页面,
#第一步,构造URL获取html
#第二步,使用bs4解析详情页的超链接,保存到数组中
key_words = "自动驾驶"
key = urllib.parse.quote(key_words) #将中文进行转码
jobs_title_list = []
area_list = []
work_exp_list = []
edu_list = []
company_list = []
salary_list = []
industry_list = []
financing_stage_list = []
company_scale_list = []
for i in range(1,total_page_count+1): #查看页面有10页职位列表
print("正在爬取第 %s 页列表页..." % i)
url ='https://www.zhipin.com/c100010000/?query='+key+'&page='+str(i)+'&ka=page-'+str(i)
#获取每页的列表html
per_page_html = get_job_html(url)
#解析提取详情页超的数据
jobs_title,area,work_exp,edu,company,salary,industry\
= parse_job_detial(per_page_html) #,company_scale,financing_stage
# 将每页30个数据尾加到总的数组
jobs_title_list,area_list,work_exp_list,edu_list,company_list,salary_list,industry_list\
= append_job_detial(jobs_title_list,area_list,work_exp_list,edu_list,company_list,salary_list,industry_list,\
jobs_title,area,work_exp,edu,company,salary,industry) #,financing_stage_list,financing_stage,financing_stage_list,company_scale,,company_scale_list,company_scale_list,
#随机等待,防止封ip
span=round(random.random()*6,1)
time.sleep(span)
print("爬取列表页完成!")
# 将爬取的数据保存到Excel
jobs_data = list(zip(jobs_title_list,area_list,work_exp_list,edu_list,company_list,salary_list,industry_list)) #,company_scale_list
jobs_data.insert(0, ("岗位","工作地点","工作经验要求","学历要求","招聘公司","工资","所属行业")) #,"公司规模"
save_to_excel("jobData", "AutoDriving", jobs_data) #fileName,SheetName,数据
print("保存数据成功,打开jobData.xls查看")

total_page_count = 10 #设置爬取列表页页数,10页
get_all_detial(total_page_count) #获取工作的数据保存到Excel
图1-4 获取的数据

  图1-4为获取的目标数据,一共抓取了120个岗位信息。下一步就是对获取的信息进行清洗和统计分析。

二、数据分析

  本节主要介绍我们关心哪些信息,并如何对这些的数据进行分析处理和可视化,从而从这些数据中提取出有价值的信息。

2.1 工作地点全国分布

  找工作首先关注的点应该是“在哪”工作,找到一个房价便宜工资很高的工作应该是绝大多数求职者的最佳选择。那么“自动驾驶”相关岗位在全国范围内的分布是什么样的情况,本文通过使用优秀的可视化包pyecharts[1]实现对招聘岗位全国的分布情况的分析。

在制作过程中pyecharts的官方文档起到了很大的作用,以后在开发过程中要重视官方文档的使用。

图2-1 自动驾驶职位招聘全国分布
图2-2 自动驾驶岗位数量全国TOP10城市

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import pandas as pd
from pyecharts.charts import Geo
from pyecharts.charts import Bar
from pyecharts import options as opts
import re
from pyecharts.globals import GeoType
from pyecharts.render import make_snapshot
from snapshot_selenium import snapshot

def city_counter():
"""
全国工作分布热力图
"""
datas = pd.read_excel('jobData.xls', encoding = 'utf-8')
datas_copy = datas
datas_copy['工作地点'] = datas_copy['工作地点'].apply(lambda x :x.split(' ')[0])
grouped_city = datas_copy.groupby(datas['工作地点'])
grouped_city_count = grouped_city['工作地点'].agg(['count']) # 对城市数量进行统计
grouped_city_count.reset_index(inplace = True) # 若不进行此操作,将会报错
city_data = [(grouped_city_count['工作地点'][i], grouped_city_count['count'][i]) for i in range(grouped_city_count.shape[0])]
#print(city_data)
attr = []
value = []
for obj in city_data:
attrSub = re.findall(r'[(](.*?)[)]', str(obj))[0].split(',')[0]
attr.append(attrSub.split("'")[1])
value.append(int(re.findall(r'[(](.*?)[)]', str(obj))[0].split(',')[1].strip()))
#print(attr)
#print(value)
# 全国工作分布热力图
geo = Geo()
geo = (
Geo()
.add_schema(maptype="china")
.add("岗位数",[list(z) for z in zip(attr, value)],symbol_size = 20)
.set_series_opts(label_opts=opts.LabelOpts(is_show=False)) #设置图例不可见
.set_global_opts(visualmap_opts=opts.VisualMapOpts(min_=0,max_=40),title_opts=opts.TitleOpts(title="自动驾驶职位招聘地理位置"))
)
#geo.render('自动驾驶岗位全国热力图.html')

# 全国招聘职位top10地区
city_top10 = sorted(city_data, key = lambda x: x[1], reverse = True)[0:10]
attr = []
value = []
for obj in city_top10:
attrSub = re.findall(r'[(](.*?)[)]', str(obj))[0].split(',')[0]
attr.append(attrSub.split("'")[1])
value.append(int(re.findall(r'[(](.*?)[)]', str(obj))[0].split(',')[1].strip()))
bar = (
Bar()
.add_xaxis(attr)
.add_yaxis("招聘数量",value)
.set_global_opts(title_opts=opts.TitleOpts(title="自动驾驶岗位分布柱状图"))
)
#bar.render()
return geo,bar

geo,bar = city_counter()
geo.render('自动驾驶岗位全国热力图.html')
bar.render('自动驾驶岗位分布柱状图.html')
#make_snapshot(snapshot, geo.render(), "自动驾驶岗位全国热力图.png") # 使用此语句可直接生成图片
#make_snapshot(snapshot, bar.render(), "自动驾驶岗位分布柱状图.png") # 使用此语句可直接生成图片

  从图中可以看出“自动驾驶”岗位主要分布在北京、上海、深圳、武汉、苏州、杭州等一线、二线城市,北京、江浙沪(包邮区)和深圳是主要阵地,如果想要从事这个领域的工作,到这些城市去发展有好的环境。

2.2 薪资水平

  找工作更重要的是薪资的水平,辛辛苦苦学了很多技能和知识就是为了获得更多的薪资。所以我们来看一下“自动驾驶”岗位的全国范围的薪资水平是怎样的。本文对获取的数据按照城市分类,计算了各个城市的平均薪资水平,如图2-3所示。

图2-3 自动驾驶全国平均薪资水平统计

  从图中可以看出,杭州以35K的平均月薪位居全国第一,全国范围内的平均薪资为18422元/月,佛山最低仅有5000元/月。月薪超过全国平均水平的数量超总体的60%。可以看出,薪资水平最高的城市在杭州、北京、上海、深圳等一线城市,杭州的物价水平和房价低于北上广等城市,落户和生活的成本与北上广相比较低,是一个不错的选择。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import pandas as pd
from pyecharts.charts import Bar
from pyecharts import options as opts
import re
from pyecharts.render import make_snapshot
from snapshot_selenium import snapshot

def deal_salary(salary_data):
if re.match('.*K',salary_data):
# 计算平均工资
return int(float((float(re.findall(r'(.*?)K',salary_data)[0].split('-')[0])*1000+\
float(re.findall(r'(.*?)K',salary_data)[0].split('-')[1])*1000)/2))


def city_salary():
"""
每个城市的平均工资条形统计图
"""
datas = pd.read_excel('jobData.xls', encoding = 'utf-8')
datas_copy = datas
datas_copy['工作地点'] = datas_copy['工作地点'].apply(lambda x :x.split(' ')[0])
datas_copy = datas_copy[~datas_copy['工资'].str.contains('天')] # 除去实习的数据
datas_copy = datas_copy[~datas_copy['工资'].isna()] # 除去工资为空的值
datas_copy['工资'] = datas_copy['工资'].apply(lambda x :deal_salary(x))
grouped_city_salary = datas_copy['工资'].groupby(datas_copy['工作地点'])
salary_month = grouped_city_salary.agg(['mean']) #计算各个城市的平均工资
salary_month.reset_index(inplace = True)
attr = []
value = []
for i in range(salary_month.shape[0]):
attr.append(salary_month['工作地点'][i])
value.append(str(salary_month['mean'][i])) #将 int 数字转化为 string才能显示图片
bar = (
Bar()
.add_xaxis(attr)
.add_yaxis("工资(元)",value)
.set_global_opts(title_opts=opts.TitleOpts(title="城市平均工资统计图"))
.set_series_opts(
label_opts=opts.LabelOpts(is_show=False),
markline_opts=opts.MarkLineOpts(
data=[
opts.MarkLineItem(type_="average", name="平均值")
]
),
markpoint_opts=opts.MarkPointOpts(
data=[
opts.MarkPointItem(type_="max", name="最大值"),
opts.MarkPointItem(type_="min", name="最小值"),
]
)
)
)
return bar

city_mean_salary = city_salary()
city_mean_salary.render()
#make_snapshot(snapshot, city_mean_salary.render(), "城市平均工资统计图.png") # 使用此语句可直接生成图片

2.3 学历、工作经验要求

  你可能会问这些岗位这么好,会对学历有很高的要求吗?(学历在不同行业都是越高越好吗?)对工作经验又有什么样的要求呢?那么我们就通过数据来看一下结果吧,通过对所获取信息中的学历要求、工作经验进行统计,绘制“自动驾驶”职位学历要求饼图、工作经验要求饼图如图2-4和图2-5所示。

图2-4 “自动驾驶”职位学历要求
图2-5 “自动驾驶”职位工作经验要求

  通过统计结果可以看出,在获取的岗位招聘信息中,自动驾驶相关岗位对学历的要求不是很高,本科学历要求占75%以上,硕士学历要求占15%左右。结合经验要求来看,大部分的公司要求是经验不限和1-5年,这几个时间范围占了主要部分,所以结合这两个信息,认为“自动驾驶”岗位更加看重工作经验,只要有本科的学历,经验丰富能力强就可以找到不错的工作。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import pandas as pd
from pyecharts.charts import Page, Pie
from pyecharts import options as opts
import re
from pyecharts.render import make_snapshot
from snapshot_selenium import snapshot

def edu_require():
"""
学历要求饼图
"""
datas = pd.read_excel('jobData.xls', encoding = 'utf-8')
datas_copy = datas
datas_copy = datas_copy[~datas_copy['学历要求'].str.contains('个月')] # 去掉实习工作
grouped_eductaion = datas_copy.groupby(datas_copy['学历要求']) # 按学历分组
grouped_eductaion_count = grouped_eductaion['学历要求'].agg(['count']) # 统计不同分组的数量
grouped_eductaion_count.reset_index(inplace = True)
# edu_data = [(grouped_eductaion_count['学历要求'][i], grouped_eductaion_count['count'][i]) for i in range(grouped_eductaion_count.shape[0])]
attr = []
value = []
for i in range(grouped_eductaion_count.shape[0]):
attr.append(grouped_eductaion_count['学历要求'][i])
value.append(str(grouped_eductaion_count['count'][i])) #将 int 数字转化为 string才能显示图片
pie = (
Pie()
.add(
"",
[list(z) for z in zip(attr, value)],
radius=["40%", "75%"]
)
.set_global_opts(
title_opts=opts.TitleOpts(title="学历要求"),
legend_opts=opts.LegendOpts(
orient="vertical", pos_top="15%", pos_left="2%"
)
)
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
)
return pie

def exp_require():
"""
工作经验要求饼图
"""
datas = pd.read_excel('jobData.xls', encoding = 'utf-8')
datas_copy = datas
datas_copy = datas_copy[~datas_copy['工作经验要求'].str.contains('天/周')] # 去掉实习工作
grouped_exp = datas_copy.groupby(datas_copy['工作经验要求']) # 按工作经验分组
grouped_exp_count = grouped_exp['工作经验要求'].agg(['count']) # 统计不同分组的数量
grouped_exp_count.reset_index(inplace = True)
attr = []
value = []
for i in range(grouped_exp_count.shape[0]):
attr.append(grouped_exp_count['工作经验要求'][i])
value.append(str(grouped_exp_count['count'][i])) #将 int 数字转化为 string才能显示图片
pie = (
Pie()
.add(
"",
[list(z) for z in zip(attr, value)],
radius=["40%", "75%"]
)
.set_global_opts(
title_opts=opts.TitleOpts(title="工作经验要求"),
legend_opts=opts.LegendOpts(
orient="vertical", pos_top="15%", pos_left="2%"
)
)
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
)
return pie


edu_pie = edu_require()
edu_pie.render("学历要求饼图.html")
exp_pie = exp_require()
exp_pie.render("工作经验要求饼图.html")
#make_snapshot(snapshot, edu_pie.render(), "学历要求饼图.png") # 使用此语句可直接生成图片
#make_snapshot(snapshot, exp_pie.render(), "工作经验要求饼图.png") # 使用此语句可直接生成图片

2.4 工作种类、主要企业、行业分布

  分析完学历与工作经验,我们来分析一下这些工作主要包括哪些种类,也就是说“自动驾驶”的招聘岗位主要包括哪些,可以为求职者提供学习的方向。为了更好地展示数据分析的成果,我们使用了优秀的开源包jieba以及强大、方便的可视化工具pyecharts展示,根据“工作名”这一项数据项先进行分词,然后绘制了词云如图2-6所示。

图2-6 “自动驾驶”主要岗位种类分析
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import pandas as pd
from pyecharts import options as opts
from pyecharts.charts import Page, WordCloud
from pyecharts.globals import SymbolType
import jieba
import re
from collections import Counter


def job_title():
datas = pd.read_excel('jobData.xls', encoding = 'utf-8')
datas_copy = datas
text = ''.join(datas_copy['岗位'])
requirements = [word for word in jieba.cut(text, cut_all=True)] # 全模式分词
requirements_top = Counter(requirements) # Counter()函数对str进行统计
requirements_top50 = requirements_top.most_common(50) # 统计最多的50个 ,most_common返回(string , count)的数据形式
c = (
WordCloud()
.add("", requirements_top50, word_size_range=[20, 100], shape=SymbolType.DIAMOND)
.set_global_opts(title_opts=opts.TitleOpts(title="主要岗位名称"))
)
return c

job_title = job_title()
job_title.render("主要岗位名称.html")

  从图中可以看出,算法规划感知控制嵌入式等关键词频率较高,所以想要从事这一领域的工作,可以多多关注和学习这些领域的知识。为以后的求职做好准备,打下基础。
  那么哪些公司是招聘的大户呢?即招聘岗位数量较多的企业有哪些?我们使用同样的方法绘制了基于企业招聘数量的词云如图2-7所示。

图2-7 “自动驾驶”主要招聘企业
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import pandas as pd
from pyecharts import options as opts
from pyecharts.charts import Page, WordCloud
from pyecharts.globals import SymbolType

def company_count():
datas = pd.read_excel('jobData.xls', encoding = 'utf-8')
datas_copy = datas
grouped_company = datas_copy.groupby(datas_copy['招聘公司']) # 按招聘公司分组
grouped_company_count = grouped_company['招聘公司'].agg(['count']) # 统计不同分组的数量
grouped_company_count.reset_index(inplace = True)
company_data = [(grouped_company_count['招聘公司'][i],str(grouped_company_count['count'][i])) \
for i in range(grouped_company_count.shape[0])]
# 是否要将数字转化为str

c = (
WordCloud()
.add("", company_data, word_size_range=[20, 100], shape=SymbolType.DIAMOND)
.set_global_opts(title_opts=opts.TitleOpts(title="主要的招聘公司"))
)
return c

company_count = company_count()
company_count.render("主要的招聘公司.html")
#make_snapshot(snapshot, company_count.render(), "主要的招聘公司.png") # 使用此语句可直接生成图片

  可以看出,招聘数量排在前几位的分别有禾多科技、深兰科技坎德拉51VR武汉光庭科技易航等公司,互联网大厂腾讯、华为,传统车厂吉利集团紧随其后,还有很多年轻的企业也有上榜。

  这些岗位所属的行业又有哪些呢?我们使用同样的方法统计如图2-8所示。

图2-8 自动驾驶招聘行业分布
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import pandas as pd
from pyecharts import options as opts
from pyecharts.charts import Page, WordCloud
from pyecharts.globals import SymbolType

def industry():
datas = pd.read_excel('jobData.xls', encoding = 'utf-8')
datas_copy = datas
grouped_industry = datas_copy.groupby(datas_copy['所属行业']) # 按所属行业分组
grouped_industry_count = grouped_industry['所属行业'].agg(['count']) # 统计不同分组的数量
grouped_industry_count.reset_index(inplace = True)
industry_data = [(grouped_industry_count['所属行业'][i],str(grouped_industry_count['count'][i])) \
for i in range(grouped_industry_count.shape[0])]
c = (
WordCloud()
.add("", industry_data, word_size_range=[20, 100], shape=SymbolType.DIAMOND)
.set_global_opts(title_opts=opts.TitleOpts(title="自动驾驶岗位行业分布"))
)
return c

industry_distribution = industry()
industry_distribution.render("自动驾驶岗位行业分布.html")
#make_snapshot(snapshot, industry_distribution.render(), "自动驾驶岗位行业分布.png") # 使用此语句可直接生成图片

  从图中可以看出现在“自动驾驶”的企业所示行业多为“计算机互联网”、“智能硬件”以及“汽车生产”行业,这三类行业是招聘的主力军。

三、总结与讨论

3.1 总结

从两个方面进行总结,

  • 首先是内容上:从数据的分析中对于自动驾驶岗位的招聘需求有了进一步的认识,自动驾驶相关岗位主要的工作内容有算法、规划、感知、控制、嵌入式,北京、江浙沪(包邮区)和深圳是主要的工作地点,全国范围内的平均薪资为18422元/月,自动驾驶岗位更加看重工作经验、学历多数要求为本科,所在行业一般为计算机互联网、智能硬件以及汽车生产,招聘需求较多的企业有禾多科技、深兰科技、坎德拉、51VR、武汉光庭科技、易航等公司。

  • 其次是技术上总结:
    在数据获取中学会使用开发者工具发现网页规律;在数据解析中学会使用xpathbeautifulSoup;数据分析中学会使用pyecharts绘制多种有趣的可视化图片,学会使用jieba包统计词频。

3.2 遇到的问题

  本文一开始想要获取更详细的工作职责工作技能要求的数据,在爬取详情页的过程中发现BOSS直聘在请求详情页时每次的请求都会产生不同的cookie,否则无法获取想要的html,会跳转到其他页面,经过google查询已经有前辈发现了这个问题,但是还未找到解决的反反爬方法(魔高一尺道高一丈)。所以改为爬取较为容易获取的详情页面。

3.3 不足之处

  本文仅仅分析了BOSS直聘一家的数据,数据来源与实际情况有一定的差别,但是能体现一定的代表性,未来可以进行多家招聘网站(如智联招聘、51job招聘,前程无忧等)的数据爬取,提高数据的可信度。

3.4 未来工作

  目前已经完成数据的获取、分析、统计、可视化,未来还可以对数据之间的相关性进行建模分析,得出有意思、有价值的结论。(例如,哪些数据对薪资有影响?)

致谢

  本文的主要方法与技术代码参考了网络上的博客,在此一并致谢!

参考文献

[1] LI D, MEI H, YI S, et al. ECharts: A declarative framework for rapid construction of web-based visualization ☆ [J]. Visual Informatics, 2018, S2468502X18300068-.

[2] Python爬取岗位数据并分析

[3] Python3 + xpath + excel 实现对boss直聘网的爬取

[4] BOSS直聘网站数据分析岗位信息爬取