实验实训 / udi-studio / ETL / 数据加工 / 数据转换实验平台助睿在线实验平台https://lab.guilian.cn/助睿数智官网https://www.uniplore.com/一、实验背景本次实验围绕“浏览器市场与用户画像分析”展开核心任务是将原始的半结构化行为日志进行解析、清洗、规整和聚合最终加工成可用于分析的结构化数据表。原始数据来自互联网用户行为日志数据量较大、格式复杂单靠传统的文件导入方式无法直接分析因此需要借助助睿 ETL完成从日志到表结构数据的转换。通过本实验我们可以掌握以下能力解析半结构化日志文本将原始行为数据转换为结构化表按浏览器、小时、用户等维度进行聚合统计为后续的浏览器市场分析、用户画像分析打好数据基础。二、实验目的本实验的目标主要有三个熟悉数据集构成与半结构化日志数据特点掌握文本日志解析、字段拆分与结构化转换方法实现多维度数据清洗、聚合与关联加工构建适配分析场景的数据底座。三、实验环境本次实验使用的平台与数据环境如下项目内容实验平台助睿在线实验平台ETL工具助睿 ETL 数据集成平台数据分析平台助睿 BI数据规模1000 用户800 万 行行为记录约 825MB数据类型半结构化日志 用户属性表四、实验数据说明本实验基于首届中国互联网数据挖掘竞赛公开数据集包含典型的用户行为半结构化日志适合做用户行为分析、习惯挖掘、活跃度预测和用户画像研究。4.1 数据集整体构成数据主要包括三部分用户基本信息表demographic.csv存储用户 ID、性别、年龄、职业、教育程度、收入等人口属性信息。浏览器上网记录日志中包含 URL、域名、访问时间等。软件使用记录日志中包含进程名、程序名、使用时长、窗口切换等。其中demographic.csv存储用户 ID、性别、年龄、职业、教育程度、收入等人口属性信息浏览器记录包含 URL、访问时间等软件记录包含进程名、程序名、使用时长、窗口切换等信息。4.2 数据集时间范围数据覆盖 1000 名用户连续 4 周的电脑使用行为跨越 4 个月每月抽取 1 周数据第 1 周2012-05-07 至 2012-05-13第 2 周2012-06-04 至 2012-06-10第 3 周2012-07-02 至 2012-07-08第 4 周2012-08-06 至 2012-08-124.3 数据文件结构数据分为两部分behavior/文件夹按日期归档存放大量 TXT 行为日志demographic.csv用户属性表。两类数据通过user_id唯一关联。4.4 日志文件命名规则每个 TXT 文件代表某个用户一次开机产生的行为日志命名格式为用户ID_日期_开机时间.txt示例0AB6BBBEDFF24EC8BAAC905F45AE314C_2012-05-07_21-22-38.txt从文件名中可以解析出user_id用户唯一标识file_date日志日期file_start_time开机时间4.5 日志文件内部格式每个日志文件固定分为三部分第 1 行Last 数字表示日志最后一条记录距离开机的秒数第 2 行L_Start 时间表示本次开机的绝对时间第 3 行及以后行为记录。行为记录示例如下T177[]P360se.exe[]I5572[]W30378[]V4,1,6,6[]N360安全浏览器[]C360.cn其中分隔符规则如下字段名与值分隔[]字段与字段之间分隔4.6 字段含义字段含义T距离开机的秒数行为发生时间P进程名I进程 IDU浏览器访问 URLW非浏览器窗口句柄V程序版本号N程序名称仅第一次出现C开发公司名称仅第一次出现A/B浏览器窗口句柄4.7 数据特点本数据属于半结构化数据具有以下特点没有固定行列不能直接分析数据量大文件分散格式统一、规则明确适合通过 ETL 进行解析和加工。五、实验步骤5.1 创建实验项目首先进入助睿在线实验平台点击新建项目。输入项目名称互联网用户行为日志数据加工点击“确定”后项目创建完成。创建成功后即可在数据集成页面看到新建项目。5.2 日志数据结构化转换由于原始数据量较大本次实验仅使用其中 20 个 TXT 文件进行学习重点掌握半结构化日志转结构化数据的思路。5.2.1 数据资源获取项目创建完成后点击项目右上角“...”选择打开项目。进入项目页面后可以看到左侧有三个菜单资源库文件元数据其中资源库用于管理工作流文件库用于保存工作流中需要用到的文件元数据管理用于运行配置、数据库、集群等配置。首先在文件库中创建一个目录命名为互联网用户行为日志数据集然后进入公共空间找到实验数据资源逐个导出到刚刚创建的目录中。5.2.2 建立数据源连接如果之前已经创建过团队私有数据库连接则此步骤可以直接跳过如果没有需要先建立数据源连接。5.2.3 创建原始用户行为日志表新建转换工作流命名为创建原始行为日志数据表拖拽一个“执行一个 SQL 脚本”组件到画布中输入以下 SQLCREATE 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 用户行为事件明细表;运行转换流后原始表即可创建成功。5.2.4 获取文件名日志文件批量采集新建转换工作流命名为行为日志数据转为结构化数据拖拽“获取文件名”组件到画布中选择刚刚创建的目录互联网用户行为日志数据集点击“增加”“确认”后目录下的文件将被批量读取。5.2.5 Java 代码日志解析与结构化转换接下来拖入“Java 代码”组件并与“获取文件名”组件连线。这一环节的核心思路是读取日志文件路径从文件名中解析user_id和开机时间跳过前两行头信息逐行解析行为记录提取T、P、I、U、A、B、V、W、N、C等关键字段输出结构化记录。下面是核心 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_idStringuser_idStringl_startStringtStringpStringiStringuStringaStringbStringvStringwStringnStringcStringsource_fileString注意如果字段类型不小心变成 0需要重新配置正确类型否则转换流虽然能执行但数据可能无法正常落库。5.2.6 字段选择有效字段筛选与规整由于 Java 代码输出的字段很多部分属于系统自动带出的附加字段并不需要保留因此要通过“字段选择”组件进行筛选和规整。拖入“字段选择”组件并与 Java 代码连接。打开配置后切换到“移除”选项删除不需要的字段仅保留本实验必要字段。5.2.7 表输出结构化数据表落地拖入“表输出”组件并与“字段选择”组件连接。选择数据库连接团队私有数据库勾选裁剪表指定数据库字段然后在数据库字段中完成字段映射关系。执行转换流后即可将结构化行为日志写入数据库表behavior_events。5.3 数据分析方向确定得到behavior_events后下一步需要明确分析目标。本实验先对process_name进行统计观察不同进程的用户覆盖规模从而判断哪些浏览器最值得作为后续分析对象。这样做的价值在于可以从海量记录中快速筛选重点对象可以判断哪些程序覆盖用户最多为后续的浏览器市场分析提供依据。5.3.1 创建进程统计表新建转换工作流命名为创建进程统计表输入 SQLCREATE TABLE program_stats ( program_name VARCHAR(255) NOT NULL, user_count INT NOT NULL );运行后创建成功。5.3.2 统计进程用户规模新建转换流统计进程用户规模核心流程如下使用“表输入”读取behavior_events用“字段选择”仅保留user_id、process_name用“替换NULL值”将空进程名替换为“未知”用“排序记录”按process_name排序用“分组”统计每个进程对应的用户数用“表输出”落地到program_stats。其中“分组”组件设置如下分组字段process_name聚合字段user_count user_id 个数执行转换流后数据会写入统计表。5.3.3 观察数据确定分析方向接下来借助助睿 BI观察统计结果。进入助睿 BI 后新建数据集并加载program_stats。然后创建工作表选择图表类型为水平条图将program_name拖到 Y 轴user_count拖到 X 轴并按user_count降序排序。从图中可以看出浏览器类进程如chrome.exe、360chrome.exe、sogouexplorer.exe、QQBrowser.exe的用户数明显高于其他软件这说明浏览器覆盖面最广浏览器记录包含 URL便于进一步分析网站偏好因此后续分析对象确定为浏览器。5.4 分析方案设计与数据确定根据前面的统计结果可以将分析对象锁定为浏览器并围绕以下问题展开哪些浏览器用户最多、使用时长最长不同浏览器用户的年龄、职业有什么差异用户集中在哪些时段使用浏览器用户是否会从一款浏览器切换到另一款哪些用户可能停止使用某个浏览器能否根据历史访问行为做个性化推荐为了支撑这些分析后续需要预先构建一系列结构化输出表输出表名内容粒度browser_coverage.csv每个浏览器的用户数、总使用时长每个浏览器一行browser_hourly.csv每个浏览器按小时统计活跃用户数浏览器 × 小时browser_demographic.csv按年龄分段、职业的用户分布浏览器 × 年龄组 × 职业browser_retention.csv每个浏览器第3周到第4周留存率每个浏览器一行browser_migration.csv用户浏览器迁移关系与人数源浏览器 → 目标浏览器churn_features.csvChrome 行为特征及标签每个用户一行churn_probability.csv每个用户的流失概率每个用户一行feature_importance.csv特征重要性每个特征一行high_risk_users.csv高风险流失用户每个用户一行本次实验先完成前两个核心表的加工浏览器用户数 总使用时长统计表浏览器按小时活跃用户数统计表。5.5 数据清洗、聚合与关联加工这一部分是本次实验的重点。解析后的behavior_events单条记录只反映一次电脑操作行为无法直观体现整体使用习惯因此需要继续做清洗、聚合和关联加工。加工思路如下引入行为明细表behavior_events结合用户基础属性表demographic.csv通过用户唯一编号完成联动构建可用于浏览器市场分析的核心统计表。5.5.1 表输入读取行为日志数据拖入“表输入”组件连接线上公共数据源读取behavior_events的全部数据。5.5.2 字段选择删除冗余字段拖入“字段选择”组件仅保留以下字段session_iduser_idsession_start_timeprocess_nameurlevent_seconds5.5.3 过滤记录筛选进程为主要浏览器的数据拖入“过滤记录”组件设置条件process_name IN LIST (iexplore.exe,360chrome.exe,360se.exe,chrome.exe,sogouexplorer.exe,QQBrowser.exe)匹配的记录继续进入后续流程不匹配的记录直接丢弃。5.5.4 计算停留时长原始日志只记录焦点切换时刻没有直接给出停留时间因此需要通过前后两条记录的event_seconds相减得到停留时长。步骤如下按session_id、event_seconds升序排序用“分析查询”取下一条记录的event_seconds用“计算器”计算duration_sec next_event_seconds - event_seconds5.5.5 字段选择保留必要字段只保留以下字段user_idprocess_namesession_start_timeurlduration_sec5.5.6 过滤记录筛选停留时长 0 的数据过滤掉duration_sec 0最后一条记录没有下一条因此时长无效需要忽略5.5.7 剪切字符串提取日期将session_start_time提取为日期格式yyyy-MM-dd这样后续按天聚合时可以直接使用不需要重复解析。5.5.8 字段选择设置日期格式将session_start_time的类型设置为Date方便后续提取小时。5.5.9 计算器提取小时使用“计算器”组件从yyyy-MM-dd HH:mm:ss中提取小时HH。【此处插入截图提取小时配置】5.5.10 生成用户-日-浏览器-小时明细到这里原始行为数据已经被压缩到更合适的粒度每个用户每天每个浏览器每个小时这一步非常关键因为它为后续所有统计表提供了统一的基础数据。【此处插入截图用户-日-浏览器-小时明细】5.5.11 分支A生成市场格局表目标统计每个浏览器的总用户数和总使用时长。统计逻辑user_count COUNT(user_id)total_duration_sec SUM(duration_sec)输出到browser_coverage5.5.12 分支B生成时段统计表目标统计每个浏览器在每个小时的活跃用户数。统计逻辑分组字段process_name、hour聚合字段active_user_count user_id 个数输出到browser_hourly5.5.13 执行转换流配置完成后点击运行按钮执行整个转换流。执行时可以在日志窗口中实时查看运行状态。5.5.14 查看结果最后进入元数据页面加载团队私有数据库并打开browser_coveragebrowser_hourly检查数据是否符合预期。六、实验总结本次实验完成了浏览器行为日志从原始 TXT 文件到结构化数据库表的转换主要包括以下几个关键步骤通过文件名和日志内容解析出用户行为记录使用 Java 代码完成半结构化日志拆分通过字段选择、过滤、排序、分组等 ETL 组件完成清洗与聚合输出浏览器覆盖率表和浏览器小时活跃表为后续浏览器市场分析、用户画像分析提供了基础数据。总体来看半结构化日志数据虽然复杂但只要先完成结构化转换再进行分组聚合就能逐步提炼出有价值的分析指标。
800万条浏览器日志,如何加工成用户画像分析数据?看我教你用助睿ETL做浏览器行为分析
发布时间:2026/6/1 8:56:23
实验实训 / udi-studio / ETL / 数据加工 / 数据转换实验平台助睿在线实验平台https://lab.guilian.cn/助睿数智官网https://www.uniplore.com/一、实验背景本次实验围绕“浏览器市场与用户画像分析”展开核心任务是将原始的半结构化行为日志进行解析、清洗、规整和聚合最终加工成可用于分析的结构化数据表。原始数据来自互联网用户行为日志数据量较大、格式复杂单靠传统的文件导入方式无法直接分析因此需要借助助睿 ETL完成从日志到表结构数据的转换。通过本实验我们可以掌握以下能力解析半结构化日志文本将原始行为数据转换为结构化表按浏览器、小时、用户等维度进行聚合统计为后续的浏览器市场分析、用户画像分析打好数据基础。二、实验目的本实验的目标主要有三个熟悉数据集构成与半结构化日志数据特点掌握文本日志解析、字段拆分与结构化转换方法实现多维度数据清洗、聚合与关联加工构建适配分析场景的数据底座。三、实验环境本次实验使用的平台与数据环境如下项目内容实验平台助睿在线实验平台ETL工具助睿 ETL 数据集成平台数据分析平台助睿 BI数据规模1000 用户800 万 行行为记录约 825MB数据类型半结构化日志 用户属性表四、实验数据说明本实验基于首届中国互联网数据挖掘竞赛公开数据集包含典型的用户行为半结构化日志适合做用户行为分析、习惯挖掘、活跃度预测和用户画像研究。4.1 数据集整体构成数据主要包括三部分用户基本信息表demographic.csv存储用户 ID、性别、年龄、职业、教育程度、收入等人口属性信息。浏览器上网记录日志中包含 URL、域名、访问时间等。软件使用记录日志中包含进程名、程序名、使用时长、窗口切换等。其中demographic.csv存储用户 ID、性别、年龄、职业、教育程度、收入等人口属性信息浏览器记录包含 URL、访问时间等软件记录包含进程名、程序名、使用时长、窗口切换等信息。4.2 数据集时间范围数据覆盖 1000 名用户连续 4 周的电脑使用行为跨越 4 个月每月抽取 1 周数据第 1 周2012-05-07 至 2012-05-13第 2 周2012-06-04 至 2012-06-10第 3 周2012-07-02 至 2012-07-08第 4 周2012-08-06 至 2012-08-124.3 数据文件结构数据分为两部分behavior/文件夹按日期归档存放大量 TXT 行为日志demographic.csv用户属性表。两类数据通过user_id唯一关联。4.4 日志文件命名规则每个 TXT 文件代表某个用户一次开机产生的行为日志命名格式为用户ID_日期_开机时间.txt示例0AB6BBBEDFF24EC8BAAC905F45AE314C_2012-05-07_21-22-38.txt从文件名中可以解析出user_id用户唯一标识file_date日志日期file_start_time开机时间4.5 日志文件内部格式每个日志文件固定分为三部分第 1 行Last 数字表示日志最后一条记录距离开机的秒数第 2 行L_Start 时间表示本次开机的绝对时间第 3 行及以后行为记录。行为记录示例如下T177[]P360se.exe[]I5572[]W30378[]V4,1,6,6[]N360安全浏览器[]C360.cn其中分隔符规则如下字段名与值分隔[]字段与字段之间分隔4.6 字段含义字段含义T距离开机的秒数行为发生时间P进程名I进程 IDU浏览器访问 URLW非浏览器窗口句柄V程序版本号N程序名称仅第一次出现C开发公司名称仅第一次出现A/B浏览器窗口句柄4.7 数据特点本数据属于半结构化数据具有以下特点没有固定行列不能直接分析数据量大文件分散格式统一、规则明确适合通过 ETL 进行解析和加工。五、实验步骤5.1 创建实验项目首先进入助睿在线实验平台点击新建项目。输入项目名称互联网用户行为日志数据加工点击“确定”后项目创建完成。创建成功后即可在数据集成页面看到新建项目。5.2 日志数据结构化转换由于原始数据量较大本次实验仅使用其中 20 个 TXT 文件进行学习重点掌握半结构化日志转结构化数据的思路。5.2.1 数据资源获取项目创建完成后点击项目右上角“...”选择打开项目。进入项目页面后可以看到左侧有三个菜单资源库文件元数据其中资源库用于管理工作流文件库用于保存工作流中需要用到的文件元数据管理用于运行配置、数据库、集群等配置。首先在文件库中创建一个目录命名为互联网用户行为日志数据集然后进入公共空间找到实验数据资源逐个导出到刚刚创建的目录中。5.2.2 建立数据源连接如果之前已经创建过团队私有数据库连接则此步骤可以直接跳过如果没有需要先建立数据源连接。5.2.3 创建原始用户行为日志表新建转换工作流命名为创建原始行为日志数据表拖拽一个“执行一个 SQL 脚本”组件到画布中输入以下 SQLCREATE 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 用户行为事件明细表;运行转换流后原始表即可创建成功。5.2.4 获取文件名日志文件批量采集新建转换工作流命名为行为日志数据转为结构化数据拖拽“获取文件名”组件到画布中选择刚刚创建的目录互联网用户行为日志数据集点击“增加”“确认”后目录下的文件将被批量读取。5.2.5 Java 代码日志解析与结构化转换接下来拖入“Java 代码”组件并与“获取文件名”组件连线。这一环节的核心思路是读取日志文件路径从文件名中解析user_id和开机时间跳过前两行头信息逐行解析行为记录提取T、P、I、U、A、B、V、W、N、C等关键字段输出结构化记录。下面是核心 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_idStringuser_idStringl_startStringtStringpStringiStringuStringaStringbStringvStringwStringnStringcStringsource_fileString注意如果字段类型不小心变成 0需要重新配置正确类型否则转换流虽然能执行但数据可能无法正常落库。5.2.6 字段选择有效字段筛选与规整由于 Java 代码输出的字段很多部分属于系统自动带出的附加字段并不需要保留因此要通过“字段选择”组件进行筛选和规整。拖入“字段选择”组件并与 Java 代码连接。打开配置后切换到“移除”选项删除不需要的字段仅保留本实验必要字段。5.2.7 表输出结构化数据表落地拖入“表输出”组件并与“字段选择”组件连接。选择数据库连接团队私有数据库勾选裁剪表指定数据库字段然后在数据库字段中完成字段映射关系。执行转换流后即可将结构化行为日志写入数据库表behavior_events。5.3 数据分析方向确定得到behavior_events后下一步需要明确分析目标。本实验先对process_name进行统计观察不同进程的用户覆盖规模从而判断哪些浏览器最值得作为后续分析对象。这样做的价值在于可以从海量记录中快速筛选重点对象可以判断哪些程序覆盖用户最多为后续的浏览器市场分析提供依据。5.3.1 创建进程统计表新建转换工作流命名为创建进程统计表输入 SQLCREATE TABLE program_stats ( program_name VARCHAR(255) NOT NULL, user_count INT NOT NULL );运行后创建成功。5.3.2 统计进程用户规模新建转换流统计进程用户规模核心流程如下使用“表输入”读取behavior_events用“字段选择”仅保留user_id、process_name用“替换NULL值”将空进程名替换为“未知”用“排序记录”按process_name排序用“分组”统计每个进程对应的用户数用“表输出”落地到program_stats。其中“分组”组件设置如下分组字段process_name聚合字段user_count user_id 个数执行转换流后数据会写入统计表。5.3.3 观察数据确定分析方向接下来借助助睿 BI观察统计结果。进入助睿 BI 后新建数据集并加载program_stats。然后创建工作表选择图表类型为水平条图将program_name拖到 Y 轴user_count拖到 X 轴并按user_count降序排序。从图中可以看出浏览器类进程如chrome.exe、360chrome.exe、sogouexplorer.exe、QQBrowser.exe的用户数明显高于其他软件这说明浏览器覆盖面最广浏览器记录包含 URL便于进一步分析网站偏好因此后续分析对象确定为浏览器。5.4 分析方案设计与数据确定根据前面的统计结果可以将分析对象锁定为浏览器并围绕以下问题展开哪些浏览器用户最多、使用时长最长不同浏览器用户的年龄、职业有什么差异用户集中在哪些时段使用浏览器用户是否会从一款浏览器切换到另一款哪些用户可能停止使用某个浏览器能否根据历史访问行为做个性化推荐为了支撑这些分析后续需要预先构建一系列结构化输出表输出表名内容粒度browser_coverage.csv每个浏览器的用户数、总使用时长每个浏览器一行browser_hourly.csv每个浏览器按小时统计活跃用户数浏览器 × 小时browser_demographic.csv按年龄分段、职业的用户分布浏览器 × 年龄组 × 职业browser_retention.csv每个浏览器第3周到第4周留存率每个浏览器一行browser_migration.csv用户浏览器迁移关系与人数源浏览器 → 目标浏览器churn_features.csvChrome 行为特征及标签每个用户一行churn_probability.csv每个用户的流失概率每个用户一行feature_importance.csv特征重要性每个特征一行high_risk_users.csv高风险流失用户每个用户一行本次实验先完成前两个核心表的加工浏览器用户数 总使用时长统计表浏览器按小时活跃用户数统计表。5.5 数据清洗、聚合与关联加工这一部分是本次实验的重点。解析后的behavior_events单条记录只反映一次电脑操作行为无法直观体现整体使用习惯因此需要继续做清洗、聚合和关联加工。加工思路如下引入行为明细表behavior_events结合用户基础属性表demographic.csv通过用户唯一编号完成联动构建可用于浏览器市场分析的核心统计表。5.5.1 表输入读取行为日志数据拖入“表输入”组件连接线上公共数据源读取behavior_events的全部数据。5.5.2 字段选择删除冗余字段拖入“字段选择”组件仅保留以下字段session_iduser_idsession_start_timeprocess_nameurlevent_seconds5.5.3 过滤记录筛选进程为主要浏览器的数据拖入“过滤记录”组件设置条件process_name IN LIST (iexplore.exe,360chrome.exe,360se.exe,chrome.exe,sogouexplorer.exe,QQBrowser.exe)匹配的记录继续进入后续流程不匹配的记录直接丢弃。5.5.4 计算停留时长原始日志只记录焦点切换时刻没有直接给出停留时间因此需要通过前后两条记录的event_seconds相减得到停留时长。步骤如下按session_id、event_seconds升序排序用“分析查询”取下一条记录的event_seconds用“计算器”计算duration_sec next_event_seconds - event_seconds5.5.5 字段选择保留必要字段只保留以下字段user_idprocess_namesession_start_timeurlduration_sec5.5.6 过滤记录筛选停留时长 0 的数据过滤掉duration_sec 0最后一条记录没有下一条因此时长无效需要忽略5.5.7 剪切字符串提取日期将session_start_time提取为日期格式yyyy-MM-dd这样后续按天聚合时可以直接使用不需要重复解析。5.5.8 字段选择设置日期格式将session_start_time的类型设置为Date方便后续提取小时。5.5.9 计算器提取小时使用“计算器”组件从yyyy-MM-dd HH:mm:ss中提取小时HH。【此处插入截图提取小时配置】5.5.10 生成用户-日-浏览器-小时明细到这里原始行为数据已经被压缩到更合适的粒度每个用户每天每个浏览器每个小时这一步非常关键因为它为后续所有统计表提供了统一的基础数据。【此处插入截图用户-日-浏览器-小时明细】5.5.11 分支A生成市场格局表目标统计每个浏览器的总用户数和总使用时长。统计逻辑user_count COUNT(user_id)total_duration_sec SUM(duration_sec)输出到browser_coverage5.5.12 分支B生成时段统计表目标统计每个浏览器在每个小时的活跃用户数。统计逻辑分组字段process_name、hour聚合字段active_user_count user_id 个数输出到browser_hourly5.5.13 执行转换流配置完成后点击运行按钮执行整个转换流。执行时可以在日志窗口中实时查看运行状态。5.5.14 查看结果最后进入元数据页面加载团队私有数据库并打开browser_coveragebrowser_hourly检查数据是否符合预期。六、实验总结本次实验完成了浏览器行为日志从原始 TXT 文件到结构化数据库表的转换主要包括以下几个关键步骤通过文件名和日志内容解析出用户行为记录使用 Java 代码完成半结构化日志拆分通过字段选择、过滤、排序、分组等 ETL 组件完成清洗与聚合输出浏览器覆盖率表和浏览器小时活跃表为后续浏览器市场分析、用户画像分析提供了基础数据。总体来看半结构化日志数据虽然复杂但只要先完成结构化转换再进行分组聚合就能逐步提炼出有价值的分析指标。