[Selenium+Pyecharts]爬取建筑设计师招聘信息,数据清洗并可视化

前言:
8个小时内完成爬虫,数据清洗并可视化。因为自己也是小白,做的时候时间还挺赶的。很多地方没有做到完美,比如一些数据清洗的步骤走了捷径。有不足的地方,欢迎大神们留言指教。

    selenium :3.141.0
    pyecharts:1.9.0

1.Selenium爬取信息

我个人是喜欢用selenium做爬虫的,可以享受web自动化的这个过程。因为要爬取的东西不是很多,如果要爬取很多内容的同学,还是老老实实用request的吧。

此次爬取的是51job前程无忧,这里的url可以替换成你想查询的该网站的任何职业或者岗位。

爬取几个我们需要的重要信息,包括:职位名称,发布日期,工资,学历要求,经验要求,工作地点等等等。

网速快的同学记得把睡眠时间调短一些,不然真的会爬很久。我自己大概爬了7.8分钟吧

from selenium import webdriver
import pandas as pd
import time


wd = webdriver.Chrome()
wd.get('https://search.51job.com/list/000000,000000,0000,00,9,99,%25E5%25BB%25BA%25E7%25AD%2591%25E8%25AE%25BE%25E8%25AE%25A1,2,1.html?lang=c&postchannel=0000&workyear=99&cotype=99°reefrom=99&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=')
wd.implicitly_wait(10)

max_pages = 100

titles = []
times = []
wages = []
infos = []
company_names = []
company_infos = []
company_atrri = []
def get_data(titles,times,wages,infos,company_names,company_infos,company_atrri):
    #获取职位名称
    title0 = wd.find_elements_by_css_selector('.jname.at')
    for each_title in title0:
        titles.append(each_title.text)
    #获取发布时间
    time0 = wd.find_elements_by_css_selector('.time')
    for each_time in time0:
        times.append(each_time.text)
    #获取工资信息
    wage0 = wd.find_elements_by_css_selector('.sal')
    for each_wage in wage0:
        wages.append(each_wage.text)
    #获取更多职位信息
    info0 = wd.find_elements_by_css_selector('.d.at')
    for each_info in info0:
        infos.append(each_info.text)
    #获取公司信息
    company_name0 = wd.find_elements_by_css_selector('.cname.at')
    for each_c_name in company_name0:
        company_names.append(each_c_name.text)
    #获取更多公司信息
    company_info0 = wd.find_elements_by_css_selector('.dc.at')
    for each_c_info in company_info0:
        company_infos.append(each_c_info.text)
    #获取公司性质
    company_atrri0 = wd.find_elements_by_css_selector('.int.at')
    for each_c_attr in company_atrri0:
        company_atrri.append(each_c_attr.text)



for i in range(max_pages):
    print(f'正在爬取第{i}页')
    get_data(titles,times,wages,infos,company_names,company_infos,company_atrri)
    wd.find_element_by_css_selector('.next').click()
    time.sleep(5) # 网速快的同学,请在这里操作,过快的操作可能会被检验出IP异常

data = {
     '岗位名称': titles,
        '发布时间':times,
        '薪酬':wages,
        '更多职位信息':infos,
        '公司名称':company_names,
        '公司更多信息':company_infos,
        '公司性质':company_atrri
        }
df = pd.DataFrame(data)
df.to_csv('建筑岗位信息.csv')


wd.quit()

最后将爬取的5000条信息转存为CSV格式。
下面是部分结果展示:
[Selenium+Pyecharts]爬取建筑设计师招聘信息,数据清洗并可视化_第1张图片

2 . Pandas清洗数据

这里清洗数据的工作是比较乱的,因为对我来说时间太紧了。下次会发一个另外的爬虫悉尼房价的代码,想对来说清洗很多。

清洗数据的几个主要目的:

  1. 工资的单位是不统一的,有些是年,有些是月;有些是万,有些是千。(可以从上图中看到)。为此得统一单位。
  2. 工资是一个范围,这个范围不利于我们后续的可视化和分析。我这是用的split,用正则表达式也是可以的,把上限和下限取出来求一个平均值。
  3. 需要把经验要求,上班地点和学历要求提出来作为一个单独的特征进行分析。
  4. 嗷对!还有一个很重要的点,一共爬取了5000条信息,但其中只有2500条是建筑设计师,所以同学们在自己做其他岗位职业分析的时候记得看看自己爬取的数据有没有这个问题。
  5. 节省时间(偷懒)把不符合,麻烦处理的样本直接删了。
import pandas as pd
pd.set_option('display.max_columns', None)
df = pd.read_csv('建筑岗位信息.csv')
df = df.iloc[:2500,:] # 只取建筑设计师,其他相关岗位全部删除
#print(df['薪酬'])


