基于Python与NLP的用户兴趣分析:从文本数据到可视化洞察

📅 2026/8/8 8:10:43
基于Python与NLP的用户兴趣分析:从文本数据到可视化洞察
最近在技术社区看到不少关于“直男”话题的讨论虽然这本身是一个社会文化议题但作为一名技术博主我从中看到了一个有趣的切入点如何用技术手段特别是数据分析与自然语言处理NLP来客观地分析网络文本中的群体特征或行为模式这个话题看似娱乐实则能串联起用户画像、文本分类、情感分析等多个实用的后端开发与数据科学技能。本文将从纯技术的角度出发假设一个分析场景如何通过分析某用户在公开平台如B站、微博的评论、弹幕或视频互动记录来构建一个简单的“兴趣倾向”分析模型我们将使用 Python 作为主要工具涵盖数据爬取合规前提下、文本预处理、特征提取、简单分类到结果可视化的完整流程。无论你是对数据挖掘感兴趣的新手还是想寻找一个轻量级实战项目的开发者都能从本文中获得可直接复用的代码和清晰的实现思路。1. 背景与核心概念从现象到技术问题首先我们需要明确技术边界。我们不旨在对任何个人进行定性判断而是探讨一种通用的文本分析方法。原始讨论中的关键词如“刷美女视频”可以看作是一种用户生成内容UGC中的行为描述。在技术层面这可以转化为分析目标判断一段文本或一系列行为数据中是否显性或隐性地包含对特定主题如“美女”、“游戏”、“科技”的偏好。核心技术网络爬虫合规地获取公开的评论、弹幕数据。自然语言处理NLP对文本进行清洗、分词、关键词提取。文本分类/聚类根据关键词频率或向量特征对文本进行分类。数据可视化将分析结果以图表形式直观展示。这本质上是一个用户兴趣标签生成的简化项目在推荐系统、社群分析等领域有广泛应用。2. 环境准备与版本说明本项目主要使用 Python因其在数据分析和 NLP 领域有丰富的库支持。请确保你的开发环境已就绪。操作系统Windows 10/11, macOS, 或 Linux (如 Ubuntu 20.04) 均可。Python 版本3.8 或以上。推荐使用 3.9。开发工具VS Code, PyCharm 或 Jupyter Notebook 均可。核心 Python 库及版本 我们将使用以下库请通过pip安装pip install requests beautifulsoup4 pandas jieba scikit-learn matplotlib seabornrequests(2.28): 用于发送 HTTP 请求获取网页数据。beautifulsoup4(4.11): 用于解析 HTML/XML提取所需数据。pandas(1.5): 数据处理和分析的核心库。jieba(0.42): 中文分词工具。scikit-learn(1.2): 机器学习库用于文本特征提取和简单分类。matplotlib(3.6) seaborn(0.12): 数据可视化库。项目结构user_interest_analysis/ ├── data/ # 存放原始和清洗后的数据 │ ├── raw_comments.csv │ └── cleaned_comments.csv ├── src/ # 源代码 │ ├── crawler.py # 数据爬取模块 │ ├── preprocess.py # 文本预处理模块 │ ├── analyze.py # 分析与建模模块 │ └── visualize.py # 可视化模块 ├── config.py # 配置文件如请求头、关键词列表 ├── main.py # 主程序入口 └── requirements.txt # 项目依赖列表3. 核心原理与技术拆解3.1 数据获取的合规性与策略我们仅以公开、静态、无需登录即可访问的页面为例进行技术演示。在实际应用中必须严格遵守网站的robots.txt协议尊重版权和个人隐私控制请求频率避免对目标服务器造成压力。技术要点请求头设置模拟浏览器访问避免被简单的反爬机制拦截。headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 }数据解析使用BeautifulSoup根据网页结构定位评论或弹幕所在的 HTML 标签。3.2 中文文本预处理流程原始中文文本无法直接用于分析需要经过一系列清洗和转换清洗去除特殊字符、表情符号、URL、无关标点。分词将句子切分成独立的词语。中文分词是 NLP 的基础jieba是常用工具。import jieba text 陆圣线下刷美女视频的 seg_list jieba.lcut(text) # 精确模式分词 print(seg_list) # 输出[陆圣, 线下, 刷, 美女, 视频, 的]停用词过滤去除“的”、“了”、“在”等无实际意义的虚词。词干化/词形归一化中文相对简单主要处理繁体转简体等。3.3 特征提取从文本到数字计算机无法理解文字需要将文本转换为数值特征向量。常用方法词袋模型Bag of Words, BoW统计每个词在文本中出现的次数。TF-IDF词频-逆文档频率比 BoW 更优能衡量一个词对文档的重要性。scikit-learn提供了TfidfVectorizer类。from sklearn.feature_extraction.text import TfidfVectorizer corpus [我喜欢看科技视频, 这个游戏直播很好看, 美女主播的才艺表演] vectorizer TfidfVectorizer() X vectorizer.fit_transform(corpus) print(vectorizer.get_feature_names_out()) # 查看特征词 print(X.toarray()) # 查看TF-IDF矩阵3.4 简单的兴趣分类思路我们可以定义一个简单的基于规则的分类器Rule-based Classifier作为演示预先定义若干“兴趣主题”及对应的关键词列表。例如{“游戏”: [“游戏”, “直播”, “王者”, “原神”], “时尚”: [“美女”, “穿搭”, “化妆”, “颜值”], “科技”: [“数码”, “评测”, “编程”, “手机”]}对于一段用户文本计算其词语落入各个主题关键词列表的频次。频次最高的主题可视为该文本的初步兴趣倾向。这是一种简化的文本分类方法。4. 完整实战案例用户评论兴趣分析我们模拟一个分析场景假设我们已经通过合规手段获取了一位用户在多条视频下的100条历史评论保存在data/raw_comments.csv中现在需要分析其评论中体现的兴趣分布。4.1 数据准备与预处理首先创建src/preprocess.py文件。# src/preprocess.py import pandas as pd import re import jieba from typing import List # 加载停用词表需自己准备或从网上下载 common_stopwords.txt def load_stopwords(filepath: str) - set: with open(filepath, r, encodingutf-8) as f: stopwords set([line.strip() for line in f]) return stopwords def clean_text(text: str) - str: 清洗单条文本 if not isinstance(text, str): return # 去除URL text re.sub(rhttp\S, , text) # 去除特殊字符和表情符号简单示例 text re.sub(r[^\w\u4e00-\u9fff], , text) # 去除多余空白 text re.sub(r\s, , text).strip() return text def segment_text(text: str, stopwords: set) - List[str]: 分词并去除停用词 words jieba.lcut(text) filtered_words [w for w in words if w not in stopwords and len(w) 1] # 过滤停用词和单字 return filtered_words def preprocess_comments(input_path: str, output_path: str, stopwords_path: str): 预处理主函数 # 1. 读取数据 df pd.read_csv(input_path) print(f原始数据量{len(df)}) # 2. 加载停用词 stopwords load_stopwords(stopwords_path) # 3. 清洗和分词 df[cleaned_text] df[comment].apply(clean_text) df[segmented_words] df[cleaned_text].apply(lambda x: segment_text(x, stopwords)) df[segmented_str] df[segmented_words].apply(lambda x: .join(x)) # 4. 保存处理后的数据 df.to_csv(output_path, indexFalse, encodingutf-8-sig) print(f预处理完成数据已保存至{output_path}) print(df[[comment, segmented_str]].head()) return df if __name__ __main__: # 示例运行 preprocess_comments(../data/raw_comments.csv, ../data/cleaned_comments.csv, ../data/stopwords.txt)4.2 定义兴趣主题与关键词创建config.py文件来管理配置。# config.py # 兴趣主题关键词字典示例可根据实际情况扩充 INTEREST_KEYWORDS { 游戏: [游戏, 打游戏, 直播, 王者, 原神, 英雄联盟, steam, 电竞, 副本, 氪金], 时尚美妆: [美女, 帅哥, 穿搭, 化妆, 颜值, 发型, 护肤, 口红, 时尚, 模特], 科技数码: [手机, 电脑, 数码, 评测, 编程, 代码, 算法, 人工智能, 芯片, 发布会], 动漫二次元: [动漫, 番剧, 二次元, cosplay, 声优, 新番, 追番, 弹幕], 生活娱乐: [吃饭, 旅游, 电影, 音乐, 搞笑, 日常, vlog, 宠物, 健身], } # 请求头 HEADERS { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 }4.3 基于规则的兴趣分析创建src/analyze.py文件实现简单的规则分析。# src/analyze.py import pandas as pd from collections import Counter from config import INTEREST_KEYWORDS def rule_based_interest_analysis(segmented_words_list: List[List[str]]) - pd.DataFrame: 基于规则的兴趣分析 :param segmented_words_list: 列表的列表每个内层列表是一条评论的分词结果 :return: 包含每条评论兴趣倾向的DataFrame results [] for words in segmented_words_list: interest_counter Counter() for word in words: for interest, keywords in INTEREST_KEYWORDS.items(): if word in keywords: interest_counter[interest] 1 # 找出得分最高的兴趣如果都没有则为‘其他’ if interest_counter: main_interest interest_counter.most_common(1)[0][0] else: main_interest 其他 results.append({ words: .join(words), interest_counter: dict(interest_counter), main_interest: main_interest }) return pd.DataFrame(results) def calculate_interest_distribution(analysis_df: pd.DataFrame) - pd.Series: 计算整体兴趣分布 return analysis_df[main_interest].value_counts() if __name__ __main__: # 示例加载预处理后的数据并分析 df_cleaned pd.read_csv(../data/cleaned_comments.csv) # 确保segmented_words是列表格式读取csv后会变成字符串需要转换 import ast df_cleaned[segmented_words] df_cleaned[segmented_words].apply(ast.literal_eval) analysis_df rule_based_interest_analysis(df_cleaned[segmented_words].tolist()) distribution calculate_interest_distribution(analysis_df) print( 兴趣分析结果 ) print(analysis_df[[words, main_interest]].head(10)) print(\n 整体兴趣分布 ) print(distribution)4.4 可视化分析结果创建src/visualize.py文件用图表展示结果。# src/visualize.py import matplotlib.pyplot as plt import seaborn as sns import pandas as pd def plot_interest_distribution(distribution_series: pd.Series, title: str 用户评论兴趣分布): 绘制兴趣分布饼图 plt.figure(figsize(10, 8)) # 过滤掉‘其他’类别如果存在 plot_data distribution_series[distribution_series.index ! 其他] if plot_data.empty: plot_data distribution_series colors sns.color_palette(pastel)[0:len(plot_data)] plt.pie(plot_data.values, labelsplot_data.index, autopct%1.1f%%, colorscolors, startangle90) plt.title(title, fontsize15) plt.axis(equal) # 保证饼图是圆形 plt.tight_layout() plt.savefig(../output/interest_distribution_pie.png, dpi300) plt.show() def plot_top_keywords(word_freq: Counter, top_n: int 20): 绘制高频词条形图 top_words word_freq.most_common(top_n) words, freqs zip(*top_words) if top_words else ([], []) plt.figure(figsize(12, 8)) sns.barplot(xlist(freqs), ylist(words), paletteviridis) plt.xlabel(出现频次) plt.ylabel(关键词) plt.title(f评论内容 Top {top_n} 高频词) plt.tight_layout() plt.savefig(../output/top_keywords_bar.png, dpi300) plt.show() if __name__ __main__: # 示例假设我们已经有了分析结果 from analyze import rule_based_interest_analysis, calculate_interest_distribution from preprocess import preprocess_comments import ast from collections import Counter # 1. 预处理数据 df pd.read_csv(../data/cleaned_comments.csv) df[segmented_words] df[segmented_words].apply(ast.literal_eval) # 2. 进行分析 analysis_df rule_based_interest_analysis(df[segmented_words].tolist()) distribution calculate_interest_distribution(analysis_df) # 3. 绘制兴趣分布 plot_interest_distribution(distribution) # 4. 绘制所有评论的高频词 all_words [word for sublist in df[segmented_words].tolist() for word in sublist] word_freq Counter(all_words) plot_top_keywords(word_freq, top_n20)4.5 整合与运行创建main.py作为项目入口。# main.py import sys import os sys.path.append(os.path.dirname(os.path.abspath(__file__))) from src.preprocess import preprocess_comments from src.analyze import rule_based_interest_analysis, calculate_interest_distribution from src.visualize import plot_interest_distribution, plot_top_keywords import pandas as pd import ast from collections import Counter def main(): # 路径配置 RAW_DATA_PATH ./data/raw_comments.csv CLEANED_DATA_PATH ./data/cleaned_comments.csv STOPWORDS_PATH ./data/stopwords.txt OUTPUT_DIR ./output os.makedirs(OUTPUT_DIR, exist_okTrue) print(步骤1: 数据预处理...) try: df_cleaned preprocess_comments(RAW_DATA_PATH, CLEANED_DATA_PATH, STOPWORDS_PATH) except FileNotFoundError as e: print(f文件未找到请确保数据文件存在: {e}) # 这里可以创建一个模拟数据文件用于演示 print(正在创建模拟数据...) create_sample_data(RAW_DATA_PATH) df_cleaned preprocess_comments(RAW_DATA_PATH, CLEANED_DATA_PATH, STOPWORDS_PATH) print(\n步骤2: 基于规则的兴趣分析...) # 转换分词列表格式 df_cleaned[segmented_words] df_cleaned[segmented_words].apply(ast.literal_eval) analysis_df rule_based_interest_analysis(df_cleaned[segmented_words].tolist()) print(\n步骤3: 计算整体分布...) distribution calculate_interest_distribution(analysis_df) print(兴趣分布统计:) print(distribution) print(\n步骤4: 可视化...) plot_interest_distribution(distribution, title模拟用户评论兴趣主题分布) # 额外分析总体高频词 all_words [word for sublist in df_cleaned[segmented_words].tolist() for word in sublist] word_freq Counter(all_words) plot_top_keywords(word_freq, top_n15) print(f\n分析完成图表已保存至 {OUTPUT_DIR} 目录。) print(预览分析结果前5条:) print(analysis_df[[words, main_interest]].head()) def create_sample_data(filepath): 创建模拟评论数据用于演示 import csv sample_comments [ 这个游戏直播效果太炸了主播操作666。, 最新款手机评测来了摄像头升级巨大。, 美女穿搭分享这套衣服太好看了吧, Python编程入门教程适合零基础小白。, 周末去哪旅游求推荐人少景美的地方。, 动漫新番更新了这集剧情神展开, 搞笑视频合集笑到肚子疼。, 电脑配置怎么选主要用来打游戏和编程。, 化妆品测评这款口红颜色绝了。, 关于人工智能未来发展的讨论。, ] with open(filepath, w, newline, encodingutf-8-sig) as f: writer csv.writer(f) writer.writerow([comment]) for comment in sample_comments: writer.writerow([comment]) print(f模拟数据已创建至: {filepath}) if __name__ __main__: main()运行与结果 在项目根目录下执行python main.py。程序会依次执行预处理、规则分析、统计和可视化。最终会在output/文件夹生成两张图表interest_distribution_pie.png: 展示用户评论在各个预定义兴趣主题上的分布饼图。top_keywords_bar.png: 展示所有评论中出现频率最高的前N个关键词条形图。通过饼图我们可以直观看到“游戏”、“科技数码”、“时尚美妆”等主题的占比。条形图则显示了最常被提及的具体词汇。5. 常见问题与排查思路问题现象可能原因解决思路运行pip install时失败或超时1. 网络问题2. 依赖库版本冲突1. 使用国内镜像源pip install -i https://pypi.tuna.tsinghua.edu.cn/simple package_name2. 创建虚拟环境隔离项目python -m venv venvjieba分词效果不佳专有名词被切分默认词典未包含特定领域词汇使用jieba.add_word(“陆圣”)添加自定义词典或加载自定义词典文件规则分析结果中大量评论被归类为“其他”1. 预设关键词库覆盖度不足2. 文本清洗过度丢失了关键词1. 扩充config.py中的INTEREST_KEYWORDS字典2. 检查停用词表是否误删了重要词汇调整清洗规则可视化图表中文显示为方框matplotlib 默认字体不包含中文在绘图代码前添加字体设置plt.rcParams[‘font.sans-serif’] [‘SimHei’, ‘Microsoft YaHei’]plt.rcParams[‘axes.unicode_minus’] False爬虫代码无法获取数据或返回403错误1. 网站反爬虫机制如验证码、动态加载2. 请求头User-Agent被识别1.严格遵守目标网站规则考虑使用官方API如有2. 更新User-Agent添加Referer等请求头或使用requests.Session()3.重要如非必要避免爬取使用公开数据集或模拟数据6. 最佳实践与工程建议数据合规与伦理优先底线原则任何数据分析项目其数据来源必须合法、合规、符合道德。对于用户数据必须脱敏、匿名化且仅用于分析宏观模式绝不用于定位、评判或影响具体个人。替代方案在技术学习和原型验证阶段强烈建议使用公开数据集如 Kaggle、天池、网络公开的语料库或自己构造的模拟数据。从规则到模型本文演示的基于关键词的规则方法简单直观但覆盖度和准确性有限。下一步可以探索机器学习方法有监督学习如果能有标注好的评论-兴趣标签数据可以尝试使用scikit-learn的SVM、朴素贝叶斯或深度学习模型进行文本分类。无监督学习使用聚类算法如 K-Means、DBSCAN对评论进行自动分群然后人工解读每个群落的主题。词向量模型使用Word2Vec、BERT等预训练模型获取文本的深层语义向量再进行分类或聚类效果更好。工程化扩展模块化如本文所示将爬虫、预处理、分析、可视化拆分为独立模块便于维护和测试。配置化将关键词、请求头、文件路径等放入配置文件如config.py或yaml文件避免硬编码。日志与监控在生产环境中添加日志记录使用logging模块来跟踪程序运行状态和错误。性能考虑处理大规模文本时考虑使用pandas的向量化操作、multiprocessing进行并行处理或使用Dask等库。结果解读的谨慎性技术分析结果只是一个概率性、趋势性的参考。兴趣是多元、动态且复杂的仅凭公开文本的有限信息所做的分析其结论必须谨慎对待避免绝对化。报告分析结果时应着重说明分析方法、数据局限性和结论的不确定性。通过这个项目我们不仅实践了从数据获取到分析可视化的完整 NLP 流水线更重要的是建立了一种用数据驱动的、结构化的方式去思考问题。这种能力远比分析某一个具体话题更有价值。你可以尝试更换不同的关键词库将其应用到其他领域如分析产品评论的情感倾向、归纳技术博客的主题分布等从而解决更多实际业务问题。