随着大数据时代的到来,企业对数据价值的重视,数据分析师的市场越来越大,毫无疑问数据分析师已成为"当今最具发展潜力的职业",
在美国,大数据分析师平均每年薪酬高达17.5万美元,而国内顶尖互联网公司,大数据分析师的薪酬可能要比同一个级别的其他职位高20%至30%,且颇受企业重视。
因此,小编也想看看在国内,我们的数据分析薪酬分布到底是怎样的呢?于是想到了爬取招聘网数据,在小编印象中,58同城,智联,前程,猎聘是我曾找工作常用的几个平台,又因为现在数据分析的第一份工作是在智联上找到的,所以今天就从智联入手。
研究的主题想好了,那么就来选择软件吧,平时倾向于R爬虫,而且打算应用一下Rshiny平台搭建一下可视化平台展示,所以还是一如既往选择我喜欢的R语言(我偷偷的说:因为python还在入门)。
本次可能运用到是以下几个包:
library(xml2)
library(rvest)
library(shiny)
library(shinydashboard)
library(stringr)
library("dplyr")
library(shiny)
library(shinydashboard)
首先我们进入智联招聘网站,http://www.zhaopin.com/,并且F12进入开发者工具
审查元素,并且找到对应的css或者xpath.因为这次采用的是rvest,所以选择css,如果想要知道xpath可以用360浏览器copy xpath路径非常容易。
如图所示红框框就是我们抓取时候需要的路径,顺便说一下,由于本次搜索会涉及到中文转码,例如我们把搜索后的网址复制到R里面是这样的http://sou.zhaopin.com/jobs/sear ... 6%E6%9E%90&sm=0&p=1,为了代码能多次利用,不用反复的去网页复制,就采用以下转码函数:url_escape,reserved就是我们需要保留不用转码的部分,例如./'@等
代码如下图所示:
# 选择工作地点,工作
site <- "上海+北京+广东+江苏"
work <- "人事"
page <- 10
p=1
# 抓取网页function
getinfo <- function(site,work,page){
#建立空的数据表格
result <- data.frame()
for(p in 1:page){
tryCatch({
# 赋值网址
url <- paste0("https://sou.zhaopin.com/jobs/searchresult.ashx?jl=",site,"&kw=",work,"&sm=0&p=",p)
# 中文转译
web <- url %>% url_escape(.,reserved = "()[]:;',./?!@#$-=&")
# 解析网页
web1 <- read_html(url,encoding = "utf-8")
# 获取长度
length <- length(web1 %>% html_nodes(.,'div td.zwmc') %>% html_text(trim = T))
# 提取工作/反馈率/公司名称/月薪/工作地点/发布日期:
job=response=company=salary_min=salary_max=work_place=date=rep('',length)
# 获取职位
job <- web1 %>% html_nodes(.,'div td.zwmc') %>% html_text(trim = T)
# 获取反馈率
response <- web1 %>% html_nodes(.,'div td.fk_lv span') %>% html_text(trim = T)
# 获取公司名称
company <- web1 %>% html_nodes(.,'div td.gsmc') %>% html_text(trim = T)
# 获取月薪
salary <- web1 %>% html_nodes(.,'div td.zwyx') %>% html_text(trim = T)
salary_split <- strsplit(salary,'-')
for(i in 1:length(salary_split)){
salary_min[i] <- salary_split %>% '[['(i) %>% '['(1)
salary_max[i] <- salary_split %>% '[['(i) %>% '['(2)
}
# 获取工作地点
work_place <- web1 %>% html_nodes(.,'div td.gzdd') %>% html_text(trim = T)
# 发布时间
date <- web1 %>% html_nodes(.,'div td.gxsj') %>% html_text(trim = T)
以上我们就基本获取了一级页面所有我们需要的信息,那我们来看看二级页面里面的具体工作的详细信息。
本次抓取的是红框框部分,当然你也可自己尝试公司规模,公司性质,以及下面的工作具体需求等:
# 获取二级信息
second_url <- web1 %>% html_nodes(.,'div td.zwmc a:nth-child(1)') %>% html_attr(.,"href")
work_year=education=number=position= rep('',length(second_url))
for(n in 1:length(second_url)){
# 获取工作经验要求
work_year[n] <- second_url[n] %>% read_html() %>% html_nodes(.,"div ul li:nth-child(5) strong") %>% html_text(trim = T) %>% '['(1)
education[n] <- second_url[n] %>% read_html() %>% html_nodes(.,"div ul li:nth-child(6) strong") %>% html_text(trim = T) %>% '['(1)
number[n] <- second_url[n] %>% read_html() %>% html_nodes(.,"div ul li:nth-child(7) strong") %>% html_text(trim = T) %>% '['(1)
position[n] <- second_url[n] %>% read_html() %>% html_nodes(.,"div ul li:nth-child(8) strong") %>% html_text(trim = T) %>% '['(1)
print(sprintf("正在抓取第[%d]页第[%d]个数据", p, n))
}
顺便说一声,爬虫的时候难免会遇到抓取的某个页面信息有误,我们可以采用trycatch函数进行对错误页面忽略(此条很重要!!!特别是抓取页面比较多的时候,因为在本次抓取中就遇到了错误的页面)。
之前写过一篇爬虫的文章,说到过爬取时候涉及到速度多进程,可以采取以下代码,但由于对页面10页做了和普通爬虫速度的对比未胜出所以还是采用原先的:
library("foreach")
library("doParallel")
library("iterators")
library("parallel")
system.time({
cl<- makeCluster(4)
registerDoParallel(cl) #进程注册
mydata1 <- foreach(
i=1:page, #输入等待请求的参数
.combine=rbind, #返回结果的整合
.packages = c("xml2","rvest","stringr")
#多个进程共享的系统环境
) %dopar% getinfo(site,work,page)
stopCluster(cl)
})
本次采用的是如下代码:system.time可以观测到本次程序花了多少秒,还是不错的,在跑程序的建议使用。
system.time({
result <- getinfo(site,work,page)
})
最后应该是花了3-4个小时爬了1000页,如果你只是对自己地区的该工作有兴趣呢可以选择减少地区,并且减少页数。
剩下的就是shiny平台可视化的搭建:
ui <- dashboardPage(
dashboardHeader(title = "职业工作情况",
dropdownMenu(type = "messages",
messageItem(
from = "TIME",
message = "what's time?",
icon = icon("alarm-clock"),
time = date())
)
),
dashboardSidebar(
sidebarMenu(
menuItem("职业一览表",tabName = "job1", icon = icon("briefcase")),
menuItem("职业一图",tabName = "job2", icon = icon("address-card"))
)),
dashboardBody(
tabItems(
tabItem(tabName = "job1",
column(4,select_location <- textInput("select_location",label = "填入所查地区",value = site)),
column(4,select_job <- textInput("select_job",label = "填入所查工作",value = work)),
column(4,select_page <- textInput("select_page",label = "填入所查页数",value = page)),
actionButton(inputId = "goButton", label = "let's Go!!!"),
verbatimTextOutput(outputId = "summary"),
DT::dataTableOutput("DT")
),
tabItem(tabName = "job2",
column(6,selectInput(inputId = "xcol",label = "x varible",choices = names(result1)[2:11]),
selected = names(result1)[11:11]),
column(6,selectInput(inputId = "ycol",label = "y varible",choices = names(result1)[2:11]),
selected = names(result1)[11:11]),
plotOutput("plot1")))
)
)
server <- function(input,output){
#显示表格
output$DT <- DT::renderDataTable({
# 点击
input$goButton
# 显示表格
output$summary <- renderPrint(summary(result1[,c(5,6)]))
DT::datatable(result)
})
output$plot1 <- renderPlot({
boxplot(result1[,input$ycol]~result1[,input$xcol],
data = result1,
col = rainbow(7),
pch = 19,#点类型
main = "智联招聘箱线图可视化")
})
}
#运行程序
shinyApp(ui, server)
其实可以看到数据途中,离散值很影响可视化结果的观测,所以还需将代码处理处理进行优化。本次对最低薪资进行了一次处理,去除了数量占比较少的
# 数据处理result[,5] <- as.character(result[,5])result[,6] <- as.character(result[,6])result[,6] <- as.numeric(result[,6])result[,5] <- as.numeric(result[,5])result1 <- result[result[,5] != "1000元以下" & result[,5] != "面议",]result1 <- result[result[,5] != 100001 & result[,5] != 80000 &result[,5] != 70001,]str(result)table(result1[,5])
结论:
从图中观测到在学历方面还是还是和薪资有一定的关联度,博士和硕士最低薪资高于其他学历,
从整体工资来观测,数据分析的平均工资在7300 - 11300元左右,
随后我又抓取了一批财务的数据,但由于抓取速度还未改善,仅抓取了前100页数据
财务的平均工资在5467 - 8314元左右,
行政的平均工资在5467 - 8314元左右,
数据分析薪资确实比财务涨幅在20-30%,而相对于行政来看薪资涨幅就更显著了有兴趣的小伙伴可以对其他职业也进行一次抓取比较。
待改进部分:
抓取方面:速度太慢还是一个大问题,本次已经尝试过多进程10页和不采用多进程,运行时间还是不采用比较快,不知道是不是自己参数设置有问题,有待提高,有提高速度方法的小伙伴,欢迎指导。
shiny可数话方面:数据可以进一步完善,地区可以分的粗一点,可以做成北上广苏,三个省份,由于抓下来的好多小的地方不太清楚属于哪个省,遂没进行处理。
版权声明:本站内容全部来自于腾讯微信公众号,属第三方自助推荐收录。《数据分析薪资怎么样 R语言带你一见高下(修改版)》的版权归原作者「微醺间聆R」所有,文章言论观点不代表Lambda在线的观点, Lambda在线不承担任何法律责任。如需删除可联系QQ:516101458
文章来源: 阅读原文
微醺间聆R微信公众号:YBY15651905811
手机扫描上方二维码即可关注微醺间聆R微信公众号