项目六 动态网页数据预处理
pandas 的 Series/DataFrame、缺失值处理、分组统计,以及 Pig 的批量处理写法。
本项目学习目标
- 能读写 CSV/Excel,查看与切选数据
- 能处理缺失值、重复值、异常值
- 能做分组聚合与描述统计
- 能用 Pig Latin 完成简单的批处理
本项目任务导览
动态网页数据预处理
使用 Pandas 实现新闻动态网页数据预处理、使用 Pig 实现浪潮云说网页数据预处理、使用 ELK 实现某官网日志数据预处理。
- 项目导言与学习目标
- 任务 6-1 使用 Pandas 实现新闻动态网页数据预处理
- 任务 6-2 使用 Pig 实现浪潮云说网页数据预处理
- 任务 6-3 使用 ELK 实现某官网日志数据预处理
- 知识拓展与实例案例(3 例)
原始数据往往"脏、乱、差",预处理是数据分析的前置保障。
数据预处理是指将数据的缺失值、脏数据、数据格式等进行调整处理。由于数据采集过程中会因为数据的来源不统一造成数据格式的混乱,当使用这些原始数据进行数据分析时无法为决策提供有效的帮助,对数据进行预处理能够有效解决这些问题。
了解什么是数据预处理; 熟悉数据预处理的方法; 掌握 Pandas、Pig 以及 ELK 进行数据预处理的方法; 精通 Pig 以及 ELK 环境搭建方法。
具备了解 Pandas 和 Pig 数据预处理的能力; 具备熟悉 Pandas 和 Pig 数据预处理机制的能力; 具备掌握 Pandas 和 Pig 数据预处理方法的能力; 具备掌握 ELK 数据预处理方法及流程的能力; 具备精通数据预处理的能力。
具备团队意识; 具备良好的解决问题的能力; 具备较强的学习能力。
任务 6-1 使用 Pandas 实现新闻动态网页数据预处理
目录:Pandas 简介及安装 → 数据结构 → 基本功能 → 汇总和描述统计 → 处理缺失数据。
一、Pandas 简介及安装
Pandas 是 Python 的核心开源数据分析支持库。Pandas 是基于 NumPy 开发用于完成数据分析开发的数据分析工具,并且纳入了大量的库和标准数据模型,为实现高效的大型数据集操作提供支持。
二、Pandas 数据结构
三、Pandas 基本功能
该方法用于从 CSV 文件中读取数据,其必要参数为数据文件的存储路径,同时还可在读取文件时设置分隔符、编码、进行空值定义等操作。
pd.read_csv(filepath_or_buffer, sep=',', header='infer', names=None, index_col=None,
prefix=None, dtype=None, encoding=None, converters=None,
skipinitialspace=False, na_values=None, na_filter=True,
true_values=None, false_values=None)| 参数 | 描述 |
|---|---|
| filepath_or_buffer | 文件路径 |
| sep | 分隔符设置,默认值为',' |
| header | 数据文件中用于表示列名部分的行数(数据开始的行),默认为 0 |
| names | 用于为结果添加列名 |
| index_col | 指定索引列 |
| prefix | 自动生成的列名编号的前缀 |
| dtype | 指定列的数据类型 |
| encoding | 指定编码 |
| converters | 设置指定列的处理函数,可以用"序号"、"列名"进行列的指定 |
| skipinitialspace | 忽略分割符后面的空格 |
| na_values | 空值定义 |
| na_filter | 检测空值,值为 False 时可以提供大文件的读取性能 |
| true_values | 将指定文本转换为 true |
| false_values | 将指定文本转换为 false |
该方法主要用于从 Excel 文件中加载数据并以二维数据表的格式输出。
pd.read_excel(io, sheet_name=0, header=0, names=None, index_col=None, usecols=None,
squeeze=False, dtype=None, true_values=None, false_values=None,
skiprows=None, nrows=None)| 参数 | 描述 |
|---|---|
| io | 文件路径 |
| sheet_name | 指定表单名称 |
| header | 设置数据中为表头的行,默认为 0 |
| names | 自定义表头的名称,值为数组类型 |
| index_col | 指定作为索引的列 |
| usecols | 设置要获取的列的范围。值为 str,则表示 Excel 列字母和列范围的逗号分隔列表;为 int,则表示解析到第几列;为 int 列表,则表示解析列表中指定的列 |
| squeeze | 默认为 False。设置 squeeze=True 时表示如果解析的数据只包含一列,则返回一个 Series |
| dtype | 指定列的数据类型,默认为 None 不改变数据类型 |
| true_values | 将指定的文本转换为 True,默认为 None |
| false_values | 将指定的文本转换为 False,默认为 None |
| skiprows | 省略指定行数的数据 |
| nrows | 指定需要读取前多少行,通常用于较大的数据文件中 |
该方法主要用于从 SQL 数据库表获取数据,该方法需要创建与数据库的链接,通过 SQL 语句从表中获取数据。
pandas.read_sql(sql, con, index_col=None, coerce_float=True, parse_dates=None,
columns=None, chunksize=None)| 参数 | 描述 |
|---|---|
| sql | 用于查询数据的 sql 语句,类型为 str |
| con | 连接数据所需的引擎,使用对应的数据库链接库创建 |
| index_col | 选择某一列作为 index |
| coerce_float | 将数字形字符串转为 float 读入 |
| parse_dates | 将某一列日期型字符串转换为 datetime 型数据 |
| columns | 要选取的列 |
| chunksize | 指定输出的行数 |
该方法用于加载 JSON 文件中的数据,与 read_csv() 和 read_excel() 使用方法一致。
pd.read_json(path_or_buf=None, orient=None, typ='frame', dtype=True,
keep_default_dates=True, numpy=False, date_unit=None,
encoding=None, lines=False)| 参数 | 描述 |
|---|---|
| path_or_buf | 文件路径 |
| orient | 指示预期的 JSON 字符串格式 |
| typ | 要恢复的对象类型 |
| dtype | 指定数据类型,值为 json、dict |
| keep_default_dates | 是否保留默认日期处理 |
| numpy | 直接解码为 numpy 数组 |
| date_unit | 用于检测转换日期的时间戳单位 |
| encoding | 指定编码 |
| lines | 按行读取文件作为 json 对象 |
Pandas 中提供了若干用于检查数据信息的方法,如维度、基本信息、空值、列名等相关信息,能够帮助我们快速了解数据的基本信息,主要应用在数据量较大无法快速获取有效信息的情况。
| 属性和方法 | 描述 |
|---|---|
| DataFrame.shape() | 查看数据的维度 |
| DataFrame.dtypes() | 每列数据的格式 |
| DataFrame.values() | 查看数据表的值 |
| DataFrame.columns() | 查看数据列名称 |
| DataFrame.info() | 查看数据表基本信息 |
| DataFrame.isnull() | 查看空值 |
| DataFrame.unique() | 查看某一列的唯一值 |
| DataFrame.head() | 查看前指定行数据,默认为 10 |
| DataFrame.tail() | 查看后指定行数据,默认为 10 |
该方法用于将 Pandas 程序中的数据持久化保存到 csv 文件中。
DataFrame.to_csv(path_or_buf=None, sep=',', na_rep='', float_format=None,
columns=None, header=True, index=True, index_label=None,
mode='w', encoding=None)| 参数 | 描述 |
|---|---|
| path_or_buf | 字符串类型的文件路径对象 |
| sep | 输出文件的字段分隔符 |
| na_rep | 缺失数据填充 |
| float_format | 小数点保留几位,参数类型为字符串 |
| columns | 自定义列名,参数类型为序列或数组 |
| header | 写出列名,若给定字符串列表,则作为列名的别名 |
| index | 写入索引,默认为 true |
| mode | Python 写入模式,默认为"w"。w: 覆盖写入;a: 追加写入;r+: 可读可写,必须存在;w+: 可读可写,可以不存在,必会擦掉原有内容从头写;a+: 可读可写,可以不存在,必不能修改原有内容,只能在结尾追加写 |
| encoding | 表示输出文件中使用的编码的字符串,默认为"utf-8" |
该方法用于将 DataFrame 数据以 Excel 表格的形式保存到本地文件系统。
DataFrame.to_excel(excel_writer, sheet_name='Sheet1', na_rep='',
float_format=None, columns=None, header=True, index=True,
startrow=0, startcol=0)| 参数 | 描述 |
|---|---|
| excel_writer | 保存到的文件路径 |
| sheet_name | 保存的 sheet 名 |
| na_rep | 缺失数据表示方式,默认为空 |
| float_format | 格式化浮点数的字符串,默认为 None |
| startrow | 保存的数据在目标文件的开始行 |
| startcol | 保存的数据在目标文件开始的列 |
| header | 显示列名 |
| columns | 自定义列名 |
| index | 是否显示索引 |
在使用 Pandas 处理 Json 类型的数据时通常会将 Json 数据加载到程序中转换为 DataFrame(可使用 read_json),在处理完成后需要将处理后的数据保存回 Json,这时就需要用到 to_json() 方法。
DataFrame.to_json(path_or_buf=None, orient=None, date_format=None,
double_precision=10, force_ascii=True, date_unit='ms',
default_handler=None, lines=False, compression=None, index=True)| 参数 | 描述 |
|---|---|
| path_or_buf | 指定文件保存路径 |
| orient | 指定为将要输出的 JSON 格式 |
| date_format | 日期转换类型 |
| double_precision | 对浮点值进行编码时使用的小数位数,默认为 10 位 |
| force_ascii | 强制编码为 ASCII |
| index | 是否包含索引值 |
to_sql() 是 Pandas 中提供的用于将 DataFrame 数据保存到数据库的 API。
DataFrame.to_sql(name, con, schema=None, if_exists='fail', index=True,
index_label=None, chunksize=None)| 参数 | 描述 |
|---|---|
| name | 表名称 |
| con | 连接 sql 数据库的 engine,可以用 pymysql 之类的包建立 |
| schema | 相应数据库的引擎,不设置则使用数据库的默认引擎,如 mysql 中的 innodb 引擎 |
| index | 是否将表中索引保存到数据库 |
| index_label | 是否使用索引名称 |
| if_exists | 当数据库表存在时,设置数据的保存方式 |
| chunksize | 批量保存数据量大小 |
四、汇总和描述统计
Pandas 提供了一组常用的汇总和描述统计方法,用于数据分析中完成汇总统计的功能。与对应的 NumPy 数组方法相比,它们都是基于没有缺失数据的假设而构建的。
| 函数 | 描述 |
|---|---|
| df.sum() | 求和函数 |
| df.mean() | 求平均值 |
| df.min() / df.max() | 求最小值和最大值。对于字符串类型的,最小值返回按字母升序;当不忽略 null 值时,最小值最大值都是 NaN |
| df.var() | 求样本值的方差 |
| df.std() | 求样本值的标准差 |
| df.count() | 计算非 null 值的数量 |
| df.median() | 计算中位数 |
五、处理缺失数据
缺失值是指数据中由于某些信息的缺失,造成现有数据中某个或某些属性不完整。Pandas 中提供了若干对缺失值处理的方法,可分为四类:缺失值判断、缺失值统计、缺失值填充、缺失值删除。
df.isna()df.isna().sum(axis=None)df.fillna(value=None, method=None, axis=None,
inplace=False, limit=None, downcast=None)df.dropna(axis=None)任务 6-2 使用 Pig 实现浪潮云说网页数据预处理
Pig 是基于 Hadoop 的大规模数据分析平台,用 Pig Latin 语言以数据流方式处理数据。
一、Pig 简介
Pig 是一款基于 Hadoop 的大规模数据分析平台,是 Apache 平台下的免费开源项目,是 MapReduce 的一个抽象。它是一个工具/平台,用于分析较大数据集,并表示为数据流。Pig 通常与 Hadoop 一起使用。
二、Pig 配置运行
# 配置环境变量 ~/.bashrc
[root@master local]# vim ~/.bashrc
export PIG_HOME=/usr/local/pig
export PATH=$PATH:$PIG_HOME/bin
export PIG_CLASSPATH=$HADOOP_HOME/etc/hadoop
[root@master local]# source ~/.bashrc
[root@master local]# pig -version三、Pig Latin 执行
Apache Pig 提供了本地模式和 MapReduce 模式两种运行模式。在 Local 模式下,所有文件都从本地主机和文件系统中安装和运行,不需要使用 Hadoop 或 HDFS,此模式多用于测试。MapReduce 模式是使用 Apache Pig 加载或处理 Hadoop 的分布式文件系统(HDFS)中存储的数据。
四、运算符
比较运算符用于对符号两边的值进行比较,返回值有两种情况即 True 或 False。
| 运算符 | 描述 |
|---|---|
| == | 等于,检查两个数的值是否相等;如果是,则条件为 true |
| != | 不等于,检查两个数的值是否相等。如果值不相等,则条件为 true |
| > | 大于,检查左边数的值是否大于右边数的值,如果是,则条件变为 true |
| < | 小于,检查左边数的值是否小于右边数的值,如果是,则条件变为 true |
| >= | 大于或等于,检查左边数的值是否大于或等于右边数的值,如果是,则条件变为 true |
| <= | 小于或等于,检查左边数的值是否小于或等于右边数的值,如果是,则条件变为 true |
| matches | 模式匹配,检查左侧的字符串是否与右侧的常量匹配 |
Pig Latin 的类型结构运算符主要有三个:元组构建运算符、包构造函数运算符和映射构造函数运算符。
| 运算符 | 描述 | 示例 |
|---|---|---|
| () | 元组构造函数运算符 - 此运算符用于构建元组 | (Raju, 30) |
| {} | 包构造函数运算符 - 此运算符用于构造包 | {(Raju,30),(Mohammad,45)} |
| [] | 映射构造函数运算符 - 此运算符用于构造一个映射 | [name#Raja, age#30] |
LOAD 加载数据:LOAD 运算符由两部分构成,使用等号(=)分割,等号左侧需要指定存储数据的关系的名称,右侧需要定义存储数据的方式。
Relation_name = LOAD 'Input file path' USING function as schema;| 参数 | 说明 |
|---|---|
| relation_name | 设置数据保存目标关系名称 |
| Input file path | 数据文件在本地或 HDFS 的存储路径 |
| function | 设置加载数据的文件类型函数 |
| Schema | 数据模式,加载数据时必须指定数据模式(列名) |
STORE 存储数据:数据处理场景中,数据的体量通常会超过数十万条,仅靠程序的标准输出不能满足阅读条件,并且若要对处理后的数据进一步应用还要将其进行持久化存储。
STORE Relation_name INTO 'required_directory_path' [USING function];| 参数 | 说明 |
|---|---|
| Relation_name | 关系名 |
| required_directory_path | 关系目标存储路径 |
| USING function | 加载函数 |
| 运算 | 说明 | 示例 |
|---|---|---|
| Dump | 用于运行 Pig Latin 语句,并将结果打印到屏幕显示,此方法通常用于测试 | Dump student; |
| Describe | 用于查看关系的模式 | describe student; |
| explain | 用于显示关系的逻辑、物理和 MapReduce 执行计划 | explain student; |
| illustrate | 能够输出各语句逐步执行的结果 | illustrate student; |
分组操作在 SQL 中使用频率很高,Pig Latin 中同样提供了对数据进行分组方法,Group 运算符能够对一个或多个关系中的数据进行分组。
# 对单个关系分组
Group_data = GROUP Relation_name BY Group_key;
# 对多个关系分组
Group_data = GROUP Relation_name1 BY Group_key, Relation_name2 BY Group_key;| 参数 | 说明 |
|---|---|
| Relation_name | 关系名 |
| Group_key | 分组 key |
连接运算操作类似 SQL 中的关联查询。在执行一个数据处理任务时,通常数据文件会保存在多个数据集中,这时就需要使用连接操作;或两个数据集中存在一定的联系,需要联合处理。Pig Latin 中的连接运算需要从每个关系中声明一个或一组元组作为 key,当这些 key 匹配时,两个特定的元组匹配,否则记录将被丢弃。连接可以是以下类型:自连接、内部连接和外连接。
# 自连接
Relation_name = JOIN Relation1_name BY key, Relation2_name BY key;
# 内部连接
result = JOIN relation1 BY columnname, relation2 BY columnname;
# 左外连接
outer_left = JOIN relation1 BY columnname LEFT, relation2 BY columnname;
# 右外连接
outer_right = JOIN relation1 BY columnname RIGHT, relation2 BY columnname;
# 全外连接
outer_full = JOIN relation1 BY columnname FULL OUTER, relation2 BY columnname;五、内置函数
Eval 函数能够对数据进行简单的统计运算,如平均值、最大值、最小值、求和等操作。
| 函数 | 描述 |
|---|---|
| AVG() | 计算平均值 |
| BagToString() | 将包的元素连接成字符串。在连接时,可以在这些值之间放置分隔符(可选) |
| CONCAT() | 连接两个或多个相同类型的表达式 |
| COUNT() | 统计元素数量 |
| MAX() | 计算最大值 |
| MIN() | 计算最小值 |
| SIZE() | 基于任何 Pig 数据类型计算元素的数量 |
| SUM() | 要获取单列包中某列的数值总和 |
字符串函数主要用于对数据中字符类型的数据进行处理,如大小写转换、截取字符、字符比较等。
| 函数 | 描述 |
|---|---|
| ENDSWITH(string, testAgainst) | 验证字符串是否以特定字符结尾 |
| STARTSWITH(string, substring) | 验证第一个字符串是否以第二个字符串开头 |
| SUBSTRING(string, startIndex, stopIndex) | 返回来自给定字符串的子字符串 |
| EqualsIgnoreCase(string1, string2) | 比较两个字符串,忽略大小写 |
| INDEXOF(string, 'character', startIndex) | 返回字符串中指定的第一个出现的字符 |
| LAST_INDEX_OF(expression) | 返回字符串中指定的最后一个出现的字符 |
| LCFIRST(expression) | 将字符串中的第一个字符转换为小写 |
| UCFIRST(expression) | 将字符串中的第一个字符转换为大写 |
| UPPER(expression) | 将字符串中的所有字符转换为大写 |
| LOWER(expression) | 将字符串中的所有字符转换为小写 |
| REPLACE(string, oldChar, newChar) | 使用新字符替换字符串中的现有字符 |
| STRSPLIT(string, regex, limit) | 通过给定分隔符拆分字符串 |
| TRIM(expression) | 去掉字符串头尾空格 |
| LTRIM(expression) | 去掉字符串开头空格 |
| RTRIM(expression) | 去掉字符串尾部空格 |
日期函数用于对日期类型的数据进行处理,如获取时间中的年、月、日、时、分、秒等内容。
| 重载方式 | 描述 |
|---|---|
| ToDate(milliseconds) | 接收毫秒时间,转换为日期时间对象 |
| ToDate(iosstring) | 接收字符串类型的时间,并转换为日期时间对象 |
| ToDate(userstring, format) | userstring 代表用户输入的时间字符串,format 用于指定用户输入的日期时间的格式,如 ToDate('1990/12/19 03:11:44', 'yyyy/MM/dd HH:mm:ss'),结果返回 1990-12-19T03:11:44.000+05:30 |
| ToDate(userstring, format, timezone) | 该方式较上一种可多设置一个时区 |
| 函数 | 描述 |
|---|---|
| ToDate(datetime) | 根据给定的参数返回日期时间对象 |
| GetDay(datetime) | 返回时间对象中的某一天 |
| GetHour(datetime) | 返回时间对象中的小时 |
| GetMilliSecond(datetime) | 返回时间对象中的毫秒 |
| GetMinute(datetime) | 从日期时间对象返回一小时中的分钟 |
| GetMonth(datetime) | 返回时间对象中的月份 |
| GetSecond(datetime) | 从返回时间对象中的秒 |
| GetWeek(datetime) | 从日期时间对象返回一年中的周 |
| GetYear(datetime) | 从日期时间对象返回年份 |
| DaysBetween(enddatetime, startdatetime) | 返回两个日期时间对象之间的天数 |
| HoursBetween(enddatetime, startdatetime) | 返回两个日期时间对象之间的小时数 |
| MilliSecondsBetween(datetime1, datetime2) | 返回两个日期时间对象之间的毫秒数 |
| MinutesBetween(datetime1, datetime2) | 返回两个日期时间对象之间的分钟数 |
| MonthsBetween(datetime1, datetime2) | 返回两个日期时间对象之间的月数 |
| SecondsBetween(datetime1, datetime2) | 返回两个日期时间对象之间的秒数 |
| WeeksBetween(datetime1, datetime2) | 返回两个日期时间对象之间的周数 |
| YearsBetween(datetime1, datetime2) | 返回两个日期时间对象之间的年数 |
| 函数 | 描述 |
|---|---|
| ABS(expression) | 获取表达式的绝对值 |
| ACOS(expression) | 获得表达式的反余弦值 |
| ASIN(expression) | 获取表达式的反正弦值 |
| ATAN(expression) | 此函数用于获取表达式的反正切值 |
| CBRT(expression) | 此函数用于获取表达式的立方根 |
| CEIL(expression) | 此函数用于获取向上舍入到最接近的整数的表达式的值(近 1 取整) |
| COS(expression) | 此函数用于获取表达式的三角余弦值 |
| COSH(expression) | 此函数用于获取表达式的双曲余弦值 |
| EXP(expression) | 此函数用于获得欧拉数 e 乘以 x 的幂,即指数 |
| FLOOR(expression) | 要获得向下取整为最接近整数的表达式的值(四舍五入取整) |
| LOG(expression) | 获得表达式的自然对数(基于 e) |
| LOG10(expression) | 得到表达式的基于 10 的对数 |
| RANDOM() | 获得大于或等于 0.0 且小于 1.0 的伪随机数(double 类型) |
| ROUND(expression) | 要将表达式的值四舍五入为整数(如果结果类型为 float)或四舍五入为长整型(如果结果类型为 double) |
| SIN(expression) | 获得表达式的正弦值 |
| SINH(expression) | 获得表达式的双曲正弦值 |
| SQRT(expression) | 获得表达式的正平方根 |
| TAN(expression) | 获得角度的三角正切 |
| TANH(expression) | 获得表达式的双曲正切 |
任务 6-3 使用 ELK 实现某官网日志数据预处理
ELK = Elasticsearch + Logstash + Kibana,是日志数据采集、处理与可视化的经典技术栈。
一、Elasticsearch
Elasticsearch 是一个分布式可扩展的实时搜索和分析引擎,使用 Java 语言开发,由 Elastic 公司创建并开源维护的,并且作为 Apache 的开源项目,在云计算方面能够提供稳定、可靠、快速的实时搜索服务。Elasticsearch 支持多种语言的编程接口,比如 Java、.NET(C#)、PHP、Python、Apache Groovy 等。
- 将安装包上传到 Linux 系统中的 /usr/local 目录下,为 Elasticsearch 创建安装用户名为"es";
- 在 root 用户下解压 elasticsearch 安装包,为 es 用户设置对 elasticsearch 的权限;
- 进入 elasticsearch-6.1.0 目录修改 elasticsearch.yml,使任何主机都能够访问 elasticsearch;
- 将用户的软硬限制进行调整,打开"/etc/security/limits.conf"添加配置;
- 调整虚拟内存大小,将虚拟内存调整至 262144;
- 切换到"es"用户,启动 elasticsearch。
二、Logstash
Logstash 是一款开源的数据收集引擎,其中内置了约 200 个插件,可接受各种类型的数据(日志、网络请求、关系型数据库、传感器或物联网等)。Logstash 由输入、过滤器和输出三大类插件组成:
Logstash 配置文件结构如下:
input { # 输入组件配置
}
filter { # 过滤组件配置
}
output { # 输出组件配置
}使用 Logstash 进行数据收集时需要手动创建扩展名为".conf"的配置文件,并输入三个组件的配置即可,然后使用 Logstash 命令启动数据收集:
logstash -f ./logstash.confLogstash 中提供了数十种过滤插件,并且在 Logstash 中过滤插件是功能最强大、配置最为复杂的插件。过滤插件能够根据要求对数据在采集过程中进行初步的筛选或格式化操作。
grok 过滤器能够将非结构化日志数据解析为结构化数据。 %{SYNTAX:SEMANTIC}
geoip 能够根据免费的 IP 地址提供对应的地域信息,其中包括国家、省市和经纬度等,用于绘制可视化地图,主要应用在根据地域统计访问流量的场景。
Logstash 提供了数十种输出配置插件,能够适应不同的应用场景和业务需求,常用的就是标准输出 stdout 和 Elasticsearch 两类。其中 stdout 在前面示例已经应用过,这里使用 Logstash 采集数据输出到 Elasticsearch。
| 参数 | 描述 |
|---|---|
| hosts | 指定 Elasticsearch 的主机地址和端口 |
| index | 事件索引,默认值为 logstash-%{+YYYY.MM.dd} |
三、Kibana
Kibana 是一个开源的分析与可视化平台,配合 Elasticsearch 能够实现数据的检索、查看、交互存放以及数据的可视化,可通过丰富的图表功能直观地展示数据信息,达到数据分析的目的。Elasticsearch、Logstash 和 Kibana 个技术简称为 ELK。
四、任务实施(6 步)
- 在"/usr/local/inspur/"目录中创建名为 data 的文件夹;
- 在"/usr/local/inspur/code/flume-code"目录下编写 Flume 配置文件,采集 /usr/local/inspur/data 目录下名为 access_2021_05_01.log 的日志文件;
- 使用"es"用户启动 Elasticsearch 服务;
- 使用 Logstash 消费 Kafka 的数据并对其进行正则匹配,将结果输出到 Elasticsearch,设置 index 为"inspur-logdata-2022";
- 将日志文件上传到"/usr/local/inspur/data"目录下,查看 logstash 窗口输出内容;
- 使用浏览器访问 Kibana 页面。
知识拓展与实例案例
课堂讲解用:3 个可运行实例 + 知识拓展卡片。
知识拓展
实例 1:Pandas 新闻数据完整清洗实战
目标:对一份新闻采集结果执行"读取 → 检查 → 去重 → 填充 → 保存"的完整清洗流程。
# pandas_clean.py
import pandas as pd
# 1. 读取采集到的新闻数据
df = pd.read_csv("news_raw.csv")
# 2. 检查基本信息与缺失情况
print("维度:", df.shape)
print("列名:", list(df.columns))
print("缺失统计:\n", df.isna().sum())
# 3. 去重:按"标题"去重,保留第一条
df = df.drop_duplicates(subset=["标题"])
# 4. 填充:标题为空用"未知",阅读量为空用 0
df["标题"] = df["标题"].fillna("未知")
df["阅读量"] = df["阅读量"].fillna(0)
# 5. 类型转换:阅读量转为整数
df["阅读量"] = df["阅读量"].astype(int)
# 6. 保存清洗结果
df.to_csv("news_clean.csv", index=False, encoding="utf-8-sig")
print("清洗后剩余:", len(df), "条")维度: (120, 5)
列名: ['标题', '发布时间', '来源', '链接', '阅读量']
缺失统计:
标题 2
发布时间 0
来源 0
链接 0
阅读量 1
清洗后剩余: 112 条| 代码 | 白话解释 |
|---|---|
| import pandas as pd | 导入 pandas 并起别名 pd。pandas 是 Python 处理表格数据的王牌库,全课程都用 pd 这个缩写。 |
| df = pd.read_csv("news_raw.csv") | 读取 CSV 文件,转成"数据表"对象 DataFrame 存入 df。一行代码就把文件变成表格,非常方便。 |
| df.shape / df.isna().sum() | shape 返回表格的(行数,列数);isna() 判断每个单元格是否为空(空=True),sum() 把每列的空值数量加起来——快速掌握"哪里缺数据"。 |
| df = df.drop_duplicates(subset=["标题"]) | 按"标题"列去掉重复行、保留第一条。注意要重新赋值给 df,因为该方法默认返回新表、不原地修改。 |
| df["标题"] = df["标题"].fillna("未知") | 取"标题"这一列,把空值(NaN)填成"未知"两个字,避免后续处理报错。 |
| df["阅读量"] = df["阅读量"].astype(int) | astype(int) 把该列数据类型转成整数。转成整数后才能做求和、平均等数学运算。 |
| df.to_csv("news_clean.csv", index=False, encoding="utf-8-sig") | 把处理好的表保存成新文件。index=False 表示不保存行号;utf-8-sig 让 Excel 打开不乱码。 |
实例 2:Pandas 分组统计新闻来源
目标:对清洗后的新闻数据按"来源"分组,统计各来源的新闻数量与平均阅读量。
# pandas_groupby.py
import pandas as pd
df = pd.read_csv("news_clean.csv")
# 按"来源"分组,聚合新闻条数与平均阅读量
result = df.groupby("来源").agg(
条数=("标题", "count"),
平均阅读量=("阅读量", "mean")
).reset_index()
# 按条数降序排列
result = result.sort_values("条数", ascending=False)
print(result)
# 输出各来源占比
total = result["条数"].sum()
for _, row in result.iterrows():
print(f"{row['来源']}:{row['条数']} 条,占比 {row['条数']/total:.1%}") 来源 条数 平均阅读量
0 官方发布 45 1325.6
1 校园新闻 38 876.4
2 行业资讯 29 1102.3
官方发布:45 条,占比 40.2%
校园新闻:38 条,占比 33.9%
行业资讯:29 条,占比 25.9%| 代码 | 白话解释 |
|---|---|
| df = pd.read_csv("news_clean.csv") | 读取上一步清洗好的数据文件,得到 DataFrame 表 df。 |
| df.groupby("来源") | 按"来源"列分组:把同一来源的新闻归到一组。想象把一叠卡片按颜色分成几摞。 |
| .agg(条数=("标题", "count"), 平均阅读量=("阅读量", "mean")) | 对每组做统计:count 数一数每组有多少条(统计标题列的数量),mean 算一算每组平均阅读量。结果列名就叫"条数"和"平均阅读量"。 |
| .reset_index() | 把"来源"从索引变回普通列,表格更直观,方便后续保存为 CSV。 |
| result.sort_values("条数", ascending=False) | 按"条数"从大到小排序,最多的来源排在最上面。 |
| for _, row in result.iterrows(): | iterrows() 逐行取出结果表;_ 表示不需要的行号,row 是当前行数据。 |
| print(f"{row['来源']}:{row['条数']} 条,占比 {row['条数']/total:.1%}") | f-string 格式化输出:打印来源、条数和占比。{...:.1%} 表示把小数显示成百分比、保留 1 位小数。 |
实例 3:Logstash grok 解析一行真实日志
目标:用 grok 过滤器把一行非结构化日志解析为结构化字段,输出到 Elasticsearch。
# logstash.conf —— 解析 Nginx 访问日志
input {
kafka {
bootstrap_servers => "localhost:9092"
topics => ["nginx-log"]
codec => "json"
}
}
filter {
grok {
# 匹配:客户端IP 时间 "请求" 状态码 字节 来源
match => { "message" => "%{IP:client_ip} \[%{HTTPDATE:time}\] \"%{WORD:method} %{URIPATHPARAM:request}\" %{INT:status} %{INT:bytes} \"%{DATA:referer}\"" }
}
date {
match => ["time", "dd/MMM/yyyy:HH:mm:ss Z"]
target => "@timestamp"
}
geoip {
source => "client_ip"
}
}
output {
elasticsearch {
hosts => ["localhost:9200"]
index => "inspur-logdata-2022"
}
stdout { codec => rubydebug }
}
# 启动
[root@master logstash]# bin/logstash -f logstash.conf# 输入日志样例
192.168.1.10 [10/Feb/2022:10:15:30 +0800] "GET /index.html HTTP/1.1" 200 5120 "-"
# 解析后的结构化字段
client_ip : 192.168.1.10
method : GET
request : /index.html
status : 200
bytes : 5120
@timestamp: 2022-02-10T02:15:30.000Z| 配置项 | 白话解释 |
|---|---|
| input { kafka { ... } } | 数据入口:从 Kafka 的 nginx-log 主题读取日志消息。相当于"水龙头"打开,让日志流进来。 |
| filter { grok { match => { "message" => "..." } } } | grok 过滤器:按模式匹配日志文本。%{IP:client_ip} 表示"这里应是一个 IP,命名为 client_ip"。一行日志被拆成多个字段。 |
| %{HTTPDATE:time} | 匹配形如 [10/Feb/2022:10:15:30 +0800] 的时间字符串,命名为 time。 |
| %{INT:status} / %{INT:bytes} | 匹配整数(状态码、字节数)。INT 是预定义的"整数"模式。 |
| date { match => ["time", "dd/MMM/yyyy:HH:mm:ss Z"] } | date 过滤器:把 time 字符串按给定格式解析成标准时间,存入 @timestamp——Elasticsearch 里按时间检索就靠它。 |
| geoip { source => "client_ip" } | geoip 过滤器:根据 IP 自动补充地理位置字段(国家、城市、经纬度等)。 |
| output { elasticsearch { index => "inspur-logdata-2022" } } | 数据出口:把处理好的结构化日志写入 Elasticsearch,索引名(index)为 inspur-logdata-2022,可理解成"数据库里的表名"。 |
| bin/logstash -f logstash.conf | 用 -f 指定配置文件启动 Logstash,加载 input/filter/output 三段配置。 |