#统一一下单位,因为时间原因,把年薪,和以千为单位的数据全部删除掉了,如果认真做,千万不要删除,每一条数据都很重要
wage_types = []
wage_types2 = []
year = ['年']
month = ['月']
wagek = ['千']
wagew = ['万']
df.loc[:, "薪酬"] = df["薪酬"].astype('str')
for i in range(len(df['薪酬'])):
    if any(key in df['薪酬'][i] for key in year):
        wage_types.append('年薪')
    elif any(key in df['薪酬'][i] for key in month):
        wage_types.append('月薪')
    else:
        wage_types.append("None")
df['薪酬类型1'] = wage_types
df = df[df['薪酬类型1'] != 'None']
df = df[df['薪酬类型1'] != '年薪']
df.drop(columns = ['Unnamed: 0'],inplace = True)
df = df.reset_index(drop=True)
df.loc[:,'薪酬'] = df['薪酬'].str.replace("/月",'').astype('str')
for i in range(len(df['薪酬'])):
    if any(key in df['薪酬'][i] for key in wagek):
        wage_types2.append('千')
    elif any(key in df['薪酬'][i] for key in wagew):
        wage_types2.append('万')
df['薪酬类型2'] = wage_types2

#把数字后面的单位(千万)提出来
for i in range(len(df['薪酬'])):
    if df['薪酬类型2'][i] == '千':
        df['薪酬'][i] = df['薪酬'][i].replace('千', '')
    elif df['薪酬类型2'][i] == '万':
        df['薪酬'][i] = df['薪酬'][i].replace('万', '')


#找出工资的上下线
min_wage = []
max_wage = []
for i in range(len(df['薪酬'])):
    try:
        min_wage0= df['薪酬'][i].split("-")[0]
        max_wage0 = df['薪酬'][i].split("-")[1]
        min_wage.append(min_wage0)
        max_wage.append(max_wage0)
    except:
        min_wage0 = 0
        max_wage0 = 0
        min_wage.append(min_wage0)
        max_wage.append(max_wage0)
df['minwage'] = min_wage
df['maxwage'] = max_wage
df['minwage'] = df["minwage"].astype('float')
df['maxwage'] =df["maxwage"].astype('float')




areas = []
exps = []
degrees = []
for i in range(len(df['更多职位信息'])):
    area = df['更多职位信息'][i].split('|')[0]
    areas.append(area)
    exp = df['更多职位信息'][i].split('|')[1]
    exps.append(exp)
    try:
        degree = df['更多职位信息'][i].split('|')[2]
        degrees.append(degree)
    except:
        degree = "None"
        degrees.append(degree)
df['上班地点'] = areas
df['经验要求'] = exps
df['学历要求'] = degrees
df = df[df['薪酬类型2'] != '千']
df.drop(['薪酬','更多职位信息','薪酬类型1'],axis = 1,inplace = True)
df['薪酬'] = (df['minwage']+df['maxwage'])/2
df.drop(['minwage','maxwage','薪酬类型2'],axis = 1,inplace = True)

df= df[df['薪酬'] != 0]
df = df.reset_index(drop=True)
df.to_csv('清洗过后的数据.csv')

下面是部分结果展示:[Selenium+Pyecharts]爬取建筑设计师招聘信息,数据清洗并可视化_第2张图片

3.Pyecharts可视化

pyecharts真的是神仙工具,除了网上的教程不那么详细之外,几乎找不到啥子缺点(好像这是我自己的缺点。。。)。pyecharts输出的是html文件,可以用浏览器打开,并且都是交互式体验,个人觉得和tableau做出来的图差距不大了。还有各种像水滴图,旭日图各种各样的图都ok!度娘良心出品。当然也没有忘记我们的老朋友matlibplot,下面也有用它做做图。具体选用什么可视库大家随喜好就好。

在可视化的基础上我写了一些自己的结论不一定对。(毕竟这行业我也不是太了解)

import pandas as pd
from pyecharts.charts import Pie,Bar
from pyecharts import options as opts
import matplotlib.pyplot as plt
from pylab import *
mpl.rcParams['font.sans-serif'] = ['SimHei']

pd.set_option('display.max_columns', None)
pd.set_option('display.max_rows', None)
#这部分数据groupby手滑被我删了,自己groupby一下吧。实在不会,代码和下面的上班地点是一样的
cate = ['房地产', '建筑', '多元化业务集团公司', '家居/室内设计','专业服务','石油/化工']
values = [935,624,73,25,24,21]
pie = (Pie()
            .add('',[list(z) for z in zip(cate,values)],
                    radius=['40%','60%'],
                    label_opts=opts.LabelOpts(is_show=True),
                 )
            .set_global_opts(title_opts=opts.TitleOpts(title = '建筑行业岗位分布'),
                             legend_opts=opts.LegendOpts(is_show=True))


        )
pie.render("社招-建筑行业岗位分布.html")
df = pd.read_csv("清洗过后的数据.csv")
#print(df.groupby('公司性质')['薪酬'].mean())


