冰岛 - Photoby 南山
本文转自公众号 Python 攻城狮
摘要:爬取分析拉勾网 Python 职位 5 月最新招聘信息。
多数人学 Python 的目的都是想找一个好工作, 日常学习之外,就很有必要多关注一下网上的 Python 岗位招聘需求,一方面检验下自己的学习方向是否正确,二一个是看看薪资如何,适当给自己打打鸡血。对于我这种转行的来说就更关注这块儿,每隔一阵都会看看市场行情。网上一条条地看有点麻烦,也看不出个总体趋势,所以就用 Python 来爬虫然后分析下。
下面以拉勾网 5 月份招聘信息为例,爬取分析 Pyton 相关岗位数据,看看目前的薪水和岗位分布。总体来说爬取难度不大,先说下容易遇到的坑,然后就上完整代码。
先说下数据采集过程中遇到的问题,首先请求头是一定要伪装的,否则第一步就会给你弹出你的请求太频繁,请稍后再试,其次网站具有多重反爬策略,解决方案是每次先获取 session 然后更新我们的 session 进行抓取,最后拿到了想要的数据。
Chrome 浏览器右键检查查看network,找到链接https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false
可以看到返回的数据正是页面的 Python 招聘详情,直接打开发现提示:
1{"status":false,"msg":"您操作太频繁,请稍后再访问","clientIp":"124.77.161.207","state":2402}"status":false,"msg":"您操作太频繁,请稍后再访问","clientIp":"124.77.161.207","state":2402}
img
操作过于频繁了,来分析下请求的报文:
img img可以看到请求是以post
的方式传递的,同时传递了参数
1datas = {23 'first': 'false',45 'pn': x,67 'kd': 'python',89 }
2
3 'first': 'false',
4
5 'pn': x,
6
7 'kd': 'python',
8
9 }
同时不难发现每次点击下一页都会同时发送一条get
请求
经过探索,发现这个 get 请求和 post 请求是一致的,那么问题就简单许多,整理一下思路:
img下面就可以写爬虫代码了,完整代码见文末。
代码里默认设置了几项关键词:岗位:python
搜索范围:全国。你可以自行修改,比如爬取「数据分析」、「机器学习」之类的关键词岗位,也可以搜索特定某个城市的。
爬取过程:
日志记录很快就爬取好,得到这样一份 Excel 表格:
img下面用pyecharts
来简单分析下。
pyecharts 是一款将 python 与 echarts 结合的强大的数据可视化工具,包含多种图表:
用户自定义
另外需要注意的是从版本 0.3.2 开始,为了缩减项目本身的体积以及维持 pyecharts 项目的轻量化运行,pyecharts 将不再自带地图 js 文件。如用户需要用到地图图表(Geo、Map),可自行安装对应的地图文件包。
全球国家地图: echarts-countries-pypkg (1.9MB): 世界地图和 213 个国家,包括中国地图
中国省级地图: echarts-china-provinces-pypkg (730KB):23 个省,5 个自治区
中国市级地图: echarts-china-cities-pypkg (3.8MB):370 个中国城市
也可以使用命令进行安装
1pip install echarts-countries-pypkg23pip install echarts-china-provinces-pypkg45pip install echarts-china-cities-pypkg
2
3pip install echarts-china-provinces-pypkg
4
5pip install echarts-china-cities-pypkg
数据可视化(代码+展示)
各城市招聘数量
1from pyecharts import Bar 2 3 4 5city_nms_top10 = ['北京', '上海', '深圳', '成都', '杭州', '广州', '武汉', '南京', '苏州', '郑州', '天津', '西安', '东莞', '珠海', '合肥', '厦门', '宁波', 6 7 '南宁', '重庆', '佛山', '大连', '哈尔滨', '长沙', '福州', '中山'] 8 9city_nums_top10 = [149, 95, 77, 22, 17, 17, 16, 13, 7, 5, 4, 4, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1]10111213bar = Bar("Python 岗位", "各城市数量")1415bar.add("数量", city_nms, city_nums, is_more_utils=True)1617# bar.print_echarts_options() # 该行只为了打印配置项,方便调试时使用1819bar.render('Python 岗位各城市数量.html') # 生成本地 HTML 文件from pyecharts import Bar
2
3
4
5city_nms_top10 = ['北京', '上海', '深圳', '成都', '杭州', '广州', '武汉', '南京', '苏州', '郑州', '天津', '西安', '东莞', '珠海', '合肥', '厦门', '宁波',
6
7 '南宁', '重庆', '佛山', '大连', '哈尔滨', '长沙', '福州', '中山']
8
9city_nums_top10 = [149, 95, 77, 22, 17, 17, 16, 13, 7, 5, 4, 4, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1]
10
11
12
13bar = Bar("Python 岗位", "各城市数量")
14
15bar.add("数量", city_nms, city_nums, is_more_utils=True)
16
17# bar.print_echarts_options() # 该行只为了打印配置项,方便调试时使用
18
19bar.render('Python 岗位各城市数量.html') # 生成本地 HTML 文件
北京的岗位需求遥遥领先,其次上海、深圳。
1from pyecharts import Geo 2 3 4 5city_datas = [('北京', 149), ('上海', 95), ('深圳', 77), ('成都', 22), ('杭州', 17), ('广州', 17), ('武汉', 16), ('南京', 13), ('苏州', 7), 6 7 ('郑州', 5), ('天津', 4), ('西安', 4), ('东莞', 3), ('珠海', 2), ('合肥', 2), ('厦门', 2), ('宁波', 1), ('南宁', 1), ('重庆', 1), 8 9 ('佛山', 1), ('大连', 1), ('哈尔滨', 1), ('长沙', 1), ('福州', 1), ('中山', 1)]1011geo = Geo("Python 岗位城市分布地图", "数据来源拉勾", title_color="#fff",1213 title_pos="center", width=1200,1415 height=600, background_color='#404a59')1617attr, value = geo.cast(city_datas)1819geo.add("", attr, value, visual_range=[0, 200], visual_text_color="#fff",2021 symbol_size=15, is_visualmap=True)2223geo.render("Python 岗位城市分布地图 _scatter.html")242526272829geo = Geo("Python 岗位城市分布地图", "数据来源拉勾", title_color="#fff",3031 title_pos="center", width=1200,3233 height=600, background_color='#404a59')3435attr, value = geo.cast(city_datas)3637geo.add("", attr, value, type="heatmap", visual_range=[0, 10], visual_text_color="#fff",3839 symbol_size=15, is_visualmap=True)4041geo.render("Python 岗位城市分布地图 _heatmap.html")from pyecharts import Geo
2
3
4
5city_datas = [('北京', 149), ('上海', 95), ('深圳', 77), ('成都', 22), ('杭州', 17), ('广州', 17), ('武汉', 16), ('南京', 13), ('苏州', 7),
6
7 ('郑州', 5), ('天津', 4), ('西安', 4), ('东莞', 3), ('珠海', 2), ('合肥', 2), ('厦门', 2), ('宁波', 1), ('南宁', 1), ('重庆', 1),
8
9 ('佛山', 1), ('大连', 1), ('哈尔滨', 1), ('长沙', 1), ('福州', 1), ('中山', 1)]
10
11geo = Geo("Python 岗位城市分布地图", "数据来源拉勾", title_color="#fff",
12
13 title_pos="center", width=1200,
14
15 height=600, background_color='#404a59')
16
17attr, value = geo.cast(city_datas)
18
19geo.add("", attr, value, visual_range=[0, 200], visual_text_color="#fff",
20
21 symbol_size=15, is_visualmap=True)
22
23geo.render("Python 岗位城市分布地图 _scatter.html")
24
25
26
27
28
29geo = Geo("Python 岗位城市分布地图", "数据来源拉勾", title_color="#fff",
30
31 title_pos="center", width=1200,
32
33 height=600, background_color='#404a59')
34
35attr, value = geo.cast(city_datas)
36
37geo.add("", attr, value, type="heatmap", visual_range=[0, 10], visual_text_color="#fff",
38
39 symbol_size=15, is_visualmap=True)
40
41geo.render("Python 岗位城市分布地图 _heatmap.html")
各个城市招聘情况
1from pyecharts import Pie 2 3 4 5city_nms_top10 = ['北京', '上海', '深圳', '成都', '广州', '杭州', '武汉', '南京', '苏州', '郑州'] 6 7city_nums_top10 = [149, 95, 77, 22, 17, 17, 16, 13, 7, 5] 8 9pie = Pie()1011pie.add("", city_nms_top10, city_nums_top10, is_label_show=True)1213# pie.show_config()1415pie.render('Python 岗位各城市分布饼图.html')from pyecharts import Pie
2
3
4
5city_nms_top10 = ['北京', '上海', '深圳', '成都', '广州', '杭州', '武汉', '南京', '苏州', '郑州']
6
7city_nums_top10 = [149, 95, 77, 22, 17, 17, 16, 13, 7, 5]
8
9pie = Pie()
10
11pie.add("", city_nms_top10, city_nums_top10, is_label_show=True)
12
13# pie.show_config()
14
15pie.render('Python 岗位各城市分布饼图.html')
北上深的岗位明显碾压其它城市,这也反映出为什么越来越多的 it 从业人员毕业以后相继奔赴一线城市,除了一线城市的薪资高于二三线这个因素外,还有一个最重要的原因
供需关系
因为一线岗位多,可选择性也就比较高,反观二三线的局面,很有可能你跳个几次槽,发现同行业能呆的公司都待过了。
img由此可见,python 的岗位薪资多数在 10k~20k,想从事 Python 行业的可以把工作年限和薪资结合起来参考一下。
img从工作年限来看,1-3 年或者 3-5 年工作经验的招聘比较多,而应届生和一年以下的寥寥无几,对实习生实在不太友好,学历也普遍要求本科,多数公司都很重视入职人员学历这点毋容置疑,虽然学历不代表一切,但是对于一个企业来说,想要短时间内判断一个人的能力,最快速有效的方法无疑是从学历入手。学历第一关,面试第二关。
但是,这不代表学历不高的人就没有好的出路,现在的大学生越来越多,找工作也越来越难,竞争越来越激烈,即使具备高学历,也不能保证你一定可以找到满意的工作,天道酬勤,特别是 it 这个行业,知识的迭代,比其他行业来的更频密。不断学习,拓展自己学习的广度和深度,才是最正确的决定。
通过以上简单的分析,不难看出大多数岗位是需要有工作经验的,如果你没有相关工作经验,那学习的时候就要刻意尝试独立做几个完整项目,爬虫也好,数据分析也好都行,在这个过程中培养自己思考和解决问题的能力。持续不断的学习,才是对自己未来最好的投资。
完整代码如下:
1#!/usr/bin/env python3.4
2
3# encoding: utf-8
4
5"""
6
7Created on 19-5-05
8
9@title: ''
10
11@author: Xusl
12
13"""
14
15import json
16
17import requests
18
19import xlwt
20
21import time
22
23
24
25
26
27# 获取存储职位信息的 json 对象,遍历获得公司名、福利待遇、工作地点、学历要求、工作类型、发布时间、职位名称、薪资、工作年限
28
29def get_json(url, datas):
30
31 my_headers = {
32
33 "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36",
34
35 "Referer": "https://www.lagou.com/jobs/list_Python?city=%E5%85%A8%E5%9B%BD&cl=false&fromSearch=true&labelWords=&suginput=",
36
37 "Content-Type": "application/x-www-form-urlencoded;charset = UTF-8"
38
39 }
40
41 time.sleep(5)
42
43 ses = requests.session() # 获取 session
44
45 ses.headers.update(my_headers) # 更新
46
47 ses.get("https://www.lagou.com/jobs/list_python?city=%E5%85%A8%E5%9B%BD&cl=false&fromSearch=true&labelWords=&suginput=")
48
49 content = ses.post(url=url, data=datas)
50
51 result = content.json()
52
53 info = result['content']['positionResult']['result']
54
55 info_list = []
56
57 for job in info:
58
59 information = []
60
61 information.append(job['positionId']) # 岗位对应 ID
62
63 information.append(job['city']) # 岗位对应城市
64
65 information.append(job['companyFullName']) # 公司全名
66
67 information.append(job['companyLabelList']) # 福利待遇
68
69 information.append(job['district']) # 工作地点
70
71 information.append(job['education']) # 学历要求
72
73 information.append(job['firstType']) # 工作类型
74
75 information.append(job['formatCreateTime']) # 发布时间
76
77 information.append(job['positionName']) # 职位名称
78
79 information.append(job['salary']) # 薪资
80
81 information.append(job['workYear']) # 工作年限
82
83 info_list.append(information)
84
85 # 将列表对象进行 json 格式的编码转换,其中 indent 参数设置缩进值为 2
86
87 # print(json.dumps(info_list, ensure_ascii=False, indent=2))
88
89 # print(info_list)
90
91 return info_list
92
93
94
95
96
97def main():
98
99 page = int(input('请输入你要抓取的页码总数:'))
100
101 # kd = input('请输入你要抓取的职位关键字:') # 可以自行调整关键字
102
103 # city = input('请输入你要抓取的城市:') # 可以自行调整关键字
104
105
106
107 info_result = []
108
109 title = ['岗位 id', '城市', '公司全名', '福利待遇', '工作地点', '学历要求', '工作类型', '发布时间', '职位名称', '薪资', '工作年限']
110
111 info_result.append(title)
112
113 for x in range(1, page+1):
114
115 url = 'https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false'
116
117 datas = {
118
119 'first': 'false',
120
121 'pn': x,
122
123 'kd': 'python',
124
125 }
126
127 try:
128
129 info = get_json(url, datas)
130
131 info_result = info_result + info
132
133 print("第%s 页正常采集" % x)
134
135 except Exception as msg:
136
137 print("第%s 页出现问题" % x)
138
139
140
141 # 创建 workbook,即 excel
142
143 workbook = xlwt.Workbook(encoding='utf-8')
144
145 # 创建表,第二参数用于确认同一个 cell 单元是否可以重设值
146
147 worksheet = workbook.add_sheet('lagouzp', cell_overwrite_ok=True)
148
149 for i, row in enumerate(info_result):
150
151 # print(row)
152
153 for j, col in enumerate(row):
154
155 # print(col)
156
157 worksheet.write(i, j, col)
158
159 workbook.save('lagouzp.xls')
160
161
162if __name__ == '__main__':
163
164 main()
/今日留言主题/
你学 Python 多久了?
(留言格式:Dayxx:blahblah)