一、选题背景
随着互联网的发展,数据分析岗位在各行各业中的需求越来越大。拉勾网作为国内知名的招聘网站,其上的数据分析岗位信息具有很高的参考价值。通过对拉勾网上的数据分析岗位进行数据分析,可以了解当前数据分析岗位的市场情况,为求职者提供有价值的参考信息,同时也可以为企业和招聘方提供人才需求和供给的分析依据。预期目标是通过对拉勾网上的数据分析岗位数据进行分析,揭示数据分析岗位的市场需求、薪资水平、技能要求等方面的特点,为企业和个人提供有针对性的建议。
二、主题式网络爬虫设计方案
1、名称:拉勾网—数据分析岗位爬取+数据分析可视化
2、爬取的数据内容:职位id,岗位名称,公司全称,公司简称,公司规模,融资阶段,公司标签,工作城市,工作地区,学历要求,薪资范围,工作经验,岗位描述,岗位福利
3、爬虫设计方案概述:实现思路:本次案例主要使用Python的requests库发送请求,获取拉勾网的数据分析师岗位页面的HTML内容,使用Python的BeautifulSoup库解析HTML内容,提取出需要的信息后保存到本地文件中,随后用pandas库进行数据分析和可视化
技术难点:
网站爬虫的反爬机制,超过一定次数后会限制访问
对爬取的信息进行数据可视化
三、主题式页面结构特征分析
1.主题页面的结构与特征分析
2.html页面解析
<div class="list_item_top">职位名称
<span class="add">工作地点
<div class="li_b_l">学历要求和薪资
<span class="money">
</div><div class="li_b_r"“>公司特点
<div class="company_name">公司名称
<div class="industry">公司人数
3.节点(标签)查找方法与遍历方法
查找方法:find
遍历方法:for
四、网络爬虫程序设计
爬取内容
1 # 导入包 2 import requests 3 import json 4 import csv 5 import time 6 7 8 def get_lagou_data(url): 9 # 构建请求头 10 headers = { 11 'origin': 'https://www.lagou.com', 12 'referer': 'https://www.lagou.com/jobs/list_%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E5%B8%88/p-city_0?', 13 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36', 14 'cookie': 'user_trace_token=20210502113751-6e94202a-add9-4490-a573-962f1266be77; __lg_stoken__=67a7d1c84b86ed537c54e3d69977afad92d05cf285b726ae40509062a087e14b6a64f94fb5ae629a24b2062432407a1f3ab94acbc65df49ce63d5e4fcf6d5c7b009691ec2cf2; JSESSIONID=ABAAABAABEIABCI0E4D2CDFFC692EEF09DC3C1487ADD5A8; WEBTJ-ID=2021052%E4%B8%8A%E5%8D%8811:37:54113754-1792b276d6b551-08fbf0bfc4784e-113a6054-1024000-1792b276d6c928; X_HTTP_TOKEN=02cc1cc330da72df576629916129e561f3ad981774; PRE_UTM=; PRE_HOST=; PRE_LAND=https%3A%2F%2Fwww.lagou.com%2Fjobs%2Flist%5F%25E6%2595%25B0%25E6%258D%25AE%25E5%2588%2586%25E6%259E%2590%25E5%25B8%2588%2Fp-city%5F0%3F; PRE_SITE=; LGUID=20210502113756-6daf6df0-2de5-42d2-828e-8cb2feef29bd; LGSID=20210502113756-2910c4b4-69f0-458b-aac5-e1bf59fee8e1; sajssdk_2015_cross_new_user=1; sensorsdata2015session=%7B%7D; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%221792b27744f8eb-04cbd992f837b9-113a6054-1024000-1792b2774503c1%22%2C%22first_id%22%3A%22%22%2C%22props%22%3A%7B%22%24os%22%3A%22MacOS%22%2C%22%24browser%22%3A%22Chrome%22%2C%22%24browser_version%22%3A%2290.0.4430.93%22%7D%2C%22%24device_id%22%3A%221792b27744f8eb-04cbd992f837b9-113a6054-1024000-1792b2774503c1%22%7D; _ga=GA1.2.2141774430.1619926677; _gat=1; Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1619926677; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1619926677; LGRID=20210502113756-9a924450-7598-418b-b731-33046e64120c; _gid=GA1.2.1480471771.1619926677; SEARCH_ID=ab911c2ad61c47f2a94993729604d904' 15 } 16 17 # 用data进行分页爬取 18 for i in range(1, 31): 19 data = { 20 'first': 'true', 21 'pn': i, 22 'kd': '数据分析师' 23 } 24 25 # 请求网页 26 response = requests.post(url=url, headers=headers, data=data, timeout=3) 27 print(response.text) 28 time.sleep(3) # 休息一下 29 30 # json.loads 用于解码 JSON 数据。该函数返回 Python字段的数据类型 31 response = json.loads(response.content) 32 33 # 获取15条数据 34 result_15 = response['content']['positionResult']['result'] 35 36 # 获取每条招聘岗位里面的详细信息 37 for i in result_15: 38 position_id = i['positionId'] # 职位Id 39 position_name = i['positionName'] # 职位名称 40 company_full_name = i['companyFullName'] # 公司全称 41 company_short_name = i['companyShortName'] # 公司简称 42 company_size = i['companySize'] # 公司规模 43 finance_stage = i['financeStage'] # 融资阶段 44 company_label_list = i['companyLabelList'] # 公司标签 45 first_type = i['firstType'] # 第一类型 46 second_type = i['secondType'] # 第二类型 47 third_type = i['thirdType'] # 第三类型 48 position_labels = i['positionLables'] # 职位标签 49 industry_labels = i['industryLables'] # 行业标签 50 create_time = i['createTime'] # 创建时间 51 format_create_time = i['formatCreateTime'] # 格式化创建时间 52 city = i['city'] # 城市 53 district = i['district'] # 地区 54 salary = i['salary'] # 薪水 55 salary_month = i['salaryMonth'] # 工资月份 56 work_year = i['workYear'] # 工作年限 57 job_nature = i['jobNature'] # 工作性质 58 education = i['education'] # 教育背景 59 position_advantage = i['positionAdvantage'] # 岗位优势 60 hi_tags = i['hitags'] # 福利标签 61 62 # 存储数据, 先在当前文件下创建一个叫‘lagou_datas.csv’的文件 63 # 'a' 追加写入,;encoding设置编码格式,防止乱码 ;newline是为了解决写入时新增行与行之间的一个空白行问题 64 with open('./lagou_datas.csv', 'a', encoding='utf_8_sig', newline='') as f: 65 # 写入数据 66 csv_write = csv.writer(f) 67 # 按照以下行顺序写入,是一个列表 68 csv_write.writerow([position_id, position_name, company_full_name, company_short_name, company_size, 69 finance_stage, company_label_list, first_type, second_type, third_type, position_labels, 70 industry_labels, create_time, format_create_time, city, district, salary, salary_month, 71 work_year, job_nature, education, position_advantage, hi_tags]) 72 time.sleep(3) # 休息一下 73 74 75 # 主程序 76 if __name__ == '__main__': 77 # Ajax的URL 78 url = "https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false" 79 80 # 传入URL,调用函数 81 get_lagou_data(url)
2。数据清洗
1 #导入包 2 import pandas as pd 3 import numpy as np 4 import seaborn as sns 5 from pyecharts import Pie 6 from pyecharts import options as opts 7 import matplotlib.pyplot as plt 8 #导入数据 9 path = "C:/data/lagou.csv" 10 df = pd.read_csv(path) 11 # 取出我们进行后续分析所需的字段 12 columns = ["positionName", "companyShortName", "city", "companySize", "education", "financeStage", 13 "industryField", "salary", "workYear", "hitags", "companyLabelList", "job_detail"] 14 df = df[columns].drop_duplicates() #去重 15 # 数据分析相应的岗位数量 16 cond_1 = df["positionName"].str.contains("数据分析") # 职位名中含有数据分析字眼的 17 cond_2 = ~df["positionName"].str.contains("实习") # 剔除掉带实习字眼的 18 df = df[cond_1 & cond_2] 19 df.drop(["positionName"], axis=1, inplace=True) 20 df.reset_index(drop=True, inplace=True)
3、对各城市对数据分析岗位的需求量生成柱状图
1 fig, ax = plt.subplots(figsize=(12,8)) 2 sns.countplot(y="city",order= df["city"].value_counts().index,data=df,color='#3c7f99') 3 plt.box(False) 4 fig.text(x=0.04, y=0.90, s=' 各城市数据分析岗位的需求量 ', 5 fontsize=32, weight='bold', color='white', backgroundcolor='#c5b783') 6 plt.tick_params(axis='both', which='major', labelsize=16) 7 ax.xaxis.grid(which='both', linewidth=0.5, color='#3c7f99') 8 plt.xlabel('') 9 plt.ylabel('')
不同领域对数据分析岗的需求量生成柱形图
1 industry_index = df["industryField"].value_counts()[:10].index 2 industry =df.loc[df["industryField"].isin(industry_index),"industryField"] 3 fig, ax = plt.subplots(figsize=(12,8)) 4 sns.countplot(y=industry.values,order = industry_index,color='#3c7f99') 5 plt.box(False) 6 fig.text(x=0, y=0.90, s=' 细分领域数据分析岗位的需求量(取前十) ', 7 fontsize=32, weight='bold', color='white', backgroundcolor='#c5b783') 8 plt.tick_params(axis='both', which='major', labelsize=16) 9 ax.xaxis.grid(which='both', linewidth=0.5, color='#3c7f99') 10 plt.xlabel('') 11 plt.ylabel('')
各城市薪资水平生成柱状图
1 fig,ax = plt.subplots(figsize=(12,8)) 2 city_order = df.groupby("city")["salary"].mean()\ 3 .sort_values()\ 4 .index.tolist() 5 sns.barplot(x="city", y="salary", order=city_order, data=df, ci=95,palette="RdBu_r") 6 fig.text(x=0.04, y=0.90, s=' 各城市的薪资水平对比 ', 7 fontsize=32, weight='bold', color='white', backgroundcolor='#3c7f99') 8 plt.tick_params(axis="both",labelsize=16,) 9 ax.yaxis.grid(which='both', linewidth=0.5, color='black') 10 ax.set_yticklabels([" ","5k","10k","15k","20k"]) 11 plt.box(False) 12 plt.xlabel('') 13 plt.ylabel('')
一线城市薪资对比图
1 fig,ax = plt.subplots(figsize=(12,8)) 2 fig.text(x=0.04, y=0.90, s=' 一线城市的薪资分布对比 ', 3 fontsize=32, weight='bold', color='white', backgroundcolor='#c5b783') 4 sns.kdeplot(df[df["city"]=='北京']["salary"],shade=True,label="北京") 5 sns.kdeplot(df[df["city"]=='上海']["salary"],shade=True,label="上海") 6 sns.kdeplot(df[df["city"]=='广州']["salary"],shade=True,label="广州") 7 sns.kdeplot(df[df["city"]=='深圳']["salary"],shade=True,label="深圳") 8 plt.tick_params(axis='both', which='major', labelsize=16) 9 plt.box(False) 10 plt.xticks(np.arange(0,61,10), [str(i)+"k" for i in range(0,61,10)]) 11 plt.yticks([]) 12 plt.legend(fontsize = 'xx-large',fancybox=None)
根据不同技能的薪资水平对比绘制箱型图
1 py_rate = df["Python/R"].value_counts(normalize=True).loc[1] 2 sql_rate = df["SQL"].value_counts(normalize=True).loc[1] 3 tableau_rate = df["Tableau"].value_counts(normalize=True).loc[1] 4 excel_rate = df["Excel"].value_counts(normalize=True).loc[1] 5 print("职位技能需求:") 6 print("Python/R:",py_rate) 7 print("SQL:",sql_rate) 8 print("Excel:",excel_rate) 9 print("Tableau:",tableau_rate) 10 def get_level(x): 11 if x["Python/R"] == 1: 12 x["skill"] = "Python/R" 13 elif x["SQL"] == 1: 14 x["skill"] = "SQL" 15 elif x["Excel"] == 1: 16 x["skill"] = "Excel" 17 else: 18 x["skill"] = "其他" 19 return x 20 df = df.apply(get_level,axis=1) 21 fig,ax = plt.subplots(figsize=(12,8)) 22 fig.text(x=0.02, y=0.90, s=' 不同技能的薪资水平对比 ', 23 fontsize=32, weight='bold', color='white', backgroundcolor='#c5b783') 24 sns.boxplot(y="skill",x="salary",data=df.loc[df.skill!="其他"],palette="husl",order=["Python/R","SQL","Excel"]) 25 plt.tick_params(axis="both",labelsize=16) 26 ax.xaxis.grid(which='both', linewidth=0.75) 27 plt.xticks(np.arange(0,61,10), [str(i)+"k" for i in range(0,61,10)]) 28 plt.box(False) 29 plt.xlabel('工资', fontsize=18) 30 plt.ylabel('技能', fontsize=18)
根据不同规模公司的用人需求差异绘制散点图
1 company_size_map = { 2 "2000人以上": 6, 3 "500-2000人": 5, 4 "150-500人": 4, 5 "50-150人": 3, 6 "15-50人": 2, 7 "少于15人": 1 8 } 9 workYear_map = { 10 "5-10年": 5, 11 "3-5年": 4, 12 "1-3年": 3, 13 "1年以下": 2, 14 "应届毕业生": 1 15 } 16 df["company_size"] = df["companySize"].map(company_size_map) 17 df["work_year"] = df["workYear"].map(workYear_map) 18 df = df.sort_values(by="company_size",ascending=True) 19 df_plot = df.loc[~df.work_year.isna()] 20 color_map = { 21 5:"#ff0000", 22 4:"#ffa500", 23 3:"#c5b783", 24 2:"#3c7f99", 25 1:"#0000cd" 26 } 27 df_plot["color"] = df_plot.work_year.map(color_map) 28 df_plot.reset_index(drop=True,inplace=True) 29 def seed_scale_plot(): 30 seeds=np.arange(5)+1 31 y=np.zeros(len(seeds),dtype=int) 32 s=seeds*100 33 colors=['#ff0000', '#ffa500', '#c5b783', '#3c7f99', '#0000cd'][::-1] 34 fig,ax=plt.subplots(figsize=(12,1)) 35 plt.scatter(seeds,y,s=s,c=colors,alpha=0.3) 36 plt.scatter(seeds,y,c=colors) 37 plt.box(False) 38 plt.grid(False) 39 plt.xticks(ticks=seeds,labels=list(workYear_map.keys())[::-1],fontsize=14) 40 plt.yticks(np.arange(1),labels=[' 经验:'],fontsize=16) 41 fig, ax = plt.subplots(figsize=(12, 8)) 42 fig.text(x=0.03, y=0.92, s=' 不同规模公司的用人需求差异 ', fontsize=32, 43 weight='bold', color='white', backgroundcolor='#3c7f99') 44 plt.scatter(df_plot.salary, df_plot["companySize"], s=df_plot["work_year"]*100 ,alpha=0.35,c=df_plot["color"]) 45 plt.scatter(df_plot.salary, df_plot["companySize"], c=df_plot["color"].values.tolist()) 46 plt.tick_params(axis='both', which='both', length=0) 47 plt.tick_params(axis='both', which='major', labelsize=16) 48 ax.xaxis.grid(which='both', linewidth=0.75) 49 plt.xticks(np.arange(0,61,10), [str(i)+"k" for i in range(0,61,10)]) 50 plt.xlabel('工资', fontsize=18) 51 plt.box(False) 52 seed_scale_plot()
根据大公司对技能的要求占比生成柱形图
df_skill = df.loc[(df["companySize"]=="2000人以上")&(df.skill!="其他")]["skill"].value_counts(normalize=True) df_skill fig, ax = plt.subplots(figsize=(12, 6)) sns.barplot(x=df_skill.index,y=df_skill.values, color='#3c7f99') plt.box(False) fig.text(x=0.08, y=0.9, s=' 大公司对技能的要求占比 ', fontsize=32, weight='bold', color='white', backgroundcolor='#c5b783') plt.tick_params(axis='both', which='major', labelsize=16) ax.yaxis.grid(which='both', linewidth=0.5, color='#3c7f99')
爬虫课程设计全部代码如下:
1 # 导入包 2 import requests 3 import json 4 import csv 5 import time 6 # 定义获取拉勾网数据的函数 7 def get_lagou_data(url): 8 # 构建请求头 9 headers = { 10 'origin': 'https://www.lagou.com', 11 'referer': 'https://www.lagou.com/jobs/list_%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E5%B8%8C/p-city_0?', 12 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36', 13 14 'cookie': 'user_trace_token=20210502113751-6e94202a-add9-4490-a573-962f1266be77; __lg_stoken__=67a7d1c84b86ed537c54e3d69977afad92d05cf285b726ae40509062a087e14b6a64f94fb5ae629a24b2062432407a1f3ab94acbc65df49ce63d5e4fcf6d5c7b009691ec2cf2; JSESSIONID=ABAAABAABEIABCI0E4D2CDFFC692EEF09DC3C1487ADD5A8; WEBTJ-ID=2021052%E4%B8%8A%E5%8D%8811:37:54113754-1792b276d6b551-08fbf0fcbf4784-113a6054-1024000-1792b276d6c928; X_HTTP_TOKEN=02cc1cc330da72df576629916129e561f3ad981774; PRE_UTM=; PRE_HOST=; PRE_LAND=https%3A%2F%2Fwww.lagou.com%2Fjobs%2Flist_%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E5%B8%8C%2Fp-city_0%3F; PRE_SITE=; LGUID=20210502113756-6daf6df0-2de5-42d2-828e-8cb2feef29bd; LGSID=20210502113756-2910c4b4-69f0-458b-aac5-e1bf59fee8e1; sajssdk_2015_cross_new_user=1; sensorsdata2015session=%7B%7D; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%221792b27744f8eb-04cbd992f837b9-113a6054-1024000-1792b2774603c1%22%2C%22first_id%22%3A%22%22%2C%22props%22%3A%7B%22%24os%22%3A%22MacOS%22%2C%22%24browser%22%3A%22Chrome%22%2C%22%24browser_version%22%3A%2290.0.4430.93%22%7D%2C%22%24device_id%22%3A%221792b27744f8eb-04cbd992f837b9-113a6054-1024000-1792b2774603c1%22%7D; _ga=GA1.2.2141774430.1619926677; _gat=1; Hm_lvt_4233e74dff0aebd50a3d81c6ccf756e6=1619926677; Hm_lpvt_4233e74dff0aebd50a3d81c6ccf756e6=1619926677; LGRID=20210502113756-9a924450-7598-418b-b731-33046e64120c; _gid=GA1.2.1480471771.1619926677; SEARCH_ID=ab911c2ad61c47f2a94993729604d904' 14 } 15 16 # 用data进行分页爬取 17 for i in range(1, 31): 18 data = { 19 'first': 'true', 20 'pn': i, 21 'kd': '数据分析师' 22 } 23 24 # 请求网页 25 response = requests.post(url=url, headers=headers, data=data, timeout=3) 26 print(response.text) 27 time.sleep(3) # 休息一下 28 29 # json.loads 用于解码 JSON 数据。该函数返回 Python字段的数据类型 30 response = json.loads(response.content) 31 # 获取15条数据 32 result_15 = response['content']['positionResult']['result'] 33 # 获取每条招聘岗位里面的详细信息 34 for i in result_15: 35 position_id = i['positionId'] # 职位Id 36 position_name = i['positionName'] # 职位名称 37 company_full_name = i['companyFullName'] # 公司全称 38 company_short_name = i['companyShortName'] # 公司简称 39 company_size = i['companySize'] # 公司规模 40 finance_stage = i['financeStage'] # 融资阶段 41 company_label_list = i['companyLabelList'] # 公司标签 42 first_type = i['firstType'] # 第一类型 43 second_type = i['secondType'] # 第二类型 44 third_type = i['thirdType'] # 第三类型 45 position_labels = i['positionLables'] # 职位标签 46 industry_labels = i['industryLables'] # 行业标签 47 create_time = i['createTime'] # 创建时间 48 format_create_time = i['formatCreateTime'] # 格式化创建时间 49 city = i['city'] # 城市 50 district = i['district'] # 地区 51 salary = i['salary'] # 工资待遇 52 salary_month = i['salaryMonth'] # 工资月份 53 work_year = i['workYear'] # 工作年限 54 job_nature = i['jobNature'] # 工作性质 55 education = i['education'] # 教育背景 56 position_advantage = i['positionAdvantage'] # 岗位优势 57 hi_tags = i['hitags'] # 福利标签 58 # 存储数据, 先在当前文件下创建一个叫‘lagou_datas.csv’的文件 59 # 'a' 追加写入,;encoding设置编码格式,防止乱码 ;newline是为了解决写入时新增行与行之间的一个空白行问题 60 with open('./lagou_datas.csv', 'a', encoding='utf_8_sig', newline='') as f: 61 # 写入数据 62 csv_write = csv.writer(f) 63 # 按照以下行顺序写入,是一个列表 64 csv_write.writerow([position_id, position_name, company_full_name, company_short_name, company_size, 65 finance_stage, company_label_list, first_type, second_type, third_type, position_labels, 66 industry_labels, create_time, format_create_time, city, district, salary, salary_month, 67 work_year, job_nature, education, position_advantage, hi_tags]) 68 time.sleep(3) # 休息一下 69 # 主程序 70 if __name__ == '__main__': 71 # Ajax的URL 72 url = "https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false" 73 74 # 传入URL,调用函数 75 get_lagou_data(url) 76 #导入包 77 import pandas as pd 78 import numpy as np 79 import seaborn as sns 80 from pyecharts import Pie 81 from pyecharts import options as opts 82 import matplotlib.pyplot as plt 83 #导入数据 84 path = "C:/data/lago_data.csv" 85 df = pd.read_csv(path) 86 # 取出我们进行后续分析所需的字段 87 columns = ["positionName", "companyShortName", "city", "companySize", "education", "financeStage", 88 "industryField", "salary", "workYear", "hitags", "companyLabelList", "job_detail"] 89 df = df[columns].drop_duplicates() #去重 90 #数据清洗 91 # 数据分析相应的岗位数量 92 cond_1 = df["positionName"].str.contains("数据分析") # 职位名中含有数据分析字眼的 93 cond_2 = ~df["positionName"].str.contains("实习") # 剔除掉带实习字眼的 94 len(df[cond_1 & cond_2]["positionName"]) 95 # 使用条件 cond_1 和 cond_2 对数据框 df 进行筛选,只保留满足条件的行 96 df = df[cond_1 & cond_2] 97 98 # 删除名为 "positionName" 的列,axis=1 表示按列操作 99 df.drop(["positionName"], axis=1, inplace=True) 100 101 # 重置索引,drop=True 表示删除原来的索引,inplace=True 表示在原数据框上进行修改 102 df.reset_index(drop=True, inplace=True) 103 df["job_detail"] = df["job_detail"].str.lower().fillna("") #将字符串小写化,并将缺失值赋值为空字符串 104 105 df["Python/R"] = df["job_detail"].map(lambda x:1 if ('python' in x) or ('r' in x) else 0) 106 df["SQL"] = df["job_detail"].map(lambda x:1 if ('sql' in x) or ('hive' in x) else 0) 107 df["Tableau"] = df["job_detail"].map(lambda x:1 if 'tableau' in x else 0) 108 df["Excel"] = df["job_detail"].map(lambda x:1 if 'excel' in x else 0) 109 def clean_industry(industry): 110 # 将传入的行业字符串按逗号分割成列表 111 industry = industry.split(",") 112 # 如果列表的第一个元素是"移动互联网"且列表长度大于1,则返回第二个元素 113 if industry[0]=="移动互联网" and len(industry)>1: 114 return industry[1] 115 # 否则返回第一个元素 116 else: 117 return industry[0] 118 # 使用map函数将df中的industryField列应用clean_industry函数进行清洗 119 df["industryField"] = df.industryField.map(clean_industry) 120 #数据分析 121 # 创建一个12x8英寸的画布 122 fig, ax = plt.subplots(figsize=(12, 8)) 123 # 绘制一个柱状图,展示各城市数据分析岗位的需求量 124 # y轴表示城市名称,order参数按照城市需求量降序排列 125 # data参数指定数据来源为df,颜色设置为'#3c7f99' 126 sns.countplot(y="city", order=df["city"].value_counts().index, data=df, color='#3c7f99') 127 # 关闭箱线图显示 128 plt.box(False) 129 # 在画布上添加文本,设置字体大小、粗细、颜色和背景色 130 fig.text(x=0.04, y=0.90, s=' 各城市数据分析岗位的需求量 ', 131 fontsize=32, weight='bold', color='white', backgroundcolor='#c5b783') 132 # 设置刻度参数,主刻度字体大小为16 133 plt.tick_params(axis='both', which='major', labelsize=16) 134 # 设置x轴和y轴的网格线,宽度为0.5,颜色为'#3c7f99' 135 ax.xaxis.grid(which='both', linewidth=0.5, color='#3c7f99') 136 # 隐藏x轴和y轴的标签 137 plt.xlabel('') 138 plt.ylabel('') 139 # 计算行业字段的频次,并取前10个行业作为索引 140 industry_index = df["industryField"].value_counts()[:10].index 141 # 根据行业字段筛选出对应的数据 142 industry = df.loc[df["industryField"].isin(industry_index), "industryField"] 143 # 创建一个画布和坐标轴 144 fig, ax = plt.subplots(figsize=(12, 8)) 145 # 绘制一个柱状图,展示各行业的岗位数量 146 sns.countplot(y=industry.values, order=industry_index, color='#3c7f99') 147 # 关闭箱线图显示 148 plt.box(False) 149 # 在画布上添加文本,设置字体大小、粗细、颜色和背景色 150 fig.text(x=0, y=0.90, s=' 细分领域数据分析岗位的需求量(取前十) ', 151 fontsize=32, weight='bold', color='white', backgroundcolor='#c5b783') 152 # 设置刻度参数,主刻度字体大小为16 153 plt.tick_params(axis='both', which='major', labelsize=16) 154 # 设置x轴和y轴的网格线,宽度为0.5,颜色为'#3c7f99' 155 ax.xaxis.grid(which='both', linewidth=0.5, color='#3c7f99') 156 # 隐藏x轴和y轴的标签 157 plt.xlabel('') 158 plt.ylabel('') 159 # 创建一个12x8英寸的画布 160 fig, ax = plt.subplots(figsize=(12, 8)) 161 # 计算每个城市的薪资平均值,并按降序排序,将城市名称转换为列表 162 city_order = df.groupby("city")["salary"].mean() \n .sort_values() \n .index.tolist() 163 # 绘制柱状图,横坐标为城市名称,纵坐标为薪资,按照城市顺序排列,置信区间为95%,颜色为RdBu_r调色板 164 sns.barplot(x="city", y="salary", order=city_order, data=df, ci=95, palette="RdBu_r") 165 # 在画布上添加文本,设置字体大小、粗细、颜色和背景色 166 fig.text(x=0.04, y=0.90, s=' 各城市的薪资水平对比 ', 167 fontsize=32, weight='bold', color='white', backgroundcolor='#3c7f99') 168 # 设置刻度参数,主刻度字体大小为16 169 plt.tick_params(axis="both", labelsize=16) 170 # 设置y轴网格线,宽度为0.5,颜色为黑色 171 ax.yaxis.grid(which='both', linewidth=0.5, color='black') 172 # 设置y轴刻度标签,只显示数字部分 173 ax.set_yticklabels([" ", "5k", "10k", "15k", "20k"]) 174 # 关闭箱线图显示 175 plt.box(False) 176 # 隐藏x轴和y轴的标签 177 plt.xlabel('') 178 plt.ylabel('') 179 # 创建一个12x8英寸的画布 180 fig, ax = plt.subplots(figsize=(12, 8)) 181 # 在画布上添加文本,设置字体大小、粗细、颜色和背景色 182 fig.text(x=0.04, y=0.90, s=' 一线城市的薪资分布对比 ', 183 fontsize=32, weight='bold', color='white', backgroundcolor='#c5b783') 184 # 绘制北京的薪资密度曲线 185 sns.kdeplot(df[df["city"]=='北京']["salary"],shade=True,label="北京") 186 # 绘制上海的薪资密度曲线 187 sns.kdeplot(df[df["city"]=='上海']["salary"],shade=True,label="上海") 188 # 绘制广州的薪资密度曲线 189 sns.kdeplot(df[df["city"]=='广州']["salary"],shade=True,label="广州") 190 # 绘制深圳的薪资密度曲线 191 sns.kdeplot(df[df["city"]=='深圳']["salary"],shade=True,label="深圳") 192 # 设置刻度参数,主刻度字体大小为16 193 plt.tick_params(axis='both', which='major', labelsize=16) 194 # 关闭箱线图显示 195 plt.box(False) 196 # 设置x轴刻度标签,从0到60,步长为10,并添加千位分隔符 197 plt.xticks(np.arange(0,61,10), [str(i)+"k" for i in range(0,61,10)]) 198 # 隐藏y轴刻度标签 199 plt.yticks([]) 200 # 设置图例,字体大小为xx-large 201 plt.legend(fontsize = 'xx-large',fancybox=None) 202 # 计算Python/R技能的占比 203 py_rate = df["Python/R"].value_counts(normalize=True).loc[1] 204 # 计算SQL技能的占比 205 sql_rate = df["SQL"].value_counts(normalize=True).loc[1] 206 # 计算Tableau技能的占比 207 tableau_rate = df["Tableau"].value_counts(normalize=True).loc[1] 208 # 计算Excel技能的占比 209 excel_rate = df["Excel"].value_counts(normalize=True).loc[1] 210 # 打印职位技能需求 211 print("职位技能需求:") 212 print("Python/R:", py_rate) 213 print("SQL:", sql_rate) 214 print("Excel:", excel_rate) 215 print("Tableau:", tableau_rate) 216 # 定义一个函数,根据技能等级为数据框添加技能列 217 def get_level(x): 218 if x["Python/R"] == 1: 219 x["skill"] = "Python/R" 220 elif x["SQL"] == 1: 221 x["skill"] = "SQL" 222 elif x["Excel"] == 1: 223 x["skill"] = "Excel" 224 else: 225 x["skill"] = "其他" 226 return x 227 # 应用函数,为数据框添加技能列 228 df = df.apply(get_level, axis=1) 229 # 创建一个画布和坐标轴 230 fig, ax = plt.subplots(figsize=(12, 8)) 231 # 在画布上添加文本,设置标题、字体大小、粗细、颜色和背景色 232 fig.text(x=0.02, y=0.90, s=' 不同技能的薪资水平对比 ', 233 fontsize=32, weight='bold', color='white', backgroundcolor='#c5b783') 234 # 绘制箱线图,展示不同技能的薪资水平 235 sns.boxplot(y="skill", x="salary", data=df.loc[df.skill != "其他"], palette="husl", order=["Python/R", "SQL", "Excel"]) 236 # 设置刻度参数,主刻度字体大小为16 237 plt.tick_params(axis="both", labelsize=16) 238 # 设置坐标轴网格线宽度 239 ax.xaxis.grid(which='both', linewidth=0.75) 240 # 设置x轴刻度标签,从0到60,步长为10,并添加千位分隔符 241 plt.xticks(np.arange(0, 61, 10), [str(i) + "k" for i in range(0, 61, 10)]) 242 # 关闭箱线图的边框 243 plt.box(False) 244 # 设置x轴和y轴的标签,字体大小为18 245 plt.xlabel('工资', fontsize=18) 246 plt.ylabel('技能', fontsize=18) 247 # 定义公司规模映射字典 248 company_size_map = { 249 "2000人以上": 6, 250 "500-2000人": 5, 251 "150-500人": 4, 252 "50-150人": 3, 253 "15-50人": 2, 254 "少于15人": 1 255 } 256 # 定义工作年限映射字典 257 workYear_map = { 258 "5-10年": 5, 259 "3-5年": 4, 260 "1-3年": 3, 261 "1年以下": 2, 262 "应届毕业生": 1 263 } 264 # 将公司规模和工作年限映射到对应的数值 265 df["company_size"] = df["companySize"].map(company_size_map) 266 df["work_year"] = df["workYear"].map(workYear_map) 267 # 根据公司规模对数据进行排序 268 df = df.sort_values(by="company_size", ascending=True) 269 # 筛选出有工作年限的数据 270 df_plot = df.loc[~df.work_year.isna()] 271 # 定义颜色映射字典 272 color_map = { 273 5: "#ff0000", 274 4: "#ffa500", 275 3: "#c5b783", 276 2: "#3c7f99", 277 1: "#0000cd" 278 } 279 # 将工作年限映射到对应的颜色 280 df_plot["color"] = df_plot.work_year.map(color_map) 281 # 重置索引 282 df_plot.reset_index(drop=True, inplace=True) 283 # 定义绘图函数 284 def seed_scale_plot(): 285 seeds = np.arange(5) + 1 286 y = np.zeros(len(seeds), dtype=int) 287 s = seeds * 100 288 colors = ['#ff0000', '#ffa500', '#c5b783', '#3c7f99', '#0000cd'][::-1] 289 fig, ax = plt.subplots(figsize=(12, 1)) 290 plt.scatter(seeds, y, s=s, c=colors, alpha=0.3) 291 plt.scatter(seeds, y, c=colors) 292 plt.box(False) 293 plt.grid(False) 294 plt.xticks(ticks=seeds, labels=list(workYear_map.keys())[::-1], fontsize=14) 295 plt.yticks(np.arange(1), labels=[' 经验:'], fontsize=16) 296 # 绘制散点图 297 fig, ax = plt.subplots(figsize=(12, 8)) 298 fig.text(x=0.03, y=0.92, s=' 不同规模公司的用人需求差异 ', fontsize=32, 299 weight='bold', color='white', backgroundcolor='#3c7f99') 300 plt.scatter(df_plot.salary, df_plot["companySize"], s=df_plot["work_year"] * 100, alpha=0.35, c=df_plot["color"]) 301 362 plt.scatter(df_plot.salary, df_plot["companySize"], c=df_plot["color"].values.tolist()) 302 plt.tick_params(axis='both', which='both', length=0) 303 plt.tick_params(axis='both', which='major', labelsize=16) 304 ax.xaxis.grid(which='both', linewidth=0.75) 305 plt.xticks(np.arange(0, 61, 10), [str(i) + "k" for i in range(0, 61, 10)]) 306 plt.xlabel('工资', fontsize=18) 307 plt.box(False) 308 # 调用绘图函数 309 seed_scale_plot() 310 # 从数据框df中筛选出公司规模为"2000人以上"且技能不为"其他"的行,并获取这些行中的技能列的值计数(去重后),并进行归一化处理 311 df_skill = df.loc[(df["companySize"]=="2000人以上")&(df.skill!="其他")]["skill"].value_counts(normalize=True) 312 # 绘制条形图,展示技能占比情况 313 fig, ax = plt.subplots(figsize=(12, 6)) 314 sns.barplot(x=df_skill.index,y=df_skill.values, color='#3c7f99') 315 # 关闭箱线图边框 316 plt.box(False) 317 # 在图表上方添加标题和背景色 318 fig.text(x=0.08, y=0.9, s=' 大公司对技能的要求占比 ', 319 fontsize=32, weight='bold', color='white', backgroundcolor='#c5b783') 320 # 设置坐标轴刻度标签的字体大小 321 plt.tick_params(axis='both', which='major', labelsize=16) 322 # 设置y轴网格线 323 ax.yaxis.grid(which='both', linewidth=0.5, color='#3c7f99')
总结
通过对拉勾网数据分析师岗位的分析,我们可以看出数据分析师岗位需求量较大,且有逐年上升的趋势,这说明数据分析在企业中的地位越来越重要,对于求职者来说,具备数据分析能力将有助于提高就业竞争力,并且数据分析师岗位的薪资水平较高,且同样呈现逐年上升的趋势。这表明数据分析行业的发展势头良好,从事这一行业的人员可以获得较高的回报,但是数据分析师岗位对于工作经验和技能要求较高。大部分岗位要求具备3-5年以上的工作经验,以及熟练掌握Excel、SQL、Python等技能。这对于刚刚步入职场的应届生来说,无疑增加了求职的难度。
在完成此设计过程中,我掌握了Python爬虫的基本技巧,如请求库、解析库的使用,以及如何应对反爬机制等。学会了如何使用Python进行数据处理和分析,如数据清洗、数据筛选、数据统计等了解了数据可视化的基本原理和方法。
标签:city,课程设计,plt,拉勾,python,22%,df,True,color From: https://www.cnblogs.com/zs121517/p/17929413.html