基于助睿平台的浏览器用户行为分析与流失预测 —— 数据加工实验

一、实验背景与目的

在这次数据分析实训中,我需要处理一批典型的互联网用户行为日志数据。这些数据都是半结构化的 TXT 文本,不能直接拿来分析,所以我要完整走一遍数据加工流程:从日志解析、结构化转换,到数据清洗、字段衍生、多维度聚合,最终产出可以用来做用户行为分析、浏览器市场格局研究,甚至后续流失预测建模的标准数据集。通过这次实操,我也能真正掌握企业里常用的 ETL 数据处理思路和平台操作方法。

实验目的

  1. 熟悉半结构化用户行为日志的格式、字段与数据特点,掌握日志解析方法。
  2. 完成从零散 TXT 日志到标准结构化数据表的转换,实现数据规整与入库。
  3. 掌握数据清洗、字段衍生、分组聚合、多分支加工等 ETL 核心操作。
  4. 输出可直接用于可视化与建模的浏览器用户行为统计数据表。

二、实验环境与数据

2.1 实验环境

  • 实验平台:助睿在线实验平台
  • 数据处理:助睿 ETL 数据集成平台
  • 数据存储:团队私有数据库
  • 数据规模:1000 名用户、800 万 + 条行为记录、约 825MB(本次实操使用 20 个样本文件)

2.2 实验数据

  1. 用户基本信息demographic.csv,包含 user_id、性别、年龄、职业、教育、收入等。

  2. 行为日志behavior/目录下大量 TXT 文件,记录浏览器访问与软件使用行为。

  3. 日志命名规则用户ID_日期_开机时间.txt

  4. 日志内部格式 : 第 1 行:Last<=> 数字(最后一条记录距开机秒数) 第 2 行:L_Start<=> 时间(开机时间) 第 3 行起:行为记录,以[=]分隔字段,<=>分隔键值

2.3 核心字段

  • T:行为发生距开机秒数
  • P:进程名
  • I:进程 ID
  • U:访问 URL
  • W:窗口句柄
  • N:程序名
  • C:开发公司

三、详细实验步骤

步骤 1:创建实验项目

  1. 登录助睿平台,进入数据集成页面。
  2. 点击新建项目 ,输入名称:互联网用户行为日志数据加工,点击确定。
  3. 项目创建完成,进入项目内部进行资源管理。

步骤 2:导入实验数据

  1. 在项目内打开文件库 ,右键根目录→新建目录 ,命名为:互联网用户行为日志数据集

  2. 切换到公共空间数据资源 ,找到本次实验日志数据。

  3. 点击数据卡片更多→导出 ,选择目标目录为刚创建的文件夹。

  4. 重复操作,将 20 个日志 TXT 文件全部导入个人目录。

步骤 3:建立数据库连接与创建原始行为表

  1. 确认已配置团队私有数据库连接(未配置则按平台指引新建)。

  2. 新建转换:创建原始行为日志数据表

  3. 拖拽执行一个 SQL 脚本 组件,配置数据库连接。

  4. 执行建表 SQL,创建behavior_events表:

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 '用户行为事件明细表';
  1. 运行转换,完成建表。

步骤 4:日志结构化转换(半结构化→结构化)

新建转换:行为日志数据转为结构化数据

  1. 获取文件名

    • 拖拽获取文件名组件,双击配置。

    • 点击浏览文件 ,选择互联网用户行为日志数据集目录。

    • 点击增加→确认 ,批量读取所有 TXT 文件路径。

  2. 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 String
user_id String
l_start String
t String
p String
i String
u String
a String
b String
v String
w String
n String
c String
source_file String
  1. 字段选择(清理冗余)

    • 拖拽字段选择组件,连接 Java 代码输出。

    • 切换到移除 tab,右键获取字段

    • 删除 Java 代码输出的有效字段,保留冗余字段并移除。

    • 确认,只保留核心字段。

  2. 表输出(入库)

    • 拖拽表输出组件,连接字段选择。

    • 选择团队私有数据库 ,目标表:behavior_events

    • 勾选裁剪表指定数据库字段

    • 右键获取字段 ,手动匹配流字段与表字段。

    • 确认保存。

  3. 运行转换并验证

    • 点击工具栏执行,使用默认配置启动。

    • 查看执行日志,确认无报错。

    • 进入元数据 ,右键数据库加载元数据 ,打开behavior_events查询数据,验证结构化结果。


步骤 5:确定分析方向(统计进程用户规模)

5.1 创建进程统计表
  1. 新建转换:创建进程统计表

  2. 拖拽执行 SQL 脚本 ,执行建表语句:

sql

复制代码
CREATE TABLE program_stats (
    program_name VARCHAR(255) NOT NULL,
    user_count INT NOT NULL
);
  1. 运行转换完成建表。
5.2 统计各进程用户数

新建转换:统计进程用户规模

  1. 表输入 :读取behavior_events全量数据。

  2. 字段选择 :只保留user_idprocess_name,其余移除。统计每个进程得用户数量只需用到 user_id、process_name 两个字段,所以需要移除其他字段

    选中user_id、process_name 两个字段,右键点击"删除选中的行",删除后点击"确认"

  3. 替换 NULL 值 :将process_name空值替换为 "未知"。

  4. 排序记录 :按process_name升序排序。

  5. 分组:

    • 分组字段:process_name

    • 聚合:user_count = user_id 个数

  6. 表输出 :输出到program_stats,勾选裁剪表。

    勾选后会激活"数据库字段"tab页,在数据库字段tab页,右键选择"获取字段"

  7. 运行转换,完成统计。

