【大数据应用技术】作业八|爬虫综合大作业(下)

左心房为你撑大大i 提交于 2020-08-07 15:11:07

本次所以的要求来自: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相关岗位的福利待遇中,被提及最多的词汇分别是带薪年假、股票期权、绩效奖金、年底双薪、节日礼物、技能培训、定期体检、五险一金等。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!