"""
岗位更多的集中在房地产(甲方)和建筑事务所/设计院(乙方)
传统建筑行业的平均薪酬在1.303w每个月,房地产行业的平均薪酬在1.85W每个月,平均薪酬最高的是采矿页2.75w每个月。
但是这个统计不完全正确,单纯的比较不具有意义,因为同时应该考虑到房地产行业是否对经验或者学历要求更高。

"""




#上班地点可视化
area_group = df.groupby('上班地点').count()
#print(area_group.sort_values(by = '薪酬',ascending= False))
cate = ["异地招聘",'深圳南山', '深圳福田', '广州天河', '成都高新','上海','上海浦东','广州','成都','南京']
values = [174,41,37,32,32,28,26,22,21,18]

pie = (Pie()
            .add('',[list(z) for z in zip(cate,values)],
                    radius=['40%','60%'],
                    label_opts=opts.LabelOpts(is_show=True),
                 )
            .set_global_opts(title_opts=opts.TitleOpts(title = '建筑行业地区分布'),
                             legend_opts=opts.LegendOpts(is_show=True))


        )
pie.render("社招-建筑行业地区分布.html")
#print(df.groupby('上班地点')['薪酬'].mean())

"""
建筑设计师的需求想对来说比较分散,全国各地都有需要。不像一些特殊岗位如金融,计算机的需求会比较聚集在超一线城市。
在不考虑经验的情况下。可以看超一线城市的平均薪酬是高于一般一线城市的,大约在1.8+W的位置。
不过东莞,四川,重庆等特殊地区对建筑设的需求明显大于其他同类城市的。
"""
#学历要求

degree_group = df.groupby('学历要求').count()
#print(degree_group.sort_values(by = '薪酬',ascending= False))
cate = ["本科",'大专', '未知', '硕士', '中专']
values = [1343,267,39,10,1]

bar = (Bar()
       .add_xaxis(cate)
       .add_yaxis('', values)
       .set_series_opts(label_opts=opts.LabelOpts(is_show=True, font_size=15))
       .set_global_opts(title_opts=opts.TitleOpts(title='社招-建筑行业学历要求'),
                        xaxis_opts=opts.AxisOpts(name='学历要求'),
                        yaxis_opts=opts.AxisOpts(name='样本数量'))
       )
bar.render('社招-建筑行业学历要求.html')
print(df.groupby('学历要求')['薪酬'].mean())
"""
根据爬取到的1600多条建筑师招聘信息来看,学历和薪酬之间不存在明显的线性关系。(在更高维度或者更多样本的时候,可能可以够找到一些关系)
通常来说我们认为建筑设计师对于学历并没有太硬性的要求,更多的还是个人技能的要求。

"""


#经验要求

exp_group = df.groupby('经验要求').count()
#print(exp_group.sort_values(by = '薪酬',ascending= False))
cate = ["5-7年",'3-4年', '2年经验', '8-9年', '1年经验','10年以上经验','无需经验']
values = [666,532,151,99,91,56,39]

bar = (Bar()
       .add_xaxis(cate)
       .add_yaxis('', values)
       .set_series_opts(label_opts=opts.LabelOpts(is_show=True, font_size=15))
       .set_global_opts(title_opts=opts.TitleOpts(title='社招-建筑行业经验要求'),
                        xaxis_opts=opts.AxisOpts(name='经验要求'),
                        yaxis_opts=opts.AxisOpts(name='样本数量'))
       )
bar.render('社招-建筑行业经历要求.html')
#print(df.groupby('经验要求')['薪酬'].mean())

"""
可以看出3到7年占了几乎3分之2的样本,说明这个时间段才是建筑设计师的黄金时间。
与学历不同,薪酬和工作经历之间存在一个明显的正相关关系,10年以上的平均工资在2.36w/月。
而一年工作经验的1.07W/月,2年1.17w/月.

"""



'''
x = ['1','2','3-4','5-7','8-9','10+']
y= [1.07,1.17,1.43,1.86,2.33,2.36]


plt.xlabel('working experiences')
plt.ylabel('wages')
plt.title("The relation between Wages and Working Experiences")
plt.plot(x,y)
plt.savefig("工作经验和工资关系.png")'''

pyecharts的部分结果展示:
《建筑岗位的行业分布》
[Selenium+Pyecharts]爬取建筑设计师招聘信息,数据清洗并可视化_第3张图片
《工作经验和招聘数量》
[Selenium+Pyecharts]爬取建筑设计师招聘信息,数据清洗并可视化_第4张图片

折线图还是matplotlib吧:
[Selenium+Pyecharts]爬取建筑设计师招聘信息,数据清洗并可视化_第5张图片

你可能感兴趣的:(数据可视化,可视化,数据分析,爬虫,python,selenium)