基于Hadoop实现的对历年四级单词的词频分析(入门级Hadoop项目)
前情提要:飞物作者屡次四级考试未能通过,进而恼羞成怒,制作了基于Hadoop实现的对历年四级单词的词频分析项目,希望督促自己尽快通过四级(然而并没有什么卵用)
项目需求:Pycharm、IDEA、Linux、Hadoop运行环境、Hive、beeline、八爪鱼采集器
数据来源:https://zhenti.burningvocabulary.cn/cet4
“如果你想要数据,就得自己来拿,这规矩你早就懂得” ——某V姓男子
一、 数据采集
1.从目标网站上获取所需要的网址
用来获取数据的网站是一个由主界面指向各个题目页面的分支结构,所以需要使用Python爬虫从主界面获取每一个题目页面的网址
# 从该四级真题主网站上获取各个具体题目页面的链接网址
import re
import requests
# 防止爬虫被拦截
header = {
'User-Agent': 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.193 Safari/537.36'
}
httpsGet = requests.get("https://zhenti.burningvocabulary.cn/cet4", headers=header) # 爬取整个页面
httpsTxt = open(r"E:\ShuJu\SiJiDanCi\AllWWW.txt", 'w', encoding='utf-8') # 创建储存网站信息的txt文件(真正的英语大佬都在使用拼音来命名文件夹)
httpsTxt.write(httpsGet.text) # 将爬取信息存入txt
httpsTxt.close() # 关闭并保存文件
a = open(r"E:\ShuJu\SiJiDanCi\AllWWW.txt", encoding='utf-8').read() # a为主网页的信息
httpsAns = re.findall(
r'<a class="link-primary" href="(.*?)"><div class="card">', a, # 正则表达式查找各页面网址
re.S)
httpsTxt.close() # 关闭存有主网站信息的txt
print(httpsAns) # 输出正则表达式的查找结果
with open(r"E:\ShuJu\SiJiDanCi\cet4WWW.txt", 'w', encoding="UTF8") as f: # 将结果存入文件
for item in httpsAns:
f.write(str(item) + "\t")
f.close()
获得了每一期题目的页面地址
2.使用八爪鱼采集器获取题目数据
(飞物作者用自己的爬虫爬了一天都没能拿到数据,只好借助外力)
点击新建,自定义任务,把需要爬取的网址全部复制粘贴过去,保存设置,然后在页面中点击你需要的文本,然后点击采集按钮就可以启动采集了
采集完成后获得一个存有历年所有英语题目的csv格式文件shuju.csv
之后对该csv文件进行数据处理
二、数据处理
使用Python将存有所有英语题目中的无用数据剔除,获得仅存有所有单词的文本数据
# 将csv格式的文件转换为txt格式
import pandas as pd
df = pd.read_csv(r"E:\ShuJu\SiJiDanCi\shuju.csv", index_col=0)
print(df)
df.to_csv(r"E:\ShuJu\SiJiDanCi\shuju.txt", sep='\t', index=False)
#清洗无用数据
import re
with open(r"E:\ShuJu\SiJiDanCi\shuju.txt", "r", encoding="UTF8") as f: # 读入原始数据
data = f.read()
f.close()
str = re.sub(r"[^a-zA-Z]+", " ", data) # 将非字母型的字符全部替换为空格
str = str.lower() # 将大写字母替换为小写字母
print(str) # 将数据处理情况显示在控制台,查看效果
with open(r"E:\ShuJu\SiJiDanCi\sijiShaitext.txt", 'w', encoding="UTF8") as f: # 将数据写出
f.write(str)
f.close()
最终效果长这个模样
三、Hadoop计算
作者在这里使用三台Linux虚拟机搭建的完全分布式Hadoop集群来进行计算
1.词频统计
首先是大家耳熟能详的wordcount计数 : map和reduce操作
打开IDEA,复制粘贴代码然后导包
Driver
public class WordCountDriver {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
// 1 获取配置信息以及获取job对象
Configuration conf = new Configuration();
Job job = Job.getInstance(conf);
// 2 关联本Driver程序的jar
job.setJarByClass(WordCountDriver.class);
// 3 关联Mapper和Reducer的jar
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.class);
// 4 设置Mapper输出的kv类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
// 5 设置最终输出kv类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
// 6 设置输入和输出路径
FileInputFormat.setInputPaths(job, new Path("E:\\ShuJu\\SiJiDanCi\\sijiShaitext.txt"));
FileOutputFormat.setOutputPath(job, new Path("E:\\ShuJu\\SiJiDanCi\\sijiOUT.txt"));
// 7 提交job
boolean result = job.waitForCompletion(true);
System.exit(result ? 0 : 1);
}
}
Mapper
public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
Text outK = new Text();
IntWritable outV = new IntWritable(1);
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//map被循环遍历,读取文件中的每一行字符串,重写map方法
//1、获取一行存入字符串line
String line = value.toString();
//2、切割存入名为words的字符串数组
String[] words = line.split(" ");//以空格为分界线拆分单词
//3、循环写出,读取words中的各个字符串
for (String word : words) {//从words数组中读出的字符串word
//封装outK
outK.set(word);
//写出
context.write(outK, outV);
}
}
}
Reducer
public class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
int sum;
IntWritable value = new IntWritable();
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
// 1 累加求和
sum = 0;
for (IntWritable count : values) {
sum += count.get();//数据类型切换为int
}
// 2 输出
value.set(sum);
context.write(key, value);
}
}
这样就得到了初步的词频统计结果,默认是按照字母表顺序来排列的
接下来进行一个排序,可以更直观的看出单词的出现情况
(作为一个懒人肯定要挑出现次数高的单词来背)
2.按照单词出现次数递减排序
FlowBean
public class FlowBean implements WritableComparable<FlowBean> {
private long num; //每个单词的个数
//提供无参构造
public FlowBean() {
}
public long getnum() {
return num;
}
public void setnum(long num) {
this.num = num;
}
@Override
public void write(DataOutput out) throws IOException {
out.writeLong(this.num);
}
@Override
public void readFields(DataInput in) throws IOException {
this.num = in.readLong();
}
@Override
public String toString() {
return String.valueOf(num);
}
@Override
public int compareTo(FlowBean o) { //按照单词个数进行递减排序
if (this.num > o.num) {
return -1;
} else if (this.num < o.num) {
return 1;
} else {
return 0;
}
}
}
Driver
public class FlowDriver {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
//1 获取job对象
Configuration conf = new Configuration();
Job job = Job.getInstance(conf);
//2 关联本Driver类
job.setJarByClass(FlowDriver.class);
//3 关联Mapper和Reducer
job.setMapperClass(FlowMapper.class);
job.setReducerClass(FlowReducer.class);
//4 设置Map端输出数据的KV类型
job.setMapOutputKeyClass(FlowBean.class);
job.setMapOutputValueClass(Text.class);
//5 设置程序最终输出的KV类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(FlowBean.class);
//6 设置输入输出路径
FileInputFormat.setInputPaths(job, new Path("E:\\ShuJu\\SiJiDanCi\\sijiOUT.txt\\part-r-00000"));
FileOutputFormat.setOutputPath(job, new Path("E:\\ShuJu\\SiJiDanCi\\sijiOUTCompare"));
//7 提交Job
boolean b = job.waitForCompletion(true);
System.exit(b ? 0 : 1);
}
}
Mapper
public class FlowMapper extends Mapper<LongWritable, Text, FlowBean, Text> {
private FlowBean outK = new FlowBean();
private Text outV = new Text();
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String line = value.toString();
String[] split = line.split("\t");
try {
outK.setnum(Long.parseLong(split[1].trim()));
} catch (ArrayIndexOutOfBoundsException e) {
outK.setnum(Long.parseLong(split[0].trim()));
}
outV.set(split[0]);
//4 写出outK outV
context.write(outK, outV);
}
}
Reducer
public class FlowReducer extends Reducer<FlowBean, Text, Text, FlowBean> {
@Override
protected void reduce(FlowBean key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
for (Text value : values) {
context.write(value, key);
}
}
}
这样就得到了我们想要的数据
四、Hive存储
接下来将数据存入Hive表格便于查询
首先把上面处理好的单词文件上传至HDFS中的/test文件夹中
然后在HDFS上创建一个表来存入数据,位置在/test/WordsData
使用Linux上的beeline客户端连接Hive,输入建表语句,word列存单词,num列存对应出现次数
CREATE EXTERNAL TABLE Words
(
word STRING,
num INT
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
LINES TERMINATED BY '\n'
STORED AS TEXTFILE
LOCATION '/test/WordsData';
将文本文件中的单词数据写入Hive表格
LOAD DATA INPATH '/test/part-r-00000' OVERWRITE INTO TABLE Words;
接下来就可以使用SQL语句愉快的查询各种单词的数据了
select * from Words where num>100;
想必这些操作对大家来说简直有手就行
点我跳转 Ciallo~(∠・ω< )⌒★
基于Hadoop实现的对历年四级单词的词频分析(入门级Hadoop项目)的更多相关文章
- Hadoop2源码分析-Hadoop V2初识
1.概述 在完成分析Hadoop2源码的准备工作后,我们进入到后续的源码学习阶段.本篇博客给大家分享,让大家对Hadoop V2有个初步认识,博客的目录内容如下所示: Hadoop的渊源 Hadoop ...
- Hadoop学习笔记(一):ubuntu虚拟机下的hadoop伪分布式集群搭建
hadoop百度百科:https://baike.baidu.com/item/Hadoop/3526507?fr=aladdin hadoop官网:http://hadoop.apache.org/ ...
- Hadoop源码分析(3): Hadoop的运行痕迹
在使用hadoop的时候,可能遇到各种各样的问题,然而由于hadoop的运行机制比较复杂,因而出现了问题的时候比较难于发现问题. 本文欲通过某种方式跟踪Hadoop的运行痕迹,方便出现问题的时候可以通 ...
- 报错org.apache.hadoop.mapreduce.lib.input.FileSplit cannot be cast to org.apache.hadoop.mapred.FileSplit
报错 java.lang.Exception: java.lang.ClassCastException: org.apache.hadoop.mapreduce.lib.input.FileSpli ...
- Hadoop基础--统计商家id的标签数案例分析
Hadoop基础--统计商家id的标签数案例分析 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.项目需求 将“temptags.txt”中的数据进行分析,统计出商家id的评论标 ...
- 基于TILE-GX实现快速数据包处理框架-netlib实现分析【转】
最近在研究suricata源码,在匹配模式的时候,有tilegx mpipe mode,转载下文,了解一下. 原文地址:http://blog.csdn.net/lhl_blog/article/de ...
- Hadoop学习之路(八)在eclispe上搭建Hadoop开发环境
一.添加插件 将hadoop-eclipse-plugin-2.7.5.jar放入eclipse的plugins文件夹中 二.在Windows上安装Hadoop2.7.5 版本最好与Linux集群中的 ...
- hadoop fs -put上传文件失败,WARN org.apache.hadoop.hdfs.server.datanode.DataNode: Problem connecting to server: master:8020
hadoop fs -put上传文件失败 报错信息:(test文件夹是已经成功建好的) [root@master ~]# hadoop fs -put test1.txt /test // :: WA ...
- ERROR [org.apache.hadoop.util.Shell] - Failed to locate the winutils binary in the hadoop binary path
错误日志如下: -- ::, DEBUG [org.apache.hadoop.metrics2.lib.MutableMetricsFactory] - field org.apache.hadoo ...
- 在HDInsight中从Hadoop的兼容BLOB存储查询大数据的分析
在HDInsight中从Hadoop的兼容BLOB存储查询大数据的分析 低成本的Blob存储是一个强大的.通用的Hadoop兼容Azure存储解决方式无缝集成HDInsight.通过Hadoop分布式 ...
随机推荐
- bx lr
bx lr 的作用等同于 mov pc,lr 即跳转到lr中存放的地址处. 那么lr存放的是什么地址呢? lr就是连接寄存器(Link Register, LR),在ARM体系结构中LR的特殊用途有两 ...
- .NET 9 优化,抢先体验 C# 13 新特性
前言 微软即将在 2024年11月12日发布 .NET 9 的最终版本,而08月09日发布的.NET 9 Preview 7 是最终发布前的最后一个预览版.这个版本将与.NET Conf 2024一同 ...
- 关于捣鼓Gentoo的一些见解
现在很少有人使用gentoo,大家对它的印象都是一个很难用的系统,我想给大家讲讲折腾Gentoo一年的心得,仅供参考 使用archlinux安装盘,genfstab生成fstab 使用gentoo-k ...
- 【测试平台开发】——01后端web开发框架Flask
官方中文地址:https://flask.net.cn/ 官方英文地址:https://flask.palletsprojects.com/en/2.1.x/ github地址:https://git ...
- 基于PaddleOCR + NLP实现证件识别
基于PaddleOCR + NLP实现证件识别 PaddleOCR识别 paddleOCR安装 安装 anconda虚拟环境(可参考yolov5的安装教程) paddleOCR识别 PaddleNLP ...
- JVM学习笔记之栈区
JVM学习笔记之栈区 本文主要内容: 栈是什么?栈帧又是什么?在JVM中,main方法调用say方法后,是怎么运行的?本文将详细讲解栈.希望大家学了之后,对栈有更深的了解. 心法:在JVM中,栈管运行 ...
- PlugIR:开源还不用微调,首尔大学提出即插即用的多轮对话图文检索 | ACL 2024
即插即用的PlugIR通过LLM提问者和用户之间的对话逐步改进文本查询以进行图像检索,然后利用LLM将对话转换为检索模型更易理解的格式(一句话).首先,通过重新构造对话形式上下文消除了在现有视觉对话数 ...
- DML—对表中的数据进行增删改
一.添加数据 1.给指定列添加数据 insert into 表名(列名1,列名2,...) values(值1,值2...); 执行给指定列添加数据前: -- 给指定列添加数据 insert into ...
- 开发板、windows、虚拟机互相ping通/ VMNET0、VMNET1、VMNET8释义
当前环境:板子通过网线连接windows 问题: 我当前的板子可以ping通windows,windows也能ping通ubuntu.但是板子却ping不通ubuntu. 原因: ubuntu通过NA ...
- dfs 验证搜索二叉树——leetcode98
代码来自leetcode官方 一开始我自己写这个代码时只注意当前节点是否会存在空指针,并没有注意到他的孩子节点也有可能为空,绕了我好久...... /** * Definition for a bin ...