
1. 项目背景与技术选型短视频平台的用户兴趣分析已经成为当前互联网行业的重要研究方向。随着短视频内容爆炸式增长平台需要更精准地理解用户偏好以优化内容推荐和运营策略。传统的人工分析方法已经无法应对海量数据而基于大数据技术的自动化分析系统正成为行业标配。在这个项目中我们选择Flask作为后端框架主要基于以下考虑轻量级特性相比Django等全功能框架Flask更适合快速构建数据API服务Python生态与数据分析工具链Pandas、Matplotlib等无缝集成灵活性可以自由选择数据库和前端技术栈大数据处理方面我们采用分层架构数据采集层使用ScrapyRequests构建分布式爬虫存储层HDFSMySQL混合存储方案计算层Spark进行批量处理Flink处理实时数据可视化层EChartsPyecharts实现交互式图表提示在实际部署时建议使用Redis作为缓存层特别是对于热门视频的分析结果可以显著降低数据库压力。2. 爬虫系统设计与实现2.1 爬虫架构设计短视频平台的爬虫系统需要解决三个核心问题反爬机制应对数据增量更新分布式调度我们的解决方案采用主从架构[调度服务器] ←→ [多个爬虫节点] ↑ [任务队列] ←→ [结果存储]关键组件说明调度服务器负责任务分配、失败重试和速率控制爬虫节点运行实际爬取逻辑支持动态扩展任务队列使用RabbitMQ实现优先级队列结果存储MongoDB存储原始数据便于后续处理2.2 反爬策略应对方案通过分析主流短视频平台的防护机制我们总结出以下应对策略防护类型解决方案实现细节IP限制代理池轮换维护100高质量代理IPUserAgent检测动态UA生成内置200真实设备UA行为分析随机延迟鼠标轨迹模拟每个请求间隔2-5秒验证码第三方打码平台对接XX打码API数据加密逆向分析JS使用PyExecJS执行关键JS核心代码示例def get_video_info(video_id): headers { User-Agent: random.choice(USER_AGENTS), Referer: https://www.douyin.com/ } proxy get_proxy_from_pool() try: response requests.get( fhttps://www.douyin.com/video/{video_id}, headersheaders, proxies{http: proxy}, timeout10 ) if 验证码 in response.text: raise CaptchaException(触发验证码) return parse_response(response) except Exception as e: mark_proxy_failed(proxy) raise e2.3 数据增量更新机制为保证数据的时效性我们设计了三级更新策略实时监控针对头部创作者粉丝100万每30分钟更新一次日常扫描普通创作者粉丝1-100万每天更新一次全量备份每周日凌晨进行全量数据备份更新判断逻辑def need_update(video): # 新视频24小时内发布 if video[publish_time] datetime.now() - timedelta(days1): return True # 热门视频点赞1万 if video[like_count] 10000: return time_since_last_update(video) timedelta(hours6) # 普通视频 return time_since_last_update(video) timedelta(days1)3. 用户兴趣建模与分析3.1 数据预处理流程原始爬取数据需要经过以下处理步骤数据清洗去除重复、无效记录特征提取从原始数据中提取结构化特征数据增强补充第三方数据如公开的用户画像特征工程关键代码def extract_features(raw_data): # 基础特征 features { video_id: raw_data[aweme_id], duration: raw_data[duration], create_time: parse_time(raw_data[create_time]), music: raw_data[music][title] } # 内容特征 features[hashtags] [tag[name] for tag in raw_data[text_extra]] features[word_count] len(raw_data[desc].split()) # 用户行为特征 stats raw_data[statistics] features.update({ like_count: stats[digg_count], comment_count: stats[comment_count], share_count: stats[share_count] }) return features3.2 兴趣模型构建我们采用多维度加权评分模型来计算用户兴趣度兴趣得分 0.4×观看时长权重 0.3×互动权重 0.2×搜索权重 0.1×社交权重各维度详细计算方式观看时长权重def calc_watch_score(watch_seconds, video_length): completion_rate min(watch_seconds / video_length, 1.0) return math.log(1 completion_rate * 100)互动权重点赞、评论、分享def calc_interaction_score(actions): weights {like: 0.5, comment: 0.3, share: 0.2} return sum(weights[action] for action in actions)搜索权重def calc_search_score(keywords, search_history): return sum(1 for kw in keywords if kw in search_history)社交权重关注、好友关系def calc_social_score(user, author): if user[follows] and author[id] in user[follows]: return 1.0 if user[friends] and author[id] in user[friends]: return 0.7 return 0.23.3 实时兴趣分析为支持实时推荐我们使用Flink构建了流式处理管道Kafka → Flink → Redis ↑ ↓ 原始数据 处理结果处理逻辑主要包含事件时间窗口处理5分钟窗口兴趣衰减计算最近行为权重更高实时特征更新核心算子实现public class InterestCalculator extends KeyedProcessFunctionString, UserAction, UserInterest { Override public void processElement( UserAction action, Context ctx, CollectorUserInterest out) { // 获取当前兴趣状态 UserInterest interest state.value(); if (interest null) { interest new UserInterest(action.getUserId()); } // 更新兴趣分数 double decayFactor Math.exp(-0.1 * (currentTime - action.getTimestamp())); double newScore calculateActionScore(action) * decayFactor; interest.updateScore(action.getCategory(), newScore); // 保存状态并输出 state.update(interest); out.collect(interest); } }4. 数据可视化系统实现4.1 前端架构设计可视化系统采用前后端分离架构Flask API ←→ Vue.js前端 ↑ 数据分析服务技术栈选择图表库ECharts Pyecharts前端框架Vue 3 Element Plus通信协议WebSocket RESTful API4.2 核心可视化场景4.2.1 用户兴趣热力图展示用户群体在不同时间段对不同类别视频的兴趣变化function initHeatmap() { const chart echarts.init(document.getElementById(heatmap)); const option { tooltip: {}, visualMap: { min: 0, max: 1, calculable: true }, xAxis: { type: category, data: [00:00, 04:00, 08:00, 12:00, 16:00, 20:00] }, yAxis: { type: category, data: [美食, 旅游, 科技, 时尚, 体育] }, series: [{ name: 兴趣度, type: heatmap, data: [...], label: { show: true }, emphasis: { itemStyle: { shadowBlur: 10, shadowColor: rgba(0, 0, 0, 0.5) } } }] }; chart.setOption(option); }4.2.2 兴趣演化趋势图展示单个用户兴趣随时间的变化趋势app.route(/api/user/int:uid/interest_trend) def get_interest_trend(uid): data db.query_trend_data(uid) trend ( Line() .add_xaxis([d[date] for d in data]) .add_yaxis(美食, [d[food] for d in data]) .add_yaxis(科技, [d[tech] for d in data]) .set_global_opts( title_optsopts.TitleOpts(title兴趣趋势), tooltip_optsopts.TooltipOpts(triggeraxis) ) ) return jsonify(trend.dump_options())4.2.3 用户群体画像展示不同用户群体的特征分布function renderRadar() { const chart echarts.init(document.getElementById(radar)); const option { radar: { indicator: [ { name: 活跃度, max: 100 }, { name: 消费力, max: 100 }, { name: 内容偏好, max: 100 }, { name: 社交指数, max: 100 }, { name: 设备价值, max: 100 } ] }, series: [{ type: radar, data: [ { value: [85, 72, 89, 65, 78], name: Z世代 }, { value: [62, 88, 70, 83, 65], name: 都市白领 } ] }] }; chart.setOption(option); }4.3 性能优化实践在大数据量场景下我们采用了以下优化措施数据采样对超过100万条记录的数据集使用蓄水池采样算法渐进式渲染分批加载和渲染大数据集WebWorker将复杂计算移出主线程服务端聚合在数据库层面预先聚合数据采样算法实现def reservoir_sampling(iterable, k): reservoir [] for i, item in enumerate(iterable): if i k: reservoir.append(item) else: j random.randint(0, i) if j k: reservoir[j] item return reservoir5. 系统部署与运维5.1 基础设施规划生产环境推荐配置Web服务器2台4核8GNginx Gunicorn数据库服务器主从架构16核32GMySQL Redis大数据集群至少3节点HDFS Spark爬虫节点根据目标站点数量动态扩展5.2 监控指标设计关键监控指标包括爬虫健康度成功率、延迟、被封禁率系统性能API响应时间、数据库查询耗时数据质量完整性、时效性、一致性Prometheus监控配置示例scrape_configs: - job_name: flask_app metrics_path: /metrics static_configs: - targets: [app1:5000, app2:5000] - job_name: spark metrics_path: /metrics static_configs: - targets: [spark-master:4040]5.3 常见问题排查在实际运营中我们总结了以下典型问题及解决方案爬虫被封禁现象突然大量返回403状态码解决方案立即停止爬取检查UserAgent和IP是否暴露增加随机延迟数据不一致现象可视化图表显示异常值排查步骤检查数据管道是否中断验证ETL作业是否成功对比原始数据和计算结果性能下降现象API响应变慢优化方向增加数据库索引优化Spark作业引入缓存层经验分享在高峰期前预先扩展爬虫节点可以避免因临时增加爬取量导致IP被封。我们建立了一个自动扩缩容系统根据任务队列长度动态调整爬虫节点数量。