目录
1 实验目的
2 实验环境
3 实验数据
3.1 数据集整体构成
3.2 数据文件结构
3.3 日志文件命名规则
3.4 日志文件内部格式
3.5 字段含义必须掌握
3.6 数据特点
4 实验步骤
4.1 创建实验项目
4.2 日志数据结构化转换
4.2.1 数据资源获取
4.2.2 建立数据源连接
4.2.3 创建原始用户行为日志表
4.2.4 获取文件名:日志文件批量采集
4.2.5 Java 代码:日志解析与结构化转换
4.2.6 字段选择:有效字段筛选与规整
4.2.7 表输出:结构化数据表落地
4.2.8 执行转换流并查看结果
4.3 数据分析方向确定
4.3.1 创建进程统计表
4.3.2 统计进程用户规模
4.3.3 观察数据确定分析方向
4.4 分析方案设计与数据确定
4.5 数据清洗、聚合与关联加工
4.5.1 表输入:读取行为日志数据
4.5.2 字段选择:删除冗余字段
4.5.3 过滤记录:筛选进程为主要浏览器的数据
4.5.4 计算停留时长
4.5.5 字段选择:保留必要字段
4.5.6 过滤记录:筛选停留时长>0的数据
4.5.7 剪切字符串:提取日期
4.5.8 字段选择:设置日期格式
4.5.9 计算器:提取小时
4.5.10 生成用户-日-浏览器-小时明细
4.5.11 分支A:生成市场格局表
4.5.12 分支B:生成时段统计表
4.5.13 执行转换流
4.5.14 查看结果
实验总结
1 实验目的
熟悉数据集构成与半结构化日志数据特点,掌握文本日志解析、字段拆分的实操方法
完成数据规整,将零散原始日志转化为标准结构化数据表
实现多维度数据聚合、字段衍生与跨表关联,搭建适配分析场景的指标体系
完成机器学习特征工程处理,产出可直接使用的预测建模数据集
2 实验环境
实验平台:助睿在线实验平台 https://lab.guilian.cn/
数据处理:助睿 ETL 数据集成平台
数据规模:1000 用户,800 万 + 条行为记录,约 825MB
3 实验数据
本实验基于首届中国互联网数据挖掘竞赛公开数据集开展,是非常典型的计算机用户行为半结构化日志数据,专门用于用户行为分析、习惯挖掘、活跃度预测与用户画像研究。
3.1 数据集整体构成
数据集包含三大核心部分:
用户基本信息表:
demographic.csv存储用户 ID、性别、年龄、职业、教育程度、收入等人口属性信息。浏览器上网记录:日志中包含 URL、域名、访问时间等。
软件使用记录:日志中包含进程名、程序名、使用时长、窗口切换等。
3.2 数据文件结构
所有数据分为两部分:
behavior/文件夹:按日期归档,存放数万条 TXT 行为日志demographic.csv:用户属性表
两个数据通过用户 ID(user_id)唯一关联。
3.3 日志文件命名规则
每个 TXT 文件 =一个用户一次开机产生的行为日志文件名格式:用户ID_日期_开机时间.txt示例:0AB6BBBEDFF24EC8BAAC905F45AE314C_2012-05-07_21-22-38.txt
从文件名可直接解析出:
user_id:用户唯一标识
file_date:日志日期
file_start_time:开机时间
3.4 日志文件内部格式
每个日志文件固定分为三部分:第 1 行:Last<=> 数字表示日志最后一条记录距离开机的秒数。
第 2 行:L_Start<=> 时间表示本次开机的绝对时间。
第 3 行及以后:行为记录(核心数据)格式示例:T<=>177[=]P<=>360se.exe[=]I<=>5572[=]W<=>30378[=]V<=>4,1,6,6[=]N<=>360安全浏览器[=]C<=>360.cn
采用固定分隔符:
<=>:字段名与值分隔[=]:字段与字段之间分隔
3.5 字段含义必须掌握
字段T:距离开机的秒数(行为发生时间)
字段P:进程名(如:360se.exe、QQ.exe)
字段I:进程 IDU浏览器访问
字段URLW:非浏览器窗口句柄
字段V:程序版本号N程序名称(仅第一次出现)
字段C:开发公司名称(仅第一次出现)
字段A/B:浏览器窗口句柄
3.6 数据特点
属于半结构化数据,无固定行列,不能直接分析
数据量大、文件分散、格式统一、规则明确
4 实验步骤
4.1 创建实验项目
点击“新建项目”,输入项目名称“互联网用户行为日志数据加工”,点击“确定”。创建成功后即可在数据集成页面看到新创建的项目。
4.2 日志数据结构化转换
4.2.1 数据资源获取
注意:由于本次实验的数据量过大,我们仅使用部分XT数据来学习如何将半结构化数据转换为结构化数据,为方便后续的数据使用,我们可以将原始数据导入我们自己的文件目录下。
项目创建成功后打开项目
首先获取本次的实验数据集:点击“文件库”,右键根目录,点击“新建目录”;输入目录名称为“互联网用户行为日志数据集”,点击“确定”
接下来我们将公共空间的数据资源导入到这个目录下,点击公共空间,再点击“数据资源”
点击属于“互联网用户行为日志数据集”下的数据卡片右上角的“更多”,并点击“导出”。在弹出的窗口中选择导出到刚刚新创建的目录下,点击“确定”
可以看到在互联网用户行为日志数据集的目录下,新增了数据文件
4.2.2 建立数据源连接
在之前的实验《学生用户画像-考勤主题标签构建》中,我们已经创建了团队私有数据库的连接,无需再建立数据源连接
4.2.3 创建原始用户行为日志表
新建转换工作流,并命名为“创建原始行为日志数据表”,在该工作流中拖拽“执行一个SQL脚本”组件,通过执行SQL脚本来创建一个标签表。整个转换流如下所示:
配置说明:在组件中填写SQL脚本,选择目标数据库连接“团队私有数据库”,确保脚本执行权限;
SQL脚本如下:
CREATE TABLE behavior_events ( id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '自增主键', session_id VARCHAR(255) COMMENT '会话唯一ID', user_id VARCHAR(100) COMMENT '用户ID', session_start_time VARCHAR(50) COMMENT '会话开始时间', event_seconds INT COMMENT '事件发生秒数', process_name VARCHAR(255) COMMENT '进程名称', process_id VARCHAR(100) COMMENT '进程ID', url TEXT COMMENT '访问网址', addr_handle VARCHAR(255) COMMENT '地址栏句柄', tab_handle VARCHAR(255) COMMENT '标签页句柄', browser_version VARCHAR(100) COMMENT '浏览器版本', window_handle VARCHAR(255) COMMENT '窗口句柄', app_name VARCHAR(255) COMMENT '程序名称', company_name VARCHAR(255) COMMENT '开发公司', source_file VARCHAR(255) COMMENT '原始日志文件名', create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '入库时间', INDEX idx_session_id (session_id), INDEX idx_user_id (user_id) ) COMMENT '用户行为事件明细表';完成后运行转换流,运行过程会定时刷新组件状态,并画布下面显示执行日志。
由于原始的数据是半结构化的数据,无法直接通过文件输入组件获取数据,所以需要换一种思路:
通过 “获取文件名” 组件批量读取并定位日志文件,再交由 “Java 代码” 组件完成半结构化日志的解析(含字段拆分),接着通过 “字段选择” 组件筛选并规整有效字段,最终输出为标准结构化数据表,实现原始文本日志到可分析数据的标准化转换。
4.2.4 获取文件名:日志文件批量采集
新建转换工作流,并命名为“行为日志数据转为结构化数据”,在该工作流中拖拽“获取文件名”组件
双击“获取文件名”组件,在配置窗口中,点击文件或目录后后的“浏览文件”按钮,在弹出的窗口中选择我们上面创建的目录“互联网用户行为日志数据集”,再点击“确定”。选择目录后,点击“增加”,选择的目录出现在下方的路径中,点击“确认”。
4.2.5 Java 代码:日志解析与结构化转换
根据实验数据说明,我们可以通过 java 代码来读取日志文件、解析文件名、提取用户与开机信息、跳过文件头部、按分隔符拆分半结构化行为记录,将原始 TXT 日志中的 T、P、I、U、V、W、N、C 等关键字段逐一解析提取,最终输出包含会话 ID、用户信息、行为详情的标准结构化数据,完成从半结构化数据到结构化数据的转换。
拖拽一个“Java 代码” 组件到画布中,并创建“获取文件名”组件到“Java 代码” 组件的连线,连接线类型选择“主输出步骤”
双击“Java 代码” 组件,输入以下代码:
// 全局变量定义 String pathField; String shortFilenameField; public boolean processRow() throws HopException { if (first) { pathField = "filename"; shortFilenameField = "short_filename"; first = false; } Object[] r = getRow(); if (r == null) { setOutputDone(); return false; } String path = get(Fields.In, pathField).getString(r); String short_filename = get(Fields.In, shortFilenameField).getString(r); String user_id = ""; String l_start = ""; if (short_filename != null) { String name = short_filename.replace(".txt", ""); String[] parts = name.split("_"); if (parts.length >= 3) { user_id = parts[0]; l_start = parts[1] + " " + parts[2].replace("-", ":"); } } String session_id = user_id + "_" + l_start; java.io.BufferedReader br = null; try { br = new java.io.BufferedReader(new java.io.FileReader(path)); String line = ""; // 跳过前两行(Last和L_Start) br.readLine(); br.readLine(); while ((line = br.readLine()) != null) { if (line.trim().isEmpty()) { continue; } // 解析键值对 String[] kvPairs = line.split("\\[=\\]"); String t = ""; String p = ""; String i = ""; String u = ""; String a = ""; String b = ""; String v = ""; String w = ""; String n = ""; String c = ""; for (String kv : kvPairs) { int sepIdx = kv.indexOf("<=>"); if (sepIdx == -1) { continue; } String key = kv.substring(0, sepIdx).trim(); String val = kv.substring(sepIdx + 3); if ("T".equals(key)) { t = val; } else if ("P".equals(key)) { p = val; } else if ("I".equals(key)) { i = val; } else if ("U".equals(key)) { u = val; } else if ("A".equals(key)) { a = val; } else if ("B".equals(key)) { b = val; } else if ("V".equals(key)) { v = val; } else if ("W".equals(key)) { w = val; } else if ("N".equals(key)) { n = val; } else if ("C".equals(key)) { c = val; } } // 创建输出行 Object[] outRow = createOutputRow(r, data.outputRowMeta.size()); get(Fields.Out, "session_id").setValue(outRow, session_id); get(Fields.Out, "user_id").setValue(outRow, user_id); get(Fields.Out, "l_start").setValue(outRow, l_start); get(Fields.Out, "t").setValue(outRow, t); get(Fields.Out, "p").setValue(outRow, p); get(Fields.Out, "i").setValue(outRow, i); get(Fields.Out, "u").setValue(outRow, u); get(Fields.Out, "a").setValue(outRow, a); get(Fields.Out, "b").setValue(outRow, b); get(Fields.Out, "v").setValue(outRow, v); get(Fields.Out, "w").setValue(outRow, w); get(Fields.Out, "n").setValue(outRow, n); get(Fields.Out, "c").setValue(outRow, c); get(Fields.Out, "source_file").setValue(outRow, short_filename); putRow(data.outputRowMeta, outRow); } } catch (Exception e) { logError(e.getMessage(), e); } finally { try { if (br != null) { br.close(); } } catch (Exception e) { // ignore } } return true; }在字段空白表格处右键点击“插入”,双击插入的行,字段名输入“session_id”,类型选择“String”。继续插入行,依次将java代码中输出的字段进行配置,参考如下:
字段名类型:
session_id、user_id、l_start、t、p、i、u、a、b、v、w、n、c、source_file 都是String类型
4.2.6 字段选择:有效字段筛选与规整
右键“java 代码”组件点击“预览输出字段”,可以看到有很多字段是我们不需要也不属于原始数据字段的,需要移除
拖拽“字段选择”组件到画布中,并创建“Java 代码”组件到“字段选择”组件的连线,连接线类型选择“主输出步骤”
双击“字段选择”组件,点击tab选项“移除”,并在字段名称下方空白处右键点击“获取字段”;选中上一步骤中的Java代码输出的字段后,右键点击“删除选中的行”,删掉我们不需要的字段
4.2.7 表输出:结构化数据表落地
接下来,我们将已经转换为结构化的数据输出到数据库中,以便后续使用。拖拽“表输出”组件到画布中,并创建“字段选择”组件到“表输出”组件的连线,连接线类型选择“主输出步骤”
双击“表输出”组件,选择“团队私有数据库”连接,勾选“裁剪表”和“指定数据库字段”,勾选后会激活“数据库字段”tab页,在数据库字段tab页,右键选择“获取字段”
我们在4.2.3小节中创建的表字段与流字段是不一样的,双击表字段,在下拉框中选择正确的表字段
4.2.8 执行转换流并查看结果
执行转换流,点击工具栏中的“执行”按钮。查看日志,工作流执行后会打开日志页面,定期刷新工作流日志数据。
查看数据库结果
打开“元数据”tab页,在“团队私有数据库”连接上右键选择“加载元数据”。然后进入数据探查页面,展开“团队私有数据库”
双击目标表“behavior_events”,在右侧页面选择“查询”tab标签
4.3 数据分析方向确定
得到 behavior_events 后,我们需要对 behavior_events 按进程名 process_name 统计使用人数,可以快速看出哪些程序覆盖的用户最广。
4.3.1 创建进程统计表
新建转换工作流,并命名为“创建进程统计表”,在该工作流中拖拽“执行一个SQL脚本”组件,通过执行SQL脚本来创建一个标签表。整个转换流如下所示:
配置说明:在组件中填写SQL脚本,选择目标数据库连接“团队私有数据库”,确保脚本执行权限;
SQL脚本如下:
-- 创建程序/软件统计表 CREATE TABLE program_stats ( program_name VARCHAR(255) NOT NULL, -- 程序/软件名称 user_count INT NOT NULL -- 使用用户数 );由于数据量较大,为了顺利运行转换流,我们点开“元数据”,双击“团队私有数据库”,勾选“使用结果流”
完成后运行转换流,运行过程会定时刷新组件状态,并画布下面显示执行日志。
4.3.2 统计进程用户规模
每个进程得用户规模即用户数量 = 每个进程名称得用户ID计数
新建转换流“统计进程用户规模”,拖拽“表输入”组件到画布中,数据库连接选择“团队私有数据库”,并获取 behavior_events 得所有SQL查询语句,包含了所有的日志数据
拖拽“字段选择”组件到画布中,并创建“表输入”组件到“字段选择”组件得连线,双击“字段选择”组件,点击tab选项“移除”,然后再字段名称下方空白处右键点击“获取字段”,需要在“移除”中选择其他字段。选中user_id、process_name 两个字段,右键点击“删除选中的行”
字段 process_name 可能存在空值,为避免后续操作错误,需要将空值替换为“未知”。拖拽“替换NULL值”组件到画布中,并创建“字段选择”组件到“替换NULL值”组件的连线,连接线类型选中“主输出步骤”
双击“替换NULL值”组件,勾选“选择字段”,在下方字段表格中插入一行,并输入:
字段:process_name
值替换为:未知
是否为空:否
分组聚合之前需要对数据进行排序,否则分组计算结果可能出错。拖拽“排序字段”组件到画布中,创建“替换NULL值”组件到“排序记录”组件的连线,连接线类型选中“主输出步骤”
双击“排序记录”组件,将数据按照“process_name”字段升序排序
接下来就可以对排序后的数据进行分组聚合统计了,拖拽“分组”组件到画布中,创建“排序记录”组件到“分组”组件的连线,双击“分组”组件,在分组字段空白处获取字段后,仅保留“process_name”
在聚合表格空白处右键点击“插入”。双击插入的空白行,名称输入“user_count”,subject选择“user_id”,类型选择“个数”,最后点击“确认”
分组聚合后的数据我们需要输出到4.3.1小节创建的统计表中,拖拽“表输出”组件,创建“分组”组件到“表输出”组件的连线。双击“表输出”组件,选择“团队私有数据库”连接,勾选“裁剪表”,这样表输出组件在插入数据前会清空原始表数据,避免重复插入
勾选“指定数据库字段”,建立工作流字段与数据库表字段的映射关系。勾选后会激活“数据库字段”tab页,在数据库字段tab页,右键选择“获取字段”,选择字段映射
最后执行转换流即可
4.3.3 观察数据确定分析方向
为了更好地观察数据,我们使用助睿BI来观察数据
点击实验平台左边菜单“助睿BI”,进入助睿BI首页
由于之前的实验已经创建了团队私有数据库的数据源连接,本次实验无需再创建数据源连接,可直接创建数据集,点击“数据集”菜单,在数据集页面点击“+” - “新建数据集”
数据集名称和备注信息都输入“进程用户数据统计”,点击“确认”
右上角数据源选择进程统计表 program_stats 所在的“商业数据分析” - “se_group_8”
将 program_stats 拖拽至画布中
可以看到 program_stats 的数据结果,为了方便观察,可以将字段备注修改为中文;修改完成后点击“保存”,保存并发布数据集
点击“工作表”,进入工作表页面后,点击“+” - “新建工作表”,数据集选择刚刚创建的数据集“进程用户数据统计”,图表类型选择“水平条图”
将字段“program_name”拖拽至Y轴,“user_count”拖拽至X轴,并将“user_count”按照降序排序
由此,我们可以看到,浏览器类进程(360se.exe、QQBrowser.exe)的用户数明显高于其他软件(如Maxthon.exe)。这表明浏览器是覆盖面最广的应用,样本充足;同时浏览器记录包含url,可进一步分析网站偏好。因此,确定浏览器为分析对象。
4.4 分析方案设计与数据确定
根据 4.3 节的统计结果,我们发现浏览器类进程的用户覆盖率远高于其他软件,且浏览器记录包含url字段,可以挖掘用户网站偏好。因此,我们将分析对象锁定为浏览器,并围绕以下业务问题展开分析:
浏览器市场格局:哪些浏览器用户最多、使用时长最长?
用户画像:不同浏览器的用户在年龄、职业上有何差异?
使用习惯:用户集中在什么时段使用浏览器?
竞争迁移:用户是否会从一款浏览器切换到另一款?
流失预测:哪些用户可能停止使用 iexplore.exe 浏览器?
个性化推荐:根据用户的网站访问历史,可以推荐哪些网站?
本次实验我们先完成前2个数据的加工,首先需要在团队私有数据库中先创建这2个数据表
创建两个转换流“创建浏览器的用户数总使用时长统计表”、“创建每个浏览器按小时统计活跃用户数统计表”,并且两个转换流都拖拽“执行一个SQL脚本”组件到画布中,分别输入以下SQL:
创建浏览器的用户数总使用时长统计表的“执行一个SQL脚本”组件配置如下:
SQL:
CREATE TABLE `browser_coverage` ( `browser_name` VARCHAR(50) NOT NULL COMMENT '浏览器进程名', `user_count` INT NOT NULL COMMENT '使用用户数(去重)', `total_duration_sec` BIGINT NOT NULL COMMENT '总使用时长(秒)' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='浏览器用户覆盖率与总时长';创建每个浏览器按小时统计活跃用户数统计表的“执行一个SQL脚本”组件配置如下:
SQL:
CREATE TABLE `browser_hourly` ( `browser_name` VARCHAR(50) NOT NULL COMMENT '浏览器进程名', `hour` TINYINT NOT NULL COMMENT '小时(0-23)', `active_user_count` INT NOT NULL COMMENT '活跃用户数', PRIMARY KEY (`browser_name`, `hour`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='浏览器按小时活跃用户数';最后分别执行两个转换流即可
4.5 数据清洗、聚合与关联加工
在4.1章节转换后得到明细结构化数据,单条记录仅反映单次电脑操作行为,无法直观体现用户整体使用习惯,因此开展清洗、聚合与关联加工,提炼核心统计指标,并结合用户基础属性信息,形成具备分析价值的整合数据集。
解析完成的behavior_events行为明细表,同时引入demographic.csv用户人口属性数据表,依靠用户唯一编号完成两份数据联动处理。
注:包含全部数据的behavior_events行为明细表已经存放在线上公共数据库中,可以直接使用
新建转换流“互联网用户行为日志数据清洗抽取”
4.5.1 表输入:读取行为日志数据
拖入“表输入”组件到画布中,连接线上公共数据源,获取 behavior_events 的所有SQL查询语句
4.5.2 字段选择:删除冗余字段
拖拽“字段选择”组件到画布中,创建“表输入”组件到“字段选择”组件的连线;双击“字段选择”组件,点击“移除”tab选项,在字段名称下方空白处右键点击“获取字段”
选中 session_id, user_id, session_start_time, process_name, url, event_seconds 后删除选中的行,保留下来的字段就是要移除的字段,点击“确认”
4.5.3 过滤记录:筛选进程为主要浏览器的数据
拖拽“过滤记录”组件到画布中,创建“字段选择”组件到“过滤记录”组件的连线,连接线类型选择“主输出步骤”,双击“过滤记录”组件,可以看到需要配置匹配和不匹配的结果的输出步骤。
因此,我们先将后续的步骤的组件拖进来,拖拽“排序记录”组件到画布中,创建“过滤记录”组件到“排序记录”组件的连线,连接线类型选择“True输出”;再拖一个“空操作 (什么也不做)”组件到画布中,创建“过滤记录”组件到“空操作 (什么也不做)”组件的连线,连接线类型选择“False输出”
再次双击“过滤记录”组件,发送匹配的结果给“排序记录”,发送不匹配的结果给“空操作 (什么也不做)”
接下来配置过滤条件,点击第一个“field”,选择“process_name”,表示过滤条件为process_name的值
在弹出的窗口中,类型选择“String”,值为“iexplore.exe;360chrome.exe;360se.exe;chrome.exe;sogouexplorer.exe;EXCEL.EXE;WINWORD.EXE;AlilM.exe;QQBrowser.exe”,表示process_name的值在其中的记录则为True,否则为False
4.5.4 计算停留时长
原始日志只记录了焦点切换的时刻,没有直接给出停留时长。但通过前后两条记录的event_seconds相减,就能算出用户在每个窗口上停留了多久。这个时长是后续聚合(总使用时长)的基础数据。
这一步骤需要用到3个组件:
排序记录:按
session_id和event_seconds升序排列,确保同一个会话内的行为按时间顺序处理分析查询:获取同一会话内下一行的
event_seconds值,存入新字段next_event_seconds计算器:计算
next_event_seconds - event_seconds得到停留时长duration_sec
首先,“排序记录”组件在上一步骤已经拖入了,双击“排序记录”组件,按session_id和event_seconds升序排列
拖拽“分析查询”组件到画布中,创建“排序记录”组件到“分析查询”组件的连线,双击“分析查询”组件,分组字段为“session_id”,新增加的字段“next_event_seconds”,要取值的字段为“event_seconds”,类型“前第N行”,N为“1”,获取同一会话内下一行的event_seconds值,存入新字段next_event_seconds
拖拽“计算器”组件到画布中,创建“分析查询”组件到“计算器”组件的连线,双击“计算器”组件,插入新字段行,新字段输入“duration_sec”,计算公式选择“A - B”,字段A选择“next_event_seconds”,字段B选择“event_seconds”,值类型为“Integer”
4.5.5 字段选择:保留必要字段
使用“字段选择”,只保留user_id,process_name,session_start_time,url和duration_sec
字段,移除其他字段
4.5.6 过滤记录:筛选停留时长>0的数据
使用“过滤记录”组件,过滤掉duration_sec <= 0的记录(最后一条记录没有下一条,时长无效,忽略)
4.5.7 剪切字符串:提取日期
后续很多分析需要按天、按时段聚合(比如每日使用时长、时段热力图)。提前提取好日期和小时,后续分组时直接使用,避免重复解析。
session_start_time的格式为:yyyy-MM-dd HH:mm:ss,通过剪切字符串组件可以直接获取yyyy-MM-dd
拖拽剪切字符串组件到画布中,创建过滤记录 1组件到拖拽剪切字符串组件的连线,连接线类型选择“Trur输出”,剪切字符串组件的配置如下:
4.5.8 字段选择:设置日期格式
目前获取的数据中,session_start_time的类型为String,为方便提前提取好小时,需要将session_start_time的类型设置为Date
拖拽字段选择组件到画布中,创建剪切字符串组件到字符选择组件的连线,连接线类型选择“主输出步骤”,字段选择2组件的配置如下:
4.5.9 计算器:提取小时
通过计算器组件,我们可以提取 yyyy-MM-dd HH:mm:ss 中的HH,拖拽计算器组件到画布中,创建字符选择组件到计算器组件的连线,连接线类型选择“主输出步骤”,计算器 1组件的配置如下:
4.5.10 生成用户-日-浏览器-小时明细
原始数据是每条窗口切换记录,粒度太细。我们真正关心的是“每个用户每天每浏览器每小时用了多久、启动了几次”。这一步将数据压缩到合适的粒度,同时为后续所有统计表提供统一的基础数据。
接下来我们就可以分组聚合组件来统计用户每天使用浏览器的时段数据了,但在分组聚合前,先使用排序记录组件进行排序,避免分组聚合结果出错
拖拽排序记录组件到画布中,创建“计算器 1”组件到“排序记录 1”组件的连线,排序记录 1组件的配置如下:
接下来,拖拽分组组件,创建“排序记录 1”组件到分组组件的连线,分组组件的配置如下:
以上步骤获取的数据已经是比较合适颗粒度的数据了,可以以此为基础,抽取不同维度的数据,以便用来实现后续的可视化分析
4.5.11 分支A:生成市场格局表
目标:统计每个浏览器的总用户数和总使用时长
这两个指标直接回答“哪种浏览器覆盖最广、用得最久”。去重计数能避免同一用户被重复计算,总时长反映真实使用强度。
拖拽分组组件到画布中,创建“分组”组件到“分组 1”组件的连线
“分组 1”组件只按process_name分组
聚合:
user_count= COUNT(user_id) (有多少不同用户使用过该浏览器)total_duration= SUM(total_duration_sec) (所有用户的累计使用时长)
分组聚合的结果需要落地数据库,拖拽“表输出”组件到画布中,创建“分组 1”组件到“表输出 组件的连线”
表输出组的配置如下:
4.5.12 分支B:生成时段统计表
目标:统计每个浏览器在每个小时的使用情况,用于分析用户的时间段偏好
通过这张表可以绘制柱状图或折线图,展示不同浏览器的使用高峰时段。例如,白天工作时间 Chrome 使用量高,晚上娱乐时段 360 浏览器更活跃。按小时聚合已经足够,不需要更细的粒度
此分支的分组字段包含浏览器、小时,即process_name、hour,而前一个排序记录只对process_name排序,所以在这里需要按照process_name、hour升序排序
拖拽“排序记录”组件到画布中,创建“分组”组件到“排序记录 2”组件的连线,数据传输模式选择复制发送
“排序记录 2”组件的配置如下:
拖拽分组组件到画布中,创建“排序记录 2”组件到“分组 2”组件的连线
“分组 2”组件按process_name、hour分组
聚合:active_user_count =user_id个数
分组聚合的结果需要落地数据库,拖拽“表输出”组件到画布中,创建“分组 2”组件到“表输出 1组件的连线”,表输出组的配置如下:
4.5.13 执行转换流
点击运行按钮
4.5.14 查看结果
点击“元数据”tab选项,右键团队私有数据,并点击“加载元数据”,接着点击“数据探查”,可以看到团队私有数据库目录
点击 browser_coverage、browser_hourly 两个数据表,查询数据情况是否符合预期
实验总结
本次实验我完成了浏览器用户行为日志的ETL清洗与统计分析,成功构建用户覆盖与小时活跃两张统计表。过程中遇到了过滤条件过严导致数据量不足、分组统计未正确去重、字段传递丢失等问题,通过排查过滤规则、修正聚合函数与分组字段顺序逐一解决。实验让我掌握了数据清洗、字段规整与分组聚合的核心操作,也深刻理解了原始数据质量对统计结果的决定性影响。助睿平台可视化流程搭建直观清晰,组件配置便捷,运行日志能快速定位问题,有效帮助我完成了从数据解析到统计分析的全流程实践。