本文利用Hadoop+Hive技术分析就业生毕业后就业信息,对所包含职业、岗位、薪资、所在城市、行业类别等数据信息进行模拟,分析与处理,提取出匹配到的目标数据并将其归类化处理.得出各大城市就业生就业情况数据,为大数据时代应聘人员及高校制定人才培养方案提供数据参考.
关键词:就业;就业生;大数据
1.1 目的
教育部发文,今年高校毕业生超千万,就业形势严峻
内卷现状加剧,2022应届生超千万,蓝领或成就业新风口
超千万应届毕业生,加剧就业内卷,蓝领成为就业新风口
去年,“内卷”一词火遍全网。到底什么是内卷呢?在我看来,内卷的底层逻辑还是“优胜劣汰”。蛋糕就这么大,想分蛋糕的人却日益增长,资源有限,只有通过这样的方式淘汰“躺平”的人。
我们每年都在说,今年就业是最难的。但是据数据显示,应届生一年比一年多,就业是一年比一年难。预计2022年全国高校毕业生中研究生近130万人、985、211毕业生达到75万,一本毕业生超过100万,二本毕业生近370万,专科毕业生近460万。
再加上国外疫情日渐严重,预计超过100万的留学生选择回国就业。这部分高学历的精英人才,回国求职,对于同期毕业的高校毕业生就业,造成巨大的冲击。高学历人才越来越不稀缺,同样的竞争也更激烈,想要成功就业,难度可想而知。
毕业除了就业,还可以考研,今年的考研人数达到了462万!!!于是考研教室出现了“宁可累死自己,也要卷死同学”的标语。在学校都这么卷,可想而知,就业之后的内卷有多严重。
也有人放弃内卷,认为这是一种毫无意义的内耗。所以选择了躺平。或者说不是不卷了,而是卷了半天,也卷不过来,所以选择了放弃。也有人选择跳出内卷,选择了另一种人生。世界这么大,没必要让自己在内卷中消耗,最后身心俱疲。
其实不管是公考、考研还是就业压力都非常大。再加上现在的环境和经济现状,以后就业只会越来越难。所以尽早地做好职业规划,增强自身的综合实力和素质,才能避免就业内卷。
最近一段时间,随着消费和制造业的回暖,各行各业的用工需求持续上升,缺口变大,提早出现了“用工荒”。在最缺工的100个职业当中,前三名均是服务业,随着下半年制造业订单的增加,蓝领工人的需求也大幅增长。
近几年,由于技术工人的缺口太大,一些蓝领的薪资待遇,早已经超过大部分白领。而今年,这种差距变得更大了。所以,当你还在白领中内卷时,其他人已经在蓝领中“躺平”。有数据显示,今年的第三季度,我国最缺工的100各职业中,有19个职业与制造业有关。
在如今“技工荒”的背景下,有着专业技能的技能型人才市场缺口更大、薪酬更高,这也证明了那句“技能在手、衣食无忧”。
如果你正身处大一、大二刚进入大学生活,可以提前做好职业生涯规划。分析近几年的就业数据报告,结合自身专业、特点、兴趣爱好等,找到适合自己的职业方向,提高自身专业实力和素质。
如果你身处大三大四,面临就业边缘,那就要分析当前的就业稀缺岗位,就业压力小的城市,也可以去了解一些待遇好、有编制、竞争小的工作。
其实无论蓝领还是白领,要清醒地意识到,搞钱才是第一位。所以,内卷不是必须的。最后希望每个人可以跳出内卷,找到属于自己的道路,拥有光明的未来。
1.2 意义
本课题通过大数据HIVE数仓技术对就业生就业数据分析,计算全国各个地区就业率,行业从业情况,平均薪资。对分析结果进行地图化、可视化,为就业生就业参考,为各大学校培养人才提供针对方向。
1.3 就业现状
学生就业状况:一半在校生对就业感到忧心、七成毕业生认为应先就业后择业、研究生期望薪酬逼近本科生、职业规划辅导迫在眉睫、自主创业缺资金缺人脉缺理念。
2.1 数据来源
本研究使用java模拟全国各地就业生就业数据,需要包含省份,城市,姓名,就业状态,月薪,从事行业,岗位职级。模拟数据文件存储为txt文本格式,各字段使用英文状态逗号分隔。
2.2 数据采集
使用flume将生成的数据从本地采集到HDFS文件系统中存储。
首先配置jiuye.conf,配置日志文件采集目录和HDFS上存放目录。然后使用flume-ng agent –n a1 –c ./conf –f ./jiuye.conf来启动flume采集任务。
2.3 数据清洗
使用java语言编写mapreduce程序,对2.2步骤模拟的就业生就业数据文件进行清洗,清洗规则包含:数据字段数是否正确和去除重复数据。
2.4 数据分析
采用hive离线数仓结构对数据进行分析。
首先创建一个名称为jiuye的数据库;
其次使用load data inpath xxx命令将清洗后的数据导入到hive的ODS层数据表中;
然后使用ODS层数据进行指标分析,将分析结果存储到DWS层中;
然后再将DWS层数据进一步加工成业务可视化展示的ADS层数据。最后使用SQOOP数据导出工具,将hive中ADS层数据导出到mysql表中。
分析展示指标包含:
2.5 数据可视化
使用springboot,mybatis,eachrts等技术开发web应用系统对使用sqoop从hive分析的各项指标导出到mysql的数进行图形可视化展示。
具体图形如下:
3.1 开发使用软件版本
操作系统: windows10专业版和linux系统
开发工具: IDEA2020.1
JDK:1.8
虚拟机:Oracle VM VirtualBox
HADOOP:3.2.2
HIVE:3.1.2
SQOOP:1.4.2
Flume:1.9.0
MYSQL:5.7
MobaXterm:10.2
3.2 技术简介
3.2.1 Java
3.2.2 Hadoop
3.2.3 Hive
3.2.4 Sqoop
3.2.5 Springboot
3.2.6 Echarts
4.1 系统结构图
5.1 数据生成
使用java程序模拟全国各个省市就业生就业数据。
首先按照省份,城市的方式构造出各省份辖市的字符串数组。
其次设定就业和待业两个就业状态。
其次设定岗位职级
然后设置行业
通过循环遍历城市来模拟所有省市的就业升级就业数据。
模拟的数据使用java字符流输出到数据文件中。
5.2数据采集
使用flume从本地磁盘采集静态数据到HDFS分布式文件系统中。
首先定义agent名, source、channel、sink的名称
a1.sources = r1
a1.channels = c1
a1.sinks = k1
其次具体定义source
a1.sources.r1.type = spooldir
指定从本地采集的目录
a1.sources.r1.spoolDir = /root/jiuye/data
定义具体channel
a1.channels.c1.type = memory
a1.channels.c1.capacity = 10000
a1.channels.c1.transactionCapacity = 100
定义具体sink
a1.sinks.k1.type = hdfs
指定flume采集的数据在hdfs上的存放路径
a1.sinks.k1.hdfs.path = hdfs://hadoop:9000/jiuye/input
指定生成文件的前缀
a1.sinks.k1.hdfs.filePrefix = power
以数据流的方式传输
a1.sinks.k1.hdfs.fileType = DataStream
不按照条数生成文件
a1.sinks.k1.hdfs.rollCount = 0
HDFS上的文件达到128M时生成一个文件
a1.sinks.k1.hdfs.rollSize = 134217728
HDFS上的文件达到10秒生成一个文件
a1.sinks.k1.hdfs.rollInterval = 10
组装source、channel、sink
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
配置后使用flume-ng命令启动采集程序,将java产生的数据文件上传到hdfs上。
flume-ng -n a1 -c ./conf –f ./conf/jiuye.conf
5.3 数据清洗
使用java语句开发MapReduce程序,对采集到hdfs中的数据文件进行清洗,清洗规则包含数据字段数量,数据字段类型,去除重复数据。
在map阶段,按行读取数据文件,然后将这行数据按照逗号分隔符切分成字符串数组。第一列是省份,第二列是市名,第三列是就业生姓名,第四列是就业状态,第五列是月薪,第六列是行业,第七列是岗位职级。
对切分后的数据调用length方法获得字符串数组长度,如果字符串数组长度不为四,那么认为该条数据为脏数据,需要跳过不处理;
对第五列字段月薪判断是否为整数,如果不是整数则认为是脏数据,需要跳过该行数据不处理。
在reduce阶段,对map处理后的结果进行去重处理。
5.4 创建hive库
使用hive命令进入hive交互命令窗口。如果不存在power数据库那么就创建。
CREATE DATABASE IF NOT EXISTS jiuye;
5.5 ODS层
首先使用use jiuye命令进入jiuye库。然后先判断是否存在ods_datas表,如果存在就删除。
DROP TABLE IF EXISTS power.ods_datas;
然后使用create table命令创建ods_datas表。
CREATE TABLE IF NOT EXISTS power.ods_datas(
province string,
city string,
name string,
flg string,
salary int,
trade string,
rank string)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
将存在HDFS上清洗后的数据使用load data inpath导入进ods_datas表中。
load data inpath '/output/*' into table jiuye.ods_datas;
然后使用select * from ods_datas limit 10;验证数据是否导入成功。如果能查询到数据那么认为数据已经导入。
5.6 DWS层
首先判断DWS层的数据表是否存在,如果存在则删除。然后使用create table命令创建DWS层表。
省市表
DROP TABLE IF EXISTS jiuye.dws_city;
CREATE TABLE IF NOT EXISTS jiuye.dws_city(
province string,
city string
)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
insert into table jiuye.dws_city
select province,city from jiuye.ods_datas group by province,city;
省份平均薪资表
DROP TABLE IF EXISTS jiuye.dws_salary_province;
CREATE TABLE IF NOT EXISTS jiuye.dws_salary_province(
name string,
value double
)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
insert into table jiuye.dws_salary_province
select province,sum(salary)/count(province) from jiuye.ods_datas where flg = '就业' group by province;
辖市平均薪资
DROP TABLE IF EXISTS jiuye.dws_salary_city;
CREATE TABLE IF NOT EXISTS jiuye.dws_salary_city(
province string,
city string,
value double
)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
insert into table jiuye.dws_salary_city
select province,city,sum(salary)/count(city) from jiuye.ods_datas where flg = '就业' group by province,city;
省份就业率
DROP TABLE IF EXISTS jiuye.dws_work_province;
CREATE TABLE IF NOT EXISTS jiuye.dws_work_province(
province string,
value double
)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
insert into table jiuye.dws_work_province
select province,sum(case when flg='就业' then 1 else 0 end)/count(*)*100.0 from jiuye.ods_datas group by province;
省份从事行业人数
DROP TABLE IF EXISTS jiuye.dws_industry_province;
CREATE TABLE IF NOT EXISTS jiuye.dws_industry_province(
province string,
name string,
num int
)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
insert into table jiuye.dws_industry_province
select province,trade,count(trade) from jiuye.ods_datas group by province,trade;
辖市从事行业人数
DROP TABLE IF EXISTS jiuye.dws_industry_city;
CREATE TABLE IF NOT EXISTS jiuye.dws_industry_city(
province string,
city string,
name string,
num int
)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
insert into table jiuye.dws_industry_city
select province,city,trade,count(trade) from jiuye.ods_datas group by province,city,trade;
省份各职级人数
DROP TABLE IF EXISTS jiuye.dws_rank_province;
CREATE TABLE IF NOT EXISTS jiuye.dws_rank_province(
province string,
name string,
num int
)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
insert into table jiuye.dws_rank_province
select province,rank,count(rank) from jiuye.ods_datas group by province,rank;
辖市各职级人数
DROP TABLE IF EXISTS jiuye.dws_rank_city;
CREATE TABLE IF NOT EXISTS jiuye.dws_rank_city(
province string,
city string,
name string,
num int
)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
insert into table jiuye.dws_rank_city
select province,city,rank,count(rank) from jiuye.ods_datas group by province,city,rank;
5.7 ADS层
首先判断ADS层数据表是否存在,如果存在就删除。然后创建ADS层数据表。最后使用insert into table ads_xxx select * from dws_xxx语句将DWS层计算结果插入到ADS层数据表中。具体语句如下:
DROP TABLE IF EXISTS jiuye.ads_city;
CREATE TABLE IF NOT EXISTS jiuye.ads_city(
id int,
province string,
city string
)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
insert into table jiuye.ads_city
select row_number() over(),province,city from jiuye.dws_city group by province,city;
DROP TABLE IF EXISTS jiuye.ads_salary_province;
CREATE TABLE IF NOT EXISTS jiuye.ads_salary_province(
id int,
name string,
value double
)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
insert into table jiuye.ads_salary_province
select row_number() over(),name,value from jiuye.dws_salary_province;
DROP TABLE IF EXISTS jiuye.ads_salary_city;
CREATE TABLE IF NOT EXISTS jiuye.ads_salary_city(
id int,
province string,
city string,
value double
)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
insert into table jiuye.ads_salary_city
select row_number() over(),province,city,value from jiuye.dws_salary_city;
DROP TABLE IF EXISTS jiuye.ads_work_province;
CREATE TABLE IF NOT EXISTS jiuye.ads_work_province(
id int,
province string,
value double
)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
insert into table jiuye.ads_work_province
select row_number() over(),province,value from jiuye.dws_work_province;
DROP TABLE IF EXISTS jiuye.ads_work_city;
CREATE TABLE IF NOT EXISTS jiuye.ads_work_city(
id int,
province string,
city string,
value double
)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
insert into table jiuye.ads_work_city
select row_number() over(),province,city,value from jiuye.dws_work_city;
DROP TABLE IF EXISTS jiuye.ads_industry_province;
CREATE TABLE IF NOT EXISTS jiuye.ads_industry_province(
id int,
province string,
name string,
num int
)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
insert into table jiuye.ads_industry_province
select row_number() over(),province,name,num from jiuye.dws_industry_province;
DROP TABLE IF EXISTS jiuye.ads_industry_city;
CREATE TABLE IF NOT EXISTS jiuye.ads_industry_city(
id int,
province string,
city string,
name string,
num int
)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
insert into table jiuye.ads_industry_city
select row_number() over(),province,city,name,num from jiuye.dws_industry_city;
DROP TABLE IF EXISTS jiuye.ads_rank_province;
CREATE TABLE IF NOT EXISTS jiuye.ads_rank_province(
id int,
province string,
name string,
num int
)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
insert into table jiuye.ads_rank_province
select row_number() over(),province,name,num from jiuye.dws_rank_province;
DROP TABLE IF EXISTS jiuye.ads_rank_city;
CREATE TABLE IF NOT EXISTS jiuye.ads_rank_city(
id int,
province string,
city string,
name string,
num int
)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
insert into table jiuye.ads_rank_city
select row_number() over(),province,city,name,num from jiuye.dws_rank_city;
5.8 Mysql数据库
首先使用Navicat工具连接到mysql数据库,然后创建对应的数据表,建表语句如下:
DROP TABLE IF EXISTS `city`;
CREATE TABLE `city` (
`id` int(11) NOT NULL,
`province` varchar(10) NOT NULL,
`city` varchar(10) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
DROP TABLE IF EXISTS `industry_city`;
CREATE TABLE `industry_city` (
`id` int(11) NOT NULL,
`province` varchar(10) DEFAULT NULL,
`city` varchar(10) DEFAULT NULL,
`name` varchar(10) DEFAULT NULL,
`value` int(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
DROP TABLE IF EXISTS `industry_province`;
CREATE TABLE `industry_province` (
`id` int(11) NOT NULL,
`province` varchar(10) DEFAULT NULL,
`name` varchar(10) DEFAULT NULL,
`value` int(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
DROP TABLE IF EXISTS `rank_city`;
CREATE TABLE `rank_city` (
`id` int(11) NOT NULL,
`province` varchar(10) DEFAULT NULL,
`city` varchar(10) DEFAULT NULL,
`name` varchar(10) DEFAULT NULL,
`value` int(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
DROP TABLE IF EXISTS `rank_province`;
CREATE TABLE `rank_province` (
`id` int(11) NOT NULL,
`province` varchar(10) DEFAULT NULL,
`name` varchar(10) DEFAULT NULL,
`value` int(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
DROP TABLE IF EXISTS `salary_city`;
CREATE TABLE `salary_city` (
`id` int(11) NOT NULL,
`province` varchar(10) DEFAULT NULL,
`city` varchar(10) DEFAULT NULL,
`value` double(6,2) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
DROP TABLE IF EXISTS `salary_province`;
CREATE TABLE `salary_province` (
`id` int(11) NOT NULL,
`name` varchar(10) DEFAULT NULL,
`value` double(6,2) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
DROP TABLE IF EXISTS `work_city`;
CREATE TABLE `work_city` (
`id` int(11) NOT NULL,
`province` varchar(10) DEFAULT NULL,
`city` varchar(10) DEFAULT NULL,
`value` double(6,2) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
DROP TABLE IF EXISTS `work_province`;
CREATE TABLE `work_province` (
`id` int(11) NOT NULL,
`name` varchar(10) DEFAULT NULL,
`value` double(6,2) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
5.9 Sqoop数据导出
使用sqoop export命令从hive ADS层数据表在hdfs的数据文件中导出数据到对应mysql数据表中。
####城市数据导出mysql
echo "export data to city..."
sqoop export \
--connect "jdbc:mysql://192.168.57.1:3306/jiuye?useUnicode=true&characterEncoding=utf-8" \
--username root \
--password 123456 \
--table city \
--export-dir /user/hive/warehouse/jiuye.db/ads_city \
--input-null-string '\\N' \
--input-null-non-string '\\N' \
--input-fields-terminated-by ',' \
--fields-terminated-by ','
echo "export data to salary_city..."
sqoop export \
--connect "jdbc:mysql://192.168.57.1:3306/jiuye?useUnicode=true&characterEncoding=utf-8" \
--username root \
--password 123456 \
--table salary_city \
--export-dir /user/hive/warehouse/jiuye.db/ads_salary_city \
--input-null-string '\\N' \
--input-null-non-string '\\N' \
--input-fields-terminated-by ',' \
--fields-terminated-by ','
echo "export data to salary_province..."
sqoop export \
--connect "jdbc:mysql://192.168.57.1:3306/jiuye?useUnicode=true&characterEncoding=utf-8" \
--username root \
--password 123456 \
--table salary_province \
--export-dir /user/hive/warehouse/jiuye.db/ads_salary_province \
--input-null-string '\\N' \
--input-null-non-string '\\N' \
--input-fields-terminated-by ',' \
--fields-terminated-by ','
echo "export data to work_city..."
sqoop export \
--connect "jdbc:mysql://192.168.57.1:3306/jiuye?useUnicode=true&characterEncoding=utf-8" \
--username root \
--password 123456 \
--table work_city \
--export-dir /user/hive/warehouse/jiuye.db/ads_work_city \
--input-null-string '\\N' \
--input-null-non-string '\\N' \
--input-fields-terminated-by ',' \
--fields-terminated-by ','
echo "export data to work_province..."
sqoop export \
--connect "jdbc:mysql://192.168.57.1:3306/jiuye?useUnicode=true&characterEncoding=utf-8" \
--username root \
--password 123456 \
--table work_province \
--export-dir /user/hive/warehouse/jiuye.db/ads_work_province \
--input-null-string '\\N' \
--input-null-non-string '\\N' \
--input-fields-terminated-by ',' \
--fields-terminated-by ','
echo "export data to industry_province..."
sqoop export \
--connect "jdbc:mysql://192.168.57.1:3306/jiuye?useUnicode=true&characterEncoding=utf-8" \
--username root \
--password 123456 \
--table industry_province \
--export-dir /user/hive/warehouse/jiuye.db/ads_industry_province \
--input-null-string '\\N' \
--input-null-non-string '\\N' \
--input-fields-terminated-by ',' \
--fields-terminated-by ','
echo "export data to industry_city..."
sqoop export \
--connect "jdbc:mysql://192.168.57.1:3306/jiuye?useUnicode=true&characterEncoding=utf-8" \
--username root \
--password 123456 \
--table industry_city \
--export-dir /user/hive/warehouse/jiuye.db/ads_industry_city \
--input-null-string '\\N' \
--input-null-non-string '\\N' \
--input-fields-terminated-by ',' \
--fields-terminated-by ','
echo "export data to rank_city..."
sqoop export \
--connect "jdbc:mysql://192.168.57.1:3306/jiuye?useUnicode=true&characterEncoding=utf-8" \
--username root \
--password 123456 \
--table rank_city \
--export-dir /user/hive/warehouse/jiuye.db/ads_rank_city \
--input-null-string '\\N' \
--input-null-non-string '\\N' \
--input-fields-terminated-by ',' \
--fields-terminated-by ','
echo "export data to rank_province..."
sqoop export \
--connect "jdbc:mysql://192.168.57.1:3306/jiuye?useUnicode=true&characterEncoding=utf-8" \
--username root \
--password 123456 \
--table rank_province \
--export-dir /user/hive/warehouse/jiuye.db/ads_rank_province \
--input-null-string '\\N' \
--input-null-non-string '\\N' \
--input-fields-terminated-by ',' \
--fields-terminated-by ','
5.10 可视化图表
5.10.1 各省份就业生平均薪资(地图)
通过地图颜色的深浅来表示工资的高低。
5.10.2 各省份就业生就业率(地图)
通过地图颜色生气来表示就业率的高低。
5.10.3 各省份就业生从事行业占比(饼图)
通过查询省份/直辖市展示出改地区就业生从事行业占比情况。
5.10.4 各省份就业生职级占比(饼图)
通过查询省份/直辖市展示出改地区就业生岗位职级占比情况。
5.10.5 各辖市就业生平均薪资(柱状)
通过查询省份/直辖市展示出该省份下所有市区就业生平均薪资。
5.10.6 各辖市就业生就业率(柱状)
通过查询省份/直辖市展示出该省份下所有市区就业生就业率。
5.10.7 各辖市就业生从事行业占比(饼图)
通过查询省份和市展示出该地区就业生从事行业占比。
5.10.8 各辖市就业生职级人数占比(饼图)
通过查询省份和市展示出该地区就业生职级人数占比。
7.1 数据清洗模块
7.1.1 模块设计
使用java语言结合hadoop的MapReduce数据分析框架,开发程序对原始数据镜像ETL清洗。
在map阶段将原始数据按行读取,然后将行数据作为字符串处理,然后使用英文逗号对行数据切分,切分后获得字段数组。
其次,对字段数组进行判断,如果数组长度不为七,则判断为脏数据;
如果符合要求则将这行数据作为map阶段输出的key,NullWrite作为value输出。
在reduce阶段,map阶段相同的key,如果存在多条,那么就存在重复数据,这里直接将key输出即可去重。
7.1.2 核心代码
package com.etl;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.CombineTextInputFormat;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;
import java.io.IOException;
/**
* 数据清洗存储到hdfs
*/
public class ETLMain {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
String[] otherArgs = new GenericOptionsParser(args).getRemainingArgs();
if (otherArgs.length != 2) {
System.out.println("参数错误.<input path> <output path>");
System.exit(2);
}
Configuration conf = new Configuration();
Job job = Job.getInstance(conf, "etl data");
job.setJarByClass(ETLMain.class);
job.setMapperClass(map.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(NullWritable.class);
job.setReducerClass(reduce.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(NullWritable.class);
//设置小文件合并
job.setInputFormatClass(CombineTextInputFormat.class);
CombineTextInputFormat.setMaxInputSplitSize(job, 1024 * 1024 * 128);
// 设置需要统计的文件的输入路径
FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
private static class map extends Mapper<LongWritable, Text, Text, NullWritable> {
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
try {
String[] fields = value.toString().split(",");
if (fields.length != 7) {//字段数量
return;
}
context.write(value, NullWritable.get());
} catch (Exception e) {
return;
}
}
}
private static class reduce extends Reducer<Text, NullWritable, Text, NullWritable> {
@Override
protected void reduce(Text key, Iterable<NullWritable> values, Context context) throws IOException, InterruptedException {
context.write(key, NullWritable.get());
}
}
}
7.2 首页-各省份就业生平均薪资
7.2.1 模块设计
首先使用springboot开发数据获取接口,然后使用ecahrts对查询的数据展示到地图中。
7.2.2 功能截图
7.2.3 核心代码
数据接口
@GetMapping("/salary_provinceD")
public Object salary_provinceD() {
return salaryProvinceMapper.selectByMap(null);
}
Echarts解析地图数据
var myChart = echarts.init(document.getElementById('main'));
option = {
title: {
text: '各省份就业生平均薪资'
},
tooltip: {
formatter: function (params, ticket, callback) {
return '平均薪资<br />' + params.name + ':' + params.value
}//数据格式化
},
visualMap: {
min: 5000,
max: 8000,
left: 'left',
top: 'bottom',
text: ['高', '低'],//取值范围的文字
inRange: {
color: ['#ffffff', '#ff0000']//取值范围的颜色
},
show: true//图注
},
geo: {
map: 'china',
roam: false,//不开启缩放和平移
zoom: 1.23,//视角缩放比例
label: {
normal: {
show: true,
fontSize: '14',
color: '#000000'
}
},
itemStyle: {
normal: {
borderColor: 'rgba(0, 0, 0, 0.2)'
},
emphasis: {
areaColor: '#F3B329',//鼠标选择区域颜色
shadowOffsetX: 0,
shadowOffsetY: 0,
shadowBlur: 20,
borderWidth: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
},
series: [
{
name: '各省份就业生平均薪资',
type: 'map',
geoIndex: 0,
data: []
}
]
};
function load() {
var d = new Date();
var y = d.getFullYear();
var m = d.getMonth() + 1;
var mm = m > 9 ? m : '0' + m;
var day = d.getDate();
var dd = day > 9 ? day : '0' + day;
var dm = (y + "-" + mm + "-" + dd);
console.log(dm);
fetch("/salary_provinceD").then(response => response.json()).then(res => {
// map
option.series[0].data = res
myChart.setOption(option);
})
}
使用IDEA开发完代码后,启动项目。使用浏览器打开控制台提示的访问地址。
鼠标点击左侧各项导航栏,看数据图表是否能正常显示。
首先本课题数据时使用java模拟与真实数据存在差异;从业务逻辑和模拟数据分析结果来看,全国各地区就业率和薪资基本持平。
参考文献
[1]刘艳. 基于大数据的高校毕业生就业指导分析[J]. 数码设计, 2019, 8(5):3.
[2]忻桓辰, 张书娟, 李建敦,等. 基于大数据的就业服务系统[J]. 商情, 2019, 000(017):134-136.
[3]胡文晶, 张磊. 大学应届生谈找工作[J]. 大众心理学, 2006(1):2.
[4]李唐宁. "更难就业季"应届毕业生就业境况如何?[J]. 劳动保障世界, 2014(11):1.
[5]王永和, 张劲松, 邓安明,等. Spring Boot研究和应用[J]. 信息通信, 2016(10):4.
[6]徐雯, 高建华. 基于Spring MVC及MyBatis的Web应用框架研究[J]. 微型电脑应用, 2012, 28(7):5.
[7]薛峰, 梁锋, 徐书勋,等. 基于Spring MVC框架的Web研究与应用[J]. 合肥工业大学学报:自然科学版, 2012, 35(3):4.
光阴荏苒,美好的大学时光即将画上一个句号。回望过去,仿佛昨日。孜孜不倦的老师,善良可爱的同学,美丽幽静的校园,一直陪伴着我,见证了我的成长。
第一次独自离家求学,哭过、害怕过,正是因为有远方亲人的鼓励支持,身边老师同学的关心帮助,我才能快速的适应新的环境,顺利的完成学业。
历时半年之久的论文写作,终于结束了。从最初的选题、写开题报告,到后来的初稿、定稿,并不是一帆风顺的。在这期间,有很多人给我帮助,给我建议。
首先,我要感谢指导老师对我的悉心指导。在我没能及时跟老师联系,讨论论文问题的时候,老师打电话提醒我,给我提出问题,让我及时改正。老师诲人不倦的精神,治学严谨的态度,让我无比钦佩。还要感谢大学期间遇到的其他老师,谢谢你们让我在学到知识的同时,也学到了如何做人,你们的言传身教将让我一生受用。
最后,我还要感谢我的亲人,谢谢你们在远方对我的关心、支持与鼓励,让背井离乡的我依然感受到温暖。
我始终相信,没有比人更高的山峰,没有比脚印更长的旅程!虽然大学生活即将结束,但学习是永无止境的。我将继续前行,去攀登知识的高峰,踏遍学问的大道,生命不息,奋斗不止!
四年的大学生活就快走入尾声,我们的校园生活就要划上句号,心中是无尽的难舍与眷恋。从这里走出,对我的人生来说,将是踏上一个新的征程,要把所学的知识应用到实际工作中去。
回首四年,取得了些许成绩,生活中有快乐也有艰辛。感谢老师四年来对我孜孜不倦的教诲,对我成长的关心和爱护。
学友情深,情同兄妹。四年的风风雨雨,我们一同走过,充满着关爱,给我留下了值得珍藏的最美好的记忆。
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳
我即将开始一个将录制和编辑音频文件的项目,我正在寻找一个好的库(最好是Ruby,但会考虑Java或.NET以外的任何库)以进行实时可视化波形。有人知道我应该从哪里开始搜索吗? 最佳答案 要流入浏览器的数据量很大。Flash或Flex图表可能是唯一能提高内存效率的解决方案。Javascript图表往往会因大型数据集而崩溃。 关于ruby-Ruby中的波形可视化,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.c
我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01 客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02 数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit
文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co
我正在尝试在Rails上安装ruby,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf