问题品牌AI可见度监测需要定期生成报告手动从数据库导出数据、用Excel处理、再用PPT制作每次耗时2-3天且格式不统一。本文介绍使用 Python Jinja2 WeasyPrint 实现自动化报告生成涵盖模板设计、数据聚合、图表生成和PDF输出读者可据此搭建基础框架。一、问题与原因初始方案是手动流程从数据库导出品牌提及数据在Excel中计算指标再复制到PPT中绘制图表。主要痛点数据源分散品牌提及次数、情感分析得分、趋势数据存储在不同表中报告模板不固定不同客户或不同周期的报告结构有差异图表生成繁琐每次需手动绘制趋势图、对比图重复劳动每次报告需2-3天且容易出错二、技术选型对比了四种方案方案优点缺点Python ReportLab灵活完全控制PDF布局开发量大图表需自行绘制Python Jinja2 WeasyPrint模板化支持HTML转PDF复杂布局需CSS调试Node.js Puppeteer可直接渲染前端图表依赖浏览器环境资源占用高商业报表工具如FineReport开箱即用成本高定制受限最终选择 Python Jinja2 WeasyPrint原因团队Python技术栈模板化易于维护图表使用Matplotlib生成图片嵌入。三、核心实现1. 数据表结构假设品牌提及数据表brand_mentions结构如下CREATETABLEbrand_mentions(idINTPRIMARYKEYAUTO_INCREMENT,brandVARCHAR(100)NOTNULL,mention_dateDATENOTNULL,mention_countINTDEFAULT0,sentiment_scoreDECIMAL(3,2)COMMENT情感得分范围0-1,INDEXidx_brand_date(brand,mention_date));2. 数据聚合按品牌和时间范围聚合数据返回列表字典。defaggregate_data(brand,start_date,end_date):query SELECT mention_date, mention_count, sentiment_score FROM brand_mentions WHERE brand %s AND mention_date BETWEEN %s AND %s ORDER BY mention_date rowsdb.execute(query,(brand,start_date,end_date))ifnotrows:return[]return[{date:row[0],count:row[1],sentiment:row[2]}forrowinrows]说明实际项目中建议使用连接池并考虑分页或预聚合如物化视图应对大数据量。3. 图表生成使用Matplotlib生成趋势图保存为base64嵌入HTML。注意中文字体需指定。importmatplotlib.pyplotaspltimportbase64fromioimportBytesIOdefgenerate_trend_chart(data):ifnotdata:returnNonedates[d[date]fordindata]counts[d[count]fordindata]plt.figure(figsize(10,4))plt.plot(dates,counts,markero)plt.title(品牌提及趋势)plt.xlabel(日期)plt.ylabel(提及次数)plt.grid(True)# 解决中文显示问题plt.rcParams[font.sans-serif][SimHei]bufBytesIO()plt.savefig(buf,formatpng)buf.seek(0)img_base64base64.b64encode(buf.read()).decode(utf-8)plt.close()returnimg_base644. 报告模板使用Jinja2模板关键区块封面、摘要卡片、趋势图、数据表。!DOCTYPEhtmlhtmlheadmetacharsetutf-8style.card{border:1px solid #ddd;padding:20px;margin:10px;}.trend-chart{width:100%;}/style/headbodydivclasscoverh1{{ brand_name }} AI可见度报告/h1p周期{{ start_date }} 至 {{ end_date }}/p/divdivclasssummarydivclasscardh3提及率/h3p{{ mention_rate }}%/p/div/divdivclasstrend-chartimgsrcdata:image/png;base64,{{ trend_chart_base64 }}//div/body/html5. 主流程defgenerate_report(brand,start_date,end_date):dataaggregate_data(brand,start_date,end_date)trend_chartgenerate_trend_chart(data)context{brand_name:brand,start_date:start_date,end_date:end_date,mention_rate:round(calculate_mention_rate(data),2),trend_chart_base64:trend_chart,}htmlrender_template(report_template.html,**context)pdfweasyprint.HTML(stringhtml).write_pdf()returnpdf四、验证结果在开发机CPU 4核内存16GBMySQL 8.0上测试生成一份包含10个品牌、30天数据的报告数据聚合约2秒索引优化后图表生成约3秒10张图PDF渲染约5秒总耗时约10秒注意具体性能取决于数据量和硬件配置上述数据仅为单次测试参考。验证方法检查PDF是否包含所有品牌章节、图表是否正常显示、数据是否与数据库一致。五、踩坑与边界中文字体Matplotlib默认不支持中文需指定中文字体如SimHei否则图表中文显示为方框。图表尺寸PDF页面宽度固定图表尺寸需提前计算避免溢出。大数据量当数据量超过10万行时聚合查询可能变慢建议使用预聚合表或分页查询。模板版本模板变更后需重新生成所有报告建议对模板进行版本管理。六、总结本文解决了品牌AI可见度报告手动生成效率低的问题采用 Python Jinja2 WeasyPrint 方案实现自动化。根因在于数据分散和重复劳动最终通过模板化、数据聚合和图表自动生成解决。该方案适用于品牌数少于50、周期小于1年的场景更大规模建议引入消息队列和分布式渲染。