5.3 BI 可视化确定分析对象
  1. 进入助睿 BI数据集新建数据集 ,命名:进程用户数据统计

  2. 右上角数据源选择进程统计表 program_stats 所在的"商业数据分析"-"se_group_19",

    选择program_stats表,将 program_stats 拖拽至画布中,将字段备注修改为中文,保存并发布。

  3. 新建工作表,命名为"进程用户数量分析"

  4. 用水平条图展示:Y 轴程序名,X 轴用户数,降序排列。

  5. 观察结果:浏览器类进程用户覆盖最广,确定以浏览器为核心分析对象。


步骤 6:创建分析目标表

新建两个转换,分别执行建表 SQL:

  1. 创建浏览器的用户数总使用时长统计表的"执行一个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='浏览器用户覆盖率与总时长';
  1. 创建每个浏览器按小时统计活跃用户数统计表的"执行一个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='浏览器按小时活跃用户数';




步骤 7:数据清洗、聚合与多分支加工(核心)

新建转换:互联网用户行为日志数据清洗抽取

  1. 表输入

    • 选择线上公共数据源 (全量 behavior_events)。

    • 输入 SQL 读取全量行为数据。

  2. 字段选择

    • 移除冗余字段,保留 :session_id、user_id、session_start_time、process_name、url、event_seconds。选中 session_id, user_id, session_start_time, process_name, url, event_seconds 后删除选中的行,保留下来的字段就是要移除的字段,点击"确认"

  3. 过滤记录(只保留主流浏览器)

    • 配置条件:process_name IN LIST

    • 列表值:iexplore.exe;360chrome.exe;360se.exe;chrome.exe;sogouexplorer.exe;QQBrowser.exe

    • 匹配输出到后续步骤,不匹配输出到空操作。

  4. 计算停留时长

    先对过滤记录的真假输出选择连线类型

    • 排序记录 :按session_idevent_seconds升序。

    • 分析查询分组字段为"session_id",新增加的字段"next_event_seconds",要取值的字段为"event_seconds",类型"前第N行",N为"1",获取同一会话内下一行的 event_seconds 值,存入新字段 next_event_seconds

    • 计算器duration_sec = next_event_seconds - event_seconds

      插入新字段行,新字段输入"duration_sec",计算公式选择"A - B",字段A选择"next_event_seconds",字段B选择"event_seconds",值类型为"Integer"

  5. 二次字段选择

    • 只保留:user_id、process_name、session_start_time、url、duration_sec。
  6. 过滤无效时长

    • 保留duration_sec > 0的记录,剔除异常与末尾无效数据。
  7. 提取日期与小时

    • 剪切字符串 :从session_start_time截取日期(yyyy-MM-dd)。

    • 字段选择 :将session_start_time转为 Date 类型。

    • 计算器 :提取小时(0-23),提取 yyyy-MM-dd HH:mm:ss 中的HH,生成hour字段。

  8. 生成用户 - 日 - 浏览器 - 小时明细

    • 排序记录 :按process_name排序。

    • 分组 :按 user_id、process_name、日期、hour 分组。

    • 聚合:总时长求和、访问次数统计。

  9. 分支 A:生成市场格局表 browser_coverage

  • 从上述明细分组 :只按process_name分组。

  • 聚合:

    • user_count:user_id 去重计数
    • total_duration_sec:时长求和
  • 表输出 :写入browser_coverage,勾选裁剪表。


  1. 分支 B:生成时段统计表 browser_hourly
  • 数据复制发送 ,按process_namehour排序。

  • 分组

  • process_namehour分组。

  • 聚合:active_user_count = user_id 个数。

  • 表输出 :写入browser_hourly


  1. 运行全转换流
  • 点击执行,等待完成。

  • 进入元数据→数据探查,分别查看browser_coveragebrowser_hourly数据是否正确。


四、实验结果与总结

实验结果

  1. 完成半结构化日志→结构化标准表 behavior_events
  2. 统计得到program_stats,确定浏览器为核心分析对象。
  3. 完成数据清洗、停留时长计算、日期 / 小时提取、多维度聚合。
  4. 输出两张核心表:
    • browser_coverage:各浏览器用户数与总使用时长。
    • browser_hourly:各浏览器每小时活跃用户数。

实验总结

  1. 掌握半结构化日志解析的完整流程,能独立完成 TXT 文本到结构化表的转换。
  2. 熟练使用助睿 ETL 核心组件:获取文件名、Java 代码、字段选择、过滤、排序、分组、表输出。
  3. 理解数据加工逻辑:先结构化→再探索→再清洗聚合→输出分析宽表
  4. 本次加工的数据可直接用于浏览器行为分析、用户画像、流失特征构建与可视化展示。
相关推荐
玄米乌龙茶1231 小时前
思维导图笔记:RAG检索增强生成
笔记
bllovepigpig1 小时前
A÷文章浅读笔记 【规模化托管智能体:将大脑与双手分离】
笔记
꧁꫞꯭零꯭点꯭꫞꧂1 小时前
LangChain 提示词模板与链式调用笔记
人工智能·笔记·langchain
问心无愧05131 小时前
ctf show web入门257
android·前端·笔记
songyuc2 小时前
Matplotlib&seaborn学习笔记
笔记·学习·matplotlib
Byron__2 小时前
JVM垃圾回收与调优核心面试笔记(引用计数/GC算法/CMS/G1/参数调优)
java·jvm·笔记·面试
唯情于酒2 小时前
IdentityServer4学习笔记
笔记·学习
快乐得小萝卜2 小时前
笔记:TREX工具-4
笔记
半导体守望者3 小时前
MKS Profibus-DP 接口等离子发生器Plasma Generators EIite
经验分享·笔记·机器人·自动化·制造