本次所以的要求来自:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/3075
前言
本次作业是爬取拉勾网python相关岗位的信息,通过爬取岗位id、城市、公司全名、福利待遇、工作地点、学历要求、工作类型、发布时间、职位名称、薪资、工作年限等数据并对其进行数据分析从而得出相应结论。
网页爬虫
1.代理IP
在爬取数据之前我们可以考虑使用代理ip进行爬取,所以这里我写了一段代码检测ip的有效性,这里我使用的是西刺免费代理ip进行测试。不过在测试中我发现可用的免费代理ip少之又少,并且时效性较短,用起来不太方便,所以如果有专门的爬虫需求的人可以考虑使用付费ip。
测试代理ip时效性代码如下:
import requests
import random
proxies = {'http': ''}
def loadip():
url='https: // proxy.horocn.com / api / proxies?order_id = 3JXK1633928414619951 & num = 20 & format = text & line_separator = win & can_repeat = yes'
req=requests.get(url)
date=req.json()
ipdate2=date['msg']
global ipdate
ipdate.extend(ipdate2)
print(ipdate)
def getproxies():
b=random.choice(ipdate)
d = '%s:%s' % (b['ip'], b['port'])
global proxies
proxies['http']=d
global msg
msg=b
loadip()
getproxies()
print(proxies)
2.拉勾网python相关岗位爬虫
测试完代理IP之后,我们就可以开始正式对拉勾网python相关岗位的信息进行爬虫了。拉勾网python相关岗位网页爬虫代码如下所示:
(注意:在下面的 ip_list 中的代理IP到现在为止应该已经失效了,所以如果还要使用代理IP的话需要重新找新的代理IP)
1 # encoding: utf-8
2 import json
3 import requests
4 import xlwt
5 import time
6 import random
7
8 def GetUserAgent():
9 '''
10 功能:随机获取HTTP_User_Agent
11 '''
12 user_agents=[
13 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
14 "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
15 "Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
16 "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
17 "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
18 "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
19 "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
20 "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
21 "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
22 "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
23 "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
24 "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5",
25 "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6",
26 "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
27 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20",
28 "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",
29 "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11",
30 "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER",
31 "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; LBBROWSER)",
32 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E; LBBROWSER)",
33 "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 LBBROWSER",
34 "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)",
35 "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; QQBrowser/7.0.3698.400)",
36 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)",
37 "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; 360SE)",
38 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)",
39 "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)",
40 "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1",
41 "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1",
42 "Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; zh-cn) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5",
43 "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0b13pre) Gecko/20110307 Firefox/4.0b13pre",
44 "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:16.0) Gecko/20100101 Firefox/16.0",
45 "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11",
46 "Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10"
47 ]
48 user_agent = random.choice(user_agents)
49 return user_agent
50
51 # 获取存储职位信息的json对象,遍历获得公司名、福利待遇、工作地点、学历要求、工作类型、发布时间、职位名称、薪资、工作年限
52 def get_json(url, datas):
53 user_agent = GetUserAgent()
54 ip_list = [
55 {"http":"http://138.255.165.86:40600"},
56 {"http":"http://195.122.185.95:3128"},
57 {"http":"http://185.203.18.188:3128"},
58 {"http":"http://103.55.88.52:8080"}
59 ]
60 proxies=random.choice(ip_list)
61 my_headers = {
62 "User-Agent": user_agent,
63 "Referer": "https://www.lagou.com/jobs/list_Python?city=%E5%85%A8%E5%9B%BD&cl=false&fromSearch=true&labelWords=&suginput=",
64 "Content-Type": "application/x-www-form-urlencoded;charset = UTF-8"
65 }
66 time.sleep(5)
67 ses = requests.session() # 获取session
68 ses.headers.update(my_headers) # 更新
69 ses.proxies.update(proxies)
70
71 cookie_dict = dict()
72 ses.cookies.update(cookie_dict)
73
74 ses.get(
75 "https://www.lagou.com/jobs/list_python?city=%E5%85%A8%E5%9B%BD&cl=false&fromSearch=true&labelWords=&suginput=",headers=my_headers)
76 time.sleep(5)
77 content = ses.post(url=url, data=datas)
78 result = content.json()
79 info = result['content']['positionResult']['result']
80 info_list = []
81 for job in info:
82 information = []
83 information.append(job['positionId']) # 岗位对应ID
84 information.append(job['city']) # 岗位对应城市
85 information.append(job['companyFullName']) # 公司全名
86 information.append(job['companyLabelList']) # 福利待遇
87 information.append(job['district']) # 工作地点
88 information.append(job['education']) # 学历要求
89 information.append(job['firstType']) # 工作类型
90 information.append(job['formatCreateTime']) # 发布时间
91 information.append(job['positionName']) # 职位名称
92 information.append(job['salary']) # 薪资
93 information.append(job['workYear']) # 工作年限
94 info_list.append(information)
95 # 将列表对象进行json格式的编码转换,其中indent参数设置缩进值为2
96 # print(json.dumps(info_list, ensure_ascii=False, indent=2))
97 # print(info_list)
98 return info_list
99
100
101 def main():
102 page = int(input('请输入你要抓取的页码总数:'))
103 # kd = input('请输入你要抓取的职位关键字:')
104 # city = input('请输入你要抓取的城市:')
105
106 info_result = []
107 title = ['岗位id', '城市', '公司全名', '福利待遇', '工作地点', '学历要求', '工作类型', '发布时间', '职位名称', '薪资', '工作年限']
108 info_result.append(title)
109 for x in range(56, page + 1):
110 url = 'https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false'
111 # 请求参数,pn参数是页数,kd参数是职位关键字
112 datas = {
113 'first': 'false',
114 'pn': x,
115 'kd': 'python',
116 }
117 try:
118 info = get_json(url, datas)
119 info_result = info_result + info
120 print("第%s页正常采集" % x)
121 except Exception as msg:
122 print("第%s页出现问题" % x)
123
124 # 创建workbook,即excel
125 workbook = xlwt.Workbook(encoding='utf-8')
126 # 创建表,第二参数用于确认同一个cell单元是否可以重设值
127 worksheet = workbook.add_sheet('lagoupy', cell_overwrite_ok=True)
128 for i, row in enumerate(info_result):
129 # print(row)
130 for j, col in enumerate(row):
131 # print(col)
132 worksheet.write(i, j, col)
133 workbook.save('lagoupy.xls')
134
135
136 if __name__ == '__main__':
137 main()
数据分析
在执行完上述爬虫代码之后,我们可以得到一个lagoupy.xls的文件,里面存储的是我们爬虫的结果,总共爬取了2640条数据,如下图所示。
1.数据预处理
由于我们爬取下来的数据并不是全部都是我们所要的,或者是有一些数据需要进行加工才可以用到,这时候数据的预处理就必不可少了。
① 删除重复值
如果数据中存在重复记录, 而且重复数量较多时, 势必会对结果造成影响, 因此我们应当首先处理重复值。打开lagoupy.xls文件,选中岗位id这一列数据,选择数据——>删除重复值,对重复值进行删除,删除重复值后,我们可以发现,数据从原来的2641条变成2545条。
② 过滤无效数据
由于某些数据对我们的数据分析并无用处,所以对于这一部分数据我们可以不要,在这里发布时间是无效数据,所以我们可以直接删除这一列。
③ 加工数据
由于爬取下来的数据中薪资这一列是类似于15k-30k这样的数据,并且这样的数据不能满足我们的分析需求, 因此需要对薪资这一列数据进行分列操作,把薪资这一列分裂成最低工资和最高工资,接着我们可以利用最低工资和最高工资计算出平均工资,并把平均工资作为新的一列添加进数据表中。
经过上述三个步骤后,我们最终可以得到一个经过数据预处理之后的lagoupy.xls文件,经过预处理之后我们的数据条数也从原来的2640条变成了2544条,如下图所示。
2.数据分析
① 学历要求
根据所统计的数据来看,python对学历要求以本科和大专居多,其中本科以2071名列第一 。
② 工作类型
我们把python相关的工作大体分为八类,分别是产品|需求|项目类、技术类、教育|培训类、金融类、开发|测试|运维类、生产|加工|制造类、运营|编辑|客服类,其中以开发|测试|运维类这一类工作类型的人才需求多,占绝对优势。
③ 工作城市
统计各个城市对python相关岗位的需求情况,由下图我们不难发现,北京、上海、深圳、广州、杭州、成都这六个城市对python这一相关行业的需求比较大。
④ 工作年限
对python相关岗位的工作年限进行统计,我们可以发现企业对于python的工作经验要求以3-5年、1-3年这两种工作年限需求居多。
⑤ 城市与工资——较发达的城市工资水平较高
由下图可知,城市与工资有一定的关系,在北上广深等发达的城市里,python相关职位的工资较高。
⑥ 学历与工资——学历越高工资越高
由图可知,整体上看学历越高工资越高。由于博士学历只有一条数据,所以这里可能因为数据不足的原因导致分析结果有所误差。
⑦ 工作年限与工资——工作年限越长工资越高
由图可知,工作年限越长,工资越高。其中因为10年以上只有一条数据,所以对于10年以上的工作经验所统计出来的数据可能有所偏差。
⑧ 福利待遇
首先,我们新建一个fuli.txt的文件,把福利待遇这一列粘贴到fuli.txt中并保存,如下图所示。
其次,我们对fuli.txt进行词频统计,把词频统计生成的结果存为fuli.csv文件。福利待遇词频统计代码如下所示:
1 # -*- coding: utf-8 -*-
2 import jieba # 加载停用表
3 import pandas as pd
4 from wordcloud import WordCloud
5 import matplotlib.pyplot as plt
6
7 # 分解
8 article = open("fuli.txt", "r", encoding='utf-8').read()
9 jieba.add_word('五险一金')
10 jieba.add_word('七险一金')
11 jieba.add_word('六险一金')
12 jieba.add_word('带薪年假')
13 jieba.add_word('美女多')
14 jieba.add_word('帅哥多')
15 jieba.add_word('年底双薪')
16 jieba.add_word('绩效奖金')
17 jieba.add_word('股票期权')
18 jieba.add_word('扁平管理')
19 jieba.add_word('弹性工作')
20 jieba.add_word('管理规范')
21 jieba.add_word('岗位晋升')
22 jieba.add_word('技能培训')
23 jieba.add_word('节日礼物')
24 jieba.add_word('带薪年假')
25 jieba.add_word('定期体检')
26 jieba.add_word('通讯津贴')
27 jieba.add_word('领导好')
28 jieba.add_word('年度旅游')
29 jieba.add_word('交通补助')
30 jieba.add_word('年终分红')
31 jieba.add_word('丰盛三餐')
32 jieba.add_word('发展空间大')
33 jieba.add_word('午餐补助')
34 jieba.add_word('快速发展')
35 jieba.add_word('发展前景好')
36 jieba.add_word('专项奖金')
37 jieba.add_word('免费班车')
38 jieba.add_word('丰盛三餐')
39 jieba.add_word('科技大牛')
40 words = jieba.cut(article, cut_all=False) # 统计词频
41 stayed_line = {}
42 for word in words:
43 if len(word) == 1:
44 continue
45 else:
46 stayed_line[word] = stayed_line.get(word, 0) + 1
47
48 print(stayed_line) # 排序
49 xu = list(stayed_line.items())
50 # print(xu)
51
52 #存到csv文件中
53 pd.DataFrame(data=xu).to_csv("fuli.csv",encoding="utf_8_sig")
执行完上述代码后,我们可以生成一个fuli.csv文件,如下图所示。
根据所生成fuli.csv文件使用WordArt对福利待遇生成中文词云,结果如下图所示,我们可以发现python相关岗位的福利待遇中,被提及最多的词汇分别是带薪年假、股票期权、绩效奖金、年底双薪、节日礼物、技能培训、定期体检、五险一金等。
来源:oschina
链接:https://my.oschina.net/u/4415254/blog/4326402