助睿实验作业——浏览器市场与用户画像分析-数据加工 #助睿数智#商业数据分析#浏览器用户画像#数据清洗#机器学习一.实验目的本次实验我以首届中国互联网数据挖掘竞赛公开的用户行为日志为处理对象依托助睿数智平台完成半结构化数据到结构化数据的全流程加工核心目标如下深入理解半结构化日志数据的特点掌握文本日志解析、字段拆分的实操方法解决半结构化数据无法直接分析的痛点完成从零散原始日志到标准结构化数据表的规整建立可直接用于分析的用户行为事件明细表掌握数据清洗、多维度聚合、字段衍生的方法搭建适配浏览器用户行为分析场景的核心指标体系学会从海量数据中锁定高价值分析对象建立从数据到业务问题的分析思路为后续用户画像、使用习惯分析打下基础。二.实验环境实验平台助睿数智Uniplore一站式数据科学实验平台平台定位覆盖数据接入、ETL 处理、机器学习建模到可视化分析的全链路零代码数据智能平台产品官网https://www.uniplore.com/实验平台地址https://lab.guilian.cn/数据处理工具助睿 ETL 数据集成平台实验数据用户行为日志数据集数据规模1000 名用户连续 4 周的电脑使用行为共 800 万 条行为记录解压后约 825MB数据构成包含用户基本信息表、浏览器上网记录、软件使用记录三类数据覆盖用户电脑操作的全场景行为三.整体处理流程3.1 数据集整体构成数据集包含三大核心部分用户基本信息表demographic.csv存储用户 ID、性别、年龄、职业、教育程度、收入等人口属性信息。浏览器上网记录日志中包含 URL、域名、访问时间等。软件使用记录日志中包含进程名、程序名、使用时长、窗口切换等。数据总大小解压后约825MB原始行为记录800 多万条覆盖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-123.2 数据文件结构所有数据分为两部分behavior/文件夹按日期归档存放数万条 TXT 行为日志demographic.csv用户属性表两个数据通过用户 IDuser_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 行及以后行为记录核心数据**格式示例T177[]P360se.exe[]I5572[]W30378[]V4,1,6,6[]N360安全浏览器[]C360.cn采用固定分隔符字段名与值分隔[]字段与字段之间分隔3.5 字段含义必须掌握字段含义T距离开机的秒数行为发生时间P进程名如360se.exe、QQ.exeI进程 IDU浏览器访问 URLW非浏览器窗口句柄V程序版本号N程序名称仅第一次出现C开发公司名称仅第一次出现A/B浏览器窗口句柄3.6 数据特点属于半结构化数据无固定行列不能直接分析数据量大、文件分散、格式统一、规则明确本次实验整体分为五大阶段流程逻辑清晰递进实验准备阶段创建专属实验项目导入示例原始日志数据完成数据资源的前期准备日志结构化转换阶段通过 “批量获取文件 自定义 Java 代码解析”将半结构化 TXT 日志转换为标准结构化数据表分析方向探索阶段统计各类软件的用户覆盖率从海量数据中锁定浏览器为核心分析对象数据清洗与聚合阶段对浏览器行为数据进行过滤、时长计算、维度衍生生成用户 - 日 - 浏览器 - 小时的基础明细数据核心指标生成阶段基于明细数据生成浏览器市场格局表和时段统计表为后续可视化分析提供数据支撑。二、实验步骤4.1 创建实验项目首先我登录助睿实验平台进入「数据集成」模块完成项目创建与数据准备点击右上角的「新建项目」输入项目名称为 **「互联网用户行为日志数据加工与分析」**点击「确定」完成创建在项目页面可以看到左侧有3个菜单资源库、文件、元数据资源库用于对工作流的管理包括新建、删除、修改、查看工作流的信息导出导入工作空间调度管理等操作文件库用于保存工作流中需要用到的文件和工作流产生的文件元数据管理是助睿ETL的重要基石可以为工作流定义“运行配置”、“数据库”、“flink集群”等配置进入项目详情页切换到左侧「文件库」标签右键点击根目录选择「新建目录」创建名为「用户行为日志数据集」的目录用于存放后续导入的原始数据进入「公共空间」-「数据资源」找到本次实验的 20 个示例日志文件依次点击文件右上角的「更多」-「导出」将文件导入到刚刚创建的目录中确保后续工作流可直接读取这些数据。4.2 日志数据结构化转换由于原始日志为自定义键值对格式的半结构化数据无法直接用常规组件读取因此我采用 “批量采集 代码解析 规整入库” 的方案完成转换。4.2.1 数据资源获取本次实验先使用 20 个示例 TXT 文件学习半结构化数据的解析方法后续再对接全量数据。我已将公共空间的示例数据全部导入到项目的「用户行为日志数据集」目录中确保文件路径可被后续组件识别。4.2.2 建立数据源连接本次实验使用团队私有数据库此前的实验中已完成「团队私有数据库」的连接配置因此无需重复创建后续所有数据存储操作均使用该连接。4.2.3 创建原始用户行为日志表为了给解析后的结构化数据提供存储载体我先创建了用户行为事件明细表新建转换工作流命名为 **「创建原始行为日志数据表」**拖拽「执行一个 SQL 脚本」组件到画布中配置数据库连接为「团队私有数据库」输入以下 SQL 脚本创建表结构提前定义字段类型避免后续入库时出现类型不匹配问题CREATETABLE behavior_events (id BIGINTAUTO_INCREMENTPRIMARYKEYCOMMENT自增主键,session_id VARCHAR(255)COMMENT会话唯一ID,user_id VARCHAR(100)COMMENT用户ID,session_start_time VARCHAR(50)COMMENT会话开始时间,event_seconds INTCOMMENT事件发生秒数,process_name VARCHAR(255)COMMENT进程名称,process_id VARCHAR(100)COMMENT进程ID,url TEXTCOMMENT访问网址,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 TIMESTAMPDEFAULTCURRENT_TIMESTAMPCOMMENT入库时间,INDEX idx_session_id (session_id),INDEX idx_user_id (user_id))COMMENT用户行为事件明细表;配置完成后点击「确认」运行转换流完成表的创建。4.2.4 获取文件名日志文件批量采集新建转换工作流命名为 **「行为日志数据结构化转换」**拖拽「获取文件名」组件到画布中双击组件点击「浏览文件」选择之前创建的「用户行为日志数据集」目录点击「增加」将目录添加到路径列表确认后即可批量获取目录下所有日志文件的路径和文件名。4.2.5 Java 代码日志解析与结构化转换这一步是本次实验的核心通过自定义 Java 代码完成半结构化日志的解析拖拽「Java 代码」组件到画布中与「获取文件名」组件建立主输出连线双击组件输入日志解析代码核心逻辑为从文件名中解析用户 ID 和会话开始时间读取日志文件并跳过前两行头部信息按分隔符拆分每条行为记录提取关键字段并输出为结构化数据配置输出字段在「输出字段」标签页右键插入字段依次配置 session_id、user_id、l_start、t、p、i、u、a、b、v、w、n、c、source_file类型均设置为 String注意平台会自动重置字段类型为 0导致数据无法入库因此配置完成后必须重新检查所有字段类型确保为 String 类型。配置完成后点击「确认」保存组件设置。Java 解析代码如下// 全局变量定义String pathField;String shortFilenameField;publicbooleanprocessRow()throwsHopException{if(first){pathField filename;shortFilenameField short_filename;first false;}Object[] r getRow();if(r null){setOutputDone();returnfalse;}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 newjava.io.BufferedReader(newjava.io.FileReader(path));String line ;// 跳过前两行Last和L_Startbr.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;}elseif(P.equals(key)){p val;}elseif(I.equals(key)){i val;}elseif(U.equals(key)){u val;}elseif(A.equals(key)){a val;}elseif(B.equals(key)){b val;}elseif(V.equals(key)){v val;}elseif(W.equals(key)){w val;}elseif(N.equals(key)){n val;}elseif(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}}returntrue;}4.2.6 字段选择有效字段筛选与规整Java 代码输出的字段中包含很多平台自动生成的冗余字段因此我进行了字段规整拖拽「字段选择」组件到画布中与 Java 代码组件建立主输出连线双击组件切换到「移除」标签点击「获取字段」选中所有平台自动生成的冗余字段右键点击「删除选中的行」只保留解析得到的业务字段确保后续数据处理的简洁性配置完成后点击「确认」。4.2.7 表输出结构化数据表落地将解析后的结构化数据写入数据库表拖拽「表输出」组件到画布中与字段选择组件建立主输出连线双击组件选择数据库连接为「团队私有数据库」目标表为 behavior_events勾选「裁剪表」避免重复插入数据勾选「指定数据库字段」手动建立流字段与表字段的映射关系确保每个字段的名称和类型一一对应我们在4.2.3小节中创建的表字段与流字段是不一样的双击表字段在下拉框中选择正确的表字段配置完成后点击「确认」。4.2.8 执行转换流与结果验证点击工具栏的「执行」按钮启动转换流运行过程中通过平台日志面板实时查看状态确认所有文件均被成功解析运行完成后通过「数据探查」功能查看 behavior_events 表的数据确认所有字段解析正确无空值或乱码数据格式符合预期。查看数据库结果打开“元数据”tab页在“团队私有数据库”连接上右键选择“加载元数据”然后进入数据探查页面展开“私有数据库”双击目标表“behavior_events”在右侧页面选择“查询”tab标签查看数据库表数据是否符合预期4.3 数据分析方向确定得到结构化数据后我需要从海量记录中锁定核心分析对象避免无意义的全量分析。4.3.1 创建进程统计表新建转换工作流命名为 **「创建进程统计表」**拖拽「执行一个 SQL 脚本」组件输入以下 SQL 创建表结构CREATETABLE program_stats (program_name VARCHAR(255)NOTNULLCOMMENT程序/软件名称,user_count INTNOTNULLCOMMENT使用用户数);运行转换流完成表的创建。4.3.2 统计进程用户规模新建转换流命名为 **「统计进程用户规模」**拖拽「表输入」组件读取 behavior_events 表的数据拖拽「字段选择」组件统计每个进程得用户数量只需用到 user_id、process_name 两个字段所以需要移除其他字段选中user_id、process_name 两个字段拖拽「替换 NULL 值」组件将 process_name 的空值替换为「未知」避免后续分组出错拖拽「排序记录」组件按 process_name 升序排序分组聚合前必须排序否则结果会出错拖拽「分组」组件按 process_name 分组聚合计算 user_id 的个数作为 user_count拖拽「表输出」组件将结果写入 program_stats 表运行转换流完成统计。勾选“指定数据库字段”建立工作流字段与数据库表字段的映射关系。勾选后会激活“数据库字段”tab页在数据库字段tab页右键选择“获取字段”执行转换流4.3.3 观察数据确定分析方向进入助睿 BI 平台新建数据集「进程用户数据统计」关联 program_stats 表修改完成后点击“保存”保存并发布数据集新建工作表选择水平条图将 program_name 拖拽到 Y 轴user_count 拖拽到 X 轴按 user_count 降序排序从可视化结果可以看到浏览器类进程chrome.exe、360chrome.exe、sogouexplorer.exe 等的用户数远高于其他软件且浏览器记录包含 url 字段可进一步分析用户网站偏好因此我确定将浏览器作为本次实验的核心分析对象。4.4 分析方案设计与数据确定根据 4.3 节的统计结果我们发现浏览器类进程的用户覆盖率远高于其他软件且浏览器记录包含url字段可以挖掘用户网站偏好。因此我们将分析对象锁定为浏览器并围绕以下业务问题展开分析浏览器市场格局哪些浏览器用户最多、使用时长最长用户画像不同浏览器的用户在年龄、职业上有何差异使用习惯用户集中在什么时段使用浏览器竞争迁移用户是否会从一款浏览器切换到另一款流失预测哪些用户可能停止使用 iexplore.exe 浏览器个性化推荐根据用户的网站访问历史可以推荐哪些网站为了回答这些问题我们可以预先设计一套可视化方案将在下一实验完成。下表列出了每张图表对应的业务问题、所需数据字段以及最终输出的数据表名后续数据加工将围绕它们展开。输出表名内容粒度browser_coverage.csv每个浏览器的用户数、总使用时长每个浏览器一行browser_hourly.csv每个浏览器按小时统计活跃用户数浏览器 × 小时browser_demographic.csv每个浏览器按年龄分段、职业的用户分布浏览器 × 年龄组 × 职业browser_retention.csv每个浏览器从第3周到第4周的留存率每个浏览器一行browser_migration.csv用户从第3周主用浏览器切换到第4周主用浏览器的迁移对及人数源浏览器 → 目标浏览器churn_features.csv每个用户前三周的 Chrome 行为特征及标签每个用户一行churn_probability.csv每个用户的流失概率AI Studio 输出每个用户一行feature_importance.csv流失预测模型的特征重要性每个特征一行high_risk_users.csv流失概率最高的 20% 用户及其关键特征每用户一行约200行本次实验我们先完成前2个数据的加工首先需要在团队私有数据库中先创建这2个数据表根据分析方向我围绕浏览器用户行为设计了两个核心分析指标浏览器市场格局和用户使用时段偏好对应创建两个数据表browser_coverage存储每个浏览器的去重用户数和总使用时长用于分析市场格局browser_hourly存储每个浏览器在 0-23 点的活跃用户数用于分析用户时段偏好。我新建了两个转换流拖拽「执行一个 SQL 脚本」组件分别输入以下 SQL 创建表结构-- 创建浏览器用户覆盖率与总时长统计表CREATETABLEbrowser_coverage(browser_nameVARCHAR(50)NOTNULLCOMMENT浏览器进程名,user_countINTNOTNULLCOMMENT使用用户数去重,total_duration_secBIGINTNOTNULLCOMMENT总使用时长秒)ENGINEInnoDBDEFAULTCHARSETutf8mb4 COMMENT浏览器用户覆盖率与总时长;-- 创建浏览器按小时活跃用户数统计表CREATETABLEbrowser_hourly(browser_nameVARCHAR(50)NOTNULLCOMMENT浏览器进程名,hourTINYINTNOTNULLCOMMENT小时0-23,active_user_countINTNOTNULLCOMMENT活跃用户数,PRIMARYKEY(browser_name,hour))ENGINEInnoDBDEFAULTCHARSETutf8mb4 COMMENT浏览器按小时活跃用户数;运行转换流完成两个表的创建。4.5 数据清洗、聚合与关联加工我新建了名为 **「互联网用户行为日志数据清洗抽取」** 的转换工作流基于线上公共数据源的全量 behavior_events 数据完成数据清洗与核心指标生成。4.5.1 表输入读取行为日志数据拖拽「表输入」组件连接线上公共数据源读取全量的 behavior_events 表数据团队私有数据库仅存储了 20 个示例数据无法支撑全量分析因此使用线上公共数据源的全量数据。4.5.2 字段选择删除冗余字段拖拽「字段选择」组件与表输入组件建立连线删除所有不需要的字段只保留 session_id、user_id、session_start_time、process_name、url、event_seconds 六个核心字段减少后续计算量。4.5.3 过滤记录筛选进程为主要浏览器的数据拖拽「过滤记录」组件与字段选择组件建立连线配置过滤条件过滤字段process_name过滤方式IN LIST过滤值iexplore.exe;360chrome.exe;360se.exe;chrome.exe;sogouexplorer.exe;QQBrowser.exe匹配结果发送给后续处理组件不匹配结果发送给「空操作」组件剔除无关数据。4.5.4 计算停留时长原始日志仅记录窗口切换时刻无直接停留时长因此通过前后记录的时间差计算双击已拖拽的「排序记录」组件按 session_id 和 event_seconds 升序排序确保同一会话内的记录按时间顺序排列拖拽「分析查询」组件与排序记录组件建立连线配置分组字段为 session_id获取同一会话内下一条记录的 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_sec0 的记录这些记录是会话的最后一条无后续记录无法计算停留时长因此剔除。4.5.7 剪切字符串提取日期拖拽「剪切字符串」组件与过滤记录组件建立连线从 session_start_time 中提取日期部分yyyy-MM-dd存入 usage_date 字段用于后续按天聚合。4.5.8 字段选择设置日期格式拖拽「字段选择」组件将 session_start_time 的类型从 String 转换为 Date方便后续提取小时信息。4.5.9 计算器提取小时拖拽「计算器」组件与字段选择组件建立连线从 session_start_time 中提取小时部分0-23存入 hour 字段。4.5.10 生成用户 - 日 - 浏览器 - 小时明细为了将数据压缩到合适的分析粒度我生成了基础明细数据拖拽「排序记录」组件按 user_id、usage_date、process_name、hour 升序排序拖拽「分组」组件按以上四个字段分组聚合计算每个用户每天每浏览器每小时的总使用时长SUM (duration_sec)和使用次数生成基础明细数据为后续所有统计表提供统一数据基础。4.5.11 分支 A生成市场格局表拖拽「分组」组件与基础明细数据的分组组件建立连线配置分组字段为 process_name聚合计算user_countCOUNT (user_id)即每个浏览器的去重用户数total_duration_secSUM (duration_sec)即每个浏览器的总使用时长拖拽「表输出」组件将结果写入 browser_coverage 表。4.5.12 分支 B生成时段统计表拖拽「排序记录」组件与基础明细数据的分组组件建立连线数据传输模式选择「复制发送」按 process_name 和 hour 升序排序拖拽「分组」组件按 process_name 和 hour 分组聚合计算 user_id 的个数作为 active_user_count拖拽「表输出」组件将结果写入 browser_hourly 表。4.5.13 执行转换流所有组件配置完成后点击「执行」按钮启动转换流。由于全量数据量较大运行过程持续了约 5 分钟期间通过日志面板确认无错误发生。4.5.14 查看结果运行完成后通过「数据探查」功能查看两个目标表的数据browser_coverage 表包含了 6 个浏览器的用户数和总使用时长数据完整无缺失browser_hourly 表包含了每个浏览器在 0-23 点的活跃用户数无异常值符合预期。三、实验结果本次实验成功完成了从半结构化日志到结构化数据的全流程处理最终生成了 4 个核心数据表为后续分析提供了数据支撑表名内容说明数据粒度核心用途behavior_events用户行为事件明细表每条行为记录一行所有后续分析的基础数据program_stats进程用户统计表每个程序一行确定数据分析方向锁定浏览器为核心对象browser_coverage浏览器市场格局表每个浏览器一行分析不同浏览器的用户覆盖率和使用强度browser_hourly浏览器时段活跃表浏览器 × 小时分析用户的使用时段偏好挖掘行为规律从两个核心指标表的初步数据可以看出市场格局Chrome 浏览器的用户数和总使用时长均处于领先地位360 系列浏览器紧随其后IE 浏览器的用户规模已相对较小时段偏好浏览器的使用高峰主要集中在工作日的 9:00-17:00 工作时段晚上 20:00-22:00 有一个小高峰凌晨时段使用量最低符合用户日常使用习惯。四、问题与解决本次实验中我遇到了几个典型问题通过排查和尝试均得到了解决Java 代码组件字段类型自动重置为 0现象配置好的字段类型运行后变为 0数据无法入库解决方法每次配置完成后重新检查所有字段的类型确保为 String 类型后再运行转换流避免平台自动重置导致的问题。分组聚合结果错误用户数统计偏高现象同一个用户被多次计数统计结果明显偏高解决方法在所有「分组」组件之前必须添加「排序记录」组件按照分组字段升序排序确保同组记录连续分组组件才能正确识别。全量数据运行缓慢转换流长时间未完成现象使用全量数据运行时转换流运行时间过长解决方法在元数据中勾选「使用结果流」同时适当调大「表输出」组件的提交记录数减少数据库交互次数提升运行效率。五、实验总结5.1 实验收获通过本次实验我系统掌握了半结构化日志数据的处理方法深入理解了从原始数据到可分析数据的 ETL 全流程学会了使用自定义 Java 代码解析半结构化日志解决了非标准格式数据无法直接分析的痛点熟练掌握了助睿数智平台的常用组件包括数据读取、清洗、过滤、聚合、字段衍生等操作建立了从海量数据中确定分析方向的思路学会了通过用户覆盖率锁定高价值分析对象理解了用户行为分析的核心逻辑即通过清洗、聚合提炼出有价值的指标为后续可视化和业务分析提供支撑。5.2 后续计划本次实验仅完成了浏览器用户行为分析的前两个核心指标后续我将继续开展以下工作加工用户画像表分析不同浏览器用户的年龄、职业分布特征计算各浏览器的用户留存率和迁移率分析用户的平台竞争情况构建流失预测模型的特征工程完成用户流失预测制作完整的可视化仪表盘将本次实验生成的指标数据转化为直观的分析图表。