实习僧招聘网爬虫数据可视化

我本来对实习僧网站是没什么好感的,因为之前自己在实习僧上投的实习简历几乎全部都石沉大海了(一个文科生偏要去投数据分析岗不碰壁才怪~_~)!
然鹅看到最近知乎爬虫圈儿里的两大趋势:爬美图;爬招聘网站。
后来大致了解下了,几乎各类大型的招聘文章都被别人爬过了,自己再去写免不了模仿之嫌,而且大神们都是用python去爬的(python我刚学会装包和导数据),自己也学不来。
现在只能选一个还没怎么被盯上的招聘网站,没错就它了——实习僧。
说老实话,实习僧的网站做的还是不错的,看着结构挺简单,可是我用比较主流的rvest和rcurl都失败了(主要自己技术太渣了,抓包又抓不好)。最后只能勉强用rselenium爬完了全部所需内容。(用代码驱动浏览器的好处就是不用怎么考虑时延和伪装包头了,但是要遍历成百上千页网址真的很耗时,爬完这个数据用了大约40多分钟)。
以下是爬虫部分:
library(rvest)library(stringr)library(plyr)library(dplyr)library(rwebdriver)library(dplyr)library(rwordseg)library(wordcloud2)library(treemap)library(showtext)library(cairo)library(ggplot2)library(scales)library(grid)library(rcolorbrewer)library(ggimage)library(geojsonio)
本文主要用的rwebdriver包来驱动chrome浏览器,使用该包需要提前配置好桌面环境:
下载selenium启动服务器;下载chrome的chromedriver插件并放入chrome主目录(添加系统环境变量)下载rwebdriver包
在cmd或者powershell中启动selenium服务器:
options(stringsasfactors=false,warn=false)cd d:/rwebdriver-masterjava -jar selenium-server-standalone-3.3.1.jar
在rsudio中新建进程:start_session(root=http://localhost:4444/wd/hub/,browser =chrome)
遍历实习僧的招聘信息网页baseurlpageurl
本文所用到的爬虫代码部分:homepage=internship=companyweb=company=position=address=salary=period=duration=nullfunpost.url(url=url)baseinfohomepage %html_nodes(p.po-name>p.names>a)%>% html_attr(href)internship%html_nodes(p.po-name>p.names>a)%>%html_text()companyweb%html_nodes(p.po-name>p.part>a)%>%html_attr(href)company %html_nodes(p.po-name>p.part>a)%>%html_text()position %html_nodes(p.po-name>p.part)%>%html_text()address %html_nodes(p.po-detail>p.addr>span)%>%html_text()salary %html_nodes(p.po-detail>p.xz>span:nth-child(2))%>%html_text()period %html_nodes(p.po-detail>p.xz>span:nth-child(5))%>%html_text()duration %html_nodes(p.po-detail>p.xz>span:nth-child(8))%>%html_text()interninfo
用一个循环执行上述程序:finalfor (i in pageurl){finalquit_session()
dt::datatable(final)
保存本地:
write.table (final,d:/r/file/shixiseng.csv,sep=,,row.names=false)
##############################################
接下来做数据清洗:mydatamydata#补全实习发布单位的招聘信息主页:mydata$homepage#补全实习发布单位的公司信息主页:mydata$companywebmydata$work#清除salary中的空格和斜杠mydata$salarymydata$salary#拆分实习工资的高低区间mydata$salary_lowmydata$salary_high#清除period中的汉字和特殊字符mydata$period#清除duration中的汉字和特殊字符mydata$durationmydata mydata#因为address中所含的地址可能有存在多个,影响我们后续的可视化分析,这里为了方便起见,一律使用第一个地址。mydata$address_unique至此,数据清洗工作告一段落,接下来我们要进入分析与可视化阶段
names(mydata)homepage-------公司实习职位简介internship-----公司招聘性质companyweb-----公司主页company--------公司名称address--------所在地address_unique-所在地(唯一值,只取默认第一个地址)salary---------实习工资区间salary_low-----实习工资(最低值)salary_high----实习工资(最高值)period---------到岗天数(每周)duration-------实习周期(按月算)work-----------具体职位
我们最终获取的清洗后数据如上所示。
假如本次项目需求(虚拟)要求我们获取以下几个问题:
1、实习僧的实习招聘主页岗位主要是什么性质的?
2、哪些公司最缺实习僧?
3、实习岗位具体分布的地域和城市?
4、哪些城市对实习僧的需要最为强烈?
5、实习工资大致什么水平,与城市和地域是否有关系?
6、实习岗位一般都要求每周到岗多少天?
7、实习周期一般需要多长时间?
8、哪些职位需求最为频繁,职位需要量与城市之间的大致是如何分布的?
带着这些个问题,让我们尽情的畅游在可视化的世界里吧……
1、实习僧的实习招聘主页主要是什么性质的?
length(unique(mydata$internship))
3357
绝望了,一共爬了5000条实习职位信息,做了去重处理,显示仍有3357条,建议实习僧的产品运营团队考虑下要不要标准化一下这个职位性质,内门怎么可以创造这么多独特的职位~_~
对于这个问题,真的难倒我了,因为所爬数据中的职位性质没有统一的预设标准,所以我只能用文本分词的形式来进行提取了,先分词,然后统计高频词,最后按照词频来进行模糊分析啦(可我我对文本挖掘一窍不通啊~_~)
top100%as.data.frame(stringsasfactors=false)%>% arrange(desc(freq))%>%.[1:100,]treemap(top100, index=c(var1), vsize=freq,title='实习僧职位性质分布图',palette='rdbu',fontsize.title=18,fontsize.labels=12,fontface.labels=plain,fontfamily.title=mono,fontfamily.labels=mono)
从实习职位分布图上来看,人力资源实习生职位需求最为强烈,其次是运营、财务、新媒体,这些类型的职位多为现代新兴服务业,更为符合大学生这一群体的口味和兴趣。
myreviewwthewords %unlist()thewords thewords1]reviewdata%as.data.frame(stringsasfactors = false)%>% arrange(desc(freq))%>%filter(thewords!=实习生)wordcloud
但是将职位性质分词整理成关键词后,似乎结果有所不同。
这里我们来统计所爬职位信息中公司发布职位的频率,发布最多的则作为评价公司对实习生需求的标准。
myjob%as.data.frame(stringsasfactors=false)%>%arrange(desc(freq))#看看前十名都是那些公司:myjob15
cairopng(file=e:/微信公众号/公众号——数据小魔方/2017年5月/20170512/circle-rose.png,width=1580,height=950)showtext.begin()ggplot(data=myjob15,aes(x=reorder(var1,-freq),y=freq,fill=freq))+geom_linerange(aes(ymin=0,ymax=42),linetype=5,size=.2,colour=#858585)+geom_image(aes(x=0,y=-40),image=d:/r/image/image1.jpg, size =.2)+geom_text(aes(y=45,label=paste0(var1,\n,freq)),vjust=1,size=5)+geom_bar(stat=identity,width=1,col=white)+geom_hline(yintercept =54,color=black,size=.5)+geom_point(aes(y=48,size=freq),shape=21,fill=#ed7d31,,alpha=0.6,col=orange)+labs(title=top 15 of company,caption=data source:shixiseng)+coord_polar(theta=x)+ylim(-40,60)+scale_size_area(max_size=20)+guides(fill=false,size=guide_legend(reverse=true,title=null))+theme_minimal()+theme(axis.title=element_blank(),axis.text=element_blank(),panel.grid=element_blank(),legend.text=element_text(family=myfont,size=12),legend.title=element_text(family=myfont,size=15,hjust=1),plot.title=element_text(family=myfont,size=35),plot.caption=element_text(family=myfont,size=18,hjust=0,lineheight=1.2)showtext.end()dev.off()
write.table (myjob[1:100,],d:/r/file/shixiseng_job.csv,sep=,,row.names=false)
前一百个实习生需求最旺盛企业:
先做一个地域分布图:
add%as.data.frame(stringsasfactors=false)%>%arrange(desc(freq))%>%filter(nchar(var1)==2)
#城市经纬度查询:library(rjson)library(rcurl)library(remap)library(baidumap)addressbaidu_lng baidu_lat akfor(location in address){urlurl_string msg.load json msg.load },error=function(e) {errorif(msg.load=='error'){sys.sleep(runif(1,3,10))msg.load connect msg.load }, error = function(e){errorgeo if(msg.load=='error'){lnglat}else{lnglatif(length(lng) == 0){lng lat lnglatbaidu_lngbaidu_latresultpointdata
#成功获取目标城市经纬度信息:
解析来制作分布图:
geojson encoding(geojson$name)china_mapdatachina_mapdataploygoncairopng(file=e:/微信公众号/公众号——数据小魔方/2017年5月/20170512/shixiseng_jobcity.png,width=1200,height=640)showtext.begin()ggplot()+geom_polygon(data=china_mapdataploygon,aes(x=long,y=lat,group=group),col=grey60,fill=white,size=.2,alpha=.4)+geom_point(data=pointdata,aes(x=long,y=lat,size=freq),shape=21,fill=#c72e29,col=#014d64,alpha=0.6)+scale_size_area(max_size=15,guide=guide_legend(reverse=true,title=null))+coord_map(polyconic) +labs(title=实习僧职位需求城市分布图,caption=数据来源:实习僧官网)+theme(title=element_text(family=myfont,size=18),plot.title=element_text(size=24),plot.caption=element_text(family=myfont,size=18,hjust=0),panel.grid = element_blank(),panel.background = element_blank(),axis.text = element_blank(),axis.ticks = element_blank(),axis.title = element_blank(),legend.position = c(0.02,0.6),showtext.end()dev.off()
从第三个问题及其分析结果上我们已经看出了整体形势,北上广深依然是需求最为旺盛的地区,这也符合城市的实际经济发展情况及我们的预期。
cairopng(file=e:/微信公众号/公众号——数据小魔方/2017年5月/20170512/jingjixue2.png,width=800,height=600)showtext.begin()ggplot(pointdata[1:20,],aes(reorder(var1,freq),freq))+geom_bar(fill=#0c8dc4,stat=identity)+coord_flip()+labs(title=实习僧职位需求城市分布,caption=数据来源:实习僧官网)+geom_text(aes(y=freq+25,label=freq),hjust=2,colour=#c72e29,size=5)+theme_bw()+theme(panel.border=element_blank(),panel.grid.major=element_line(linetype=dashed),panel.grid.minor=element_blank(),plot.title=element_text(size=15,colour=#003087,family=myfont),plot.caption=element_text(hjust=0,size=10),axis.title=element_blank(),axis.text=element_text(size=15)showtext.end()dev.off()
myjob_salarymyjob_salary$salary_lowmyjob_salary$salary_highmyjob_salary%arrange(salary_high)%>%filter(salary_high>=20&salary_highmyjob_salary$idmyjob_salary$meansalarycairopng(file=e:/微信公众号/公众号——数据小魔方/2017年5月/20170512/shixiseng_jobsaleryarea.png,width=1200,height=800)showtext.begin()ggplot(myjob_salary,aes(id))+geom_ribbon(aes(ymin=salary_low,ymax=salary_high),fill = grey70)+labs(title=实习僧职位工资区间分布,caption=数据来源:实习僧官网)+geom_line(aes(y=meansalary))+theme_minimal()+theme(panel.border=element_blank(),panel.grid.major=element_line(linetype=dashed),panel.grid.minor=element_blank(),plot.title=element_text(size=30,colour=#003087,family=myfont),plot.caption=element_text(hjust=0,size=20),axis.title=element_blank(),axis.text.y=element_text(size=15),axis.text.x=element_blank()showtext.end()dev.off()
myjob_salary$address_unique%as.data.frame(stringsasfactors=false)salary100%arrange(desc(freq));names(salary100)cairopng(file=e:/微信公众号/公众号——数据小魔方/2017年5月/20170512/salary100.png,width=1200,height=900)showtext.begin()ggplot(salary100[salary100$num>=5,],aes(reorder(city,-num),num))+geom_bar(fill=#0c8dc4,stat=identity)+labs(title=实习僧职位薪资城市分布(日薪低于100),caption=数据来源:实习僧官网)+geom_text(aes(y=num+10,label=num),hjust=.5,colour=#c72e29,size=5)+theme_bw()+theme(panel.border=element_blank(),panel.grid.major=element_line(linetype=dashed),panel.grid.minor=element_blank(),plot.title=element_text(size=25,colour=#003087,family=myfont),plot.caption=element_text(hjust=0,size=18),axis.title=element_blank(),axis.text=element_text(size=15)showtext.end()dev.off()
salary200%filter(meansalary>=200)%>%select(address_unique)%>%table()%>%as.data.frame(stringsasfactors=false)salary200%arrange(desc(freq));names(salary200)cairopng(file=e:/微信公众号/公众号——数据小魔方/2017年5月/20170512/salary200.png,width=1200,height=900)showtext.begin()ggplot(salary200,aes(reorder(city,-num),num))+geom_bar(fill=#0c8dc4,stat=identity)+labs(title=实习僧职位薪资城市分布(日薪高于200),caption=数据来源:实习僧官网)+geom_text(aes(y=num+10,label=num),hjust=.5,colour=#c72e29,size=5)+theme_bw()+theme(panel.border=element_blank(),panel.grid.major=element_line(linetype=dashed),panel.grid.minor=element_blank(),plot.title=element_text(size=25,colour=#003087,family=myfont),plot.caption=element_text(hjust=0,size=18),axis.title=element_blank(),axis.text=element_text(size=15)showtext.end()dev.off()
salary100_200%filter(meansalary>100 & meansalary%select(address_unique)%>%table()%>%as.data.frame(stringsasfactors=false)salary100_200%arrange(desc(freq));names(salary100_200)cairopng(file=e:/微信公众号/公众号——数据小魔方/2017年5月/20170512/salary100-200.png,width=1600,height=900)showtext.begin()ggplot(salary100_200,aes(reorder(city,-num),num))+geom_bar(fill=#0c8dc4,stat=identity)+labs(title=实习僧职位薪资城市分布(日薪处于100-200之间),caption=数据来源:实习僧官网)+geom_text(aes(y=num+10,label=num),hjust=.5,colour=#c72e29,size=5)+theme_bw()+theme(panel.border=element_blank(),panel.grid.major=element_line(linetype=dashed),panel.grid.minor=element_blank(),plot.title=element_text(size=25,colour=#003087,family=myfont),plot.caption=element_text(hjust=0,size=18),axis.title=element_blank(),axis.text=element_text(size=15)showtext.end()dev.off()
分析到这里,趋势已经很明显了,因为北上广深等一线城市的职位实在是太多了,无论是高新职位还是低薪实习岗位都能排在全国各城市�...