ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于ChatGPT的广告素材采集器构建与用户兴趣画像实践

基于ChatGPT的广告素材采集器构建与用户兴趣画像实践 最近在帮团队做广告素材监测工具这件事起于一个特别实际的痛点每天要盯的竞对新广告太多了光靠人工一条条翻看完一轮至少两小时而且经常盯着盯着就漏掉重要变化。后来我把思路改成先采集再让AI做初筛让ChatGPT替我完成广告文案的分类、关键词抽取和受众兴趣推断才终于把这个流程跑顺。这篇文章就把整套实现思路和踩过的坑整理出来聊清楚一个广告采集器到底怎么构建、ChatGPT在里面扮演什么角色、以及所谓的追踪用户该如何合规理解。先明确一个容易误会的点这里说的追踪用户不是偷摸获取个人身份信息而是对广告平台公开的投放数据和聚合后的用户行为数据做统计分析比如某类广告的用户点击偏好、停留趋势、转化倾向。那些真正涉及个人隐私的跨站追踪不在讨论范围内也绝对不建议碰。合规落地之后这类工具通常只服务三个目的竞品分析、素材趋势判断、用户兴趣画像。接下来的内容就按这三个方向展开。1. 项目整体设计与思路拆解1.1 广告采集器到底解决什么问题广告采集器做的事情一点都不玄本质上就是一个持续的数据管道从广告平台、公开榜单、自有业务后台等地方定时抓取广告素材和投放信息然后清洗、结构化、存储最后变成可分析的表格或图表。它在实际工作中解决的痛点是三个竞品广告策略变化掌握不及时。一个新品宣传活动上线往往两三小时内就会出现大量新素材人工盯根本盯不过来漏掉关键节点会直接影响投放策略的调整节奏。广告文案和图片里藏着大量非结构化信息很难用传统规则去归类。比如一句轻盈得像没穿到底是什么卖点限时5折和立减50的促销逻辑有什么本质区别这些判断过去必须靠人来读。用户对不同素材的偏好呈现高度分散状态不聚合分析就无法指导投放。同一个用户可能对美妆素材有反应也对3C测评有反应标签系统如果不能自动更新画像很快过时。所以我才把采集器做成采集AI解析标签聚合三件套。采集保证覆盖范围AI解析解决非结构化素材的理解问题标签聚合把行为数据变成可指导投放的用户画像。1.2 为什么让ChatGPT当解析员而不是决策者我最早尝试过用正则、模板匹配、甚至传统NLP情感分析来做广告文案分类效果非常不稳定。广告文案本来就擅长玩文字游戏同一个意思有几百种变体表达比如全网最低、史低价、到手价、卷后价规则写死的速度远跟不上运营的创意速度。后来把ChatGPT接进来是因为它在语义理解上的确能扩展分类广度。给它一段广告文案让它输出稳定的JSON结构包括所属行业、广告类型、促销力度、目标人群、情感倾向这些字段比正则稳定得多。但我没有让ChatGPT直接做数据决策。原因也很简单AI输出不能保证100%准确如果让它自动决定这条广告要不要跟进投放错一次代价就很大。所以最终设计是ChatGPT只做理解与打标把结论落成结构化标签真正做判断的还是后续的规则引擎和分析报表人工保留最终确认权。这套边界从项目第一天就定死了后面所有开发都围绕这个原则展开。1.3 系统边界设计合规是前提追踪用户这个说法很容易让人产生负面联想所以系统设计时必须把合规边界作为第一优先级。我在源头上只采集两类数据广告平台公开的数据。包括公开广告库、公开素材库、广告投放信息这些数据本身可以合法访问。用户主动产生的聚合行为数据。比如在自家业务系统里用户点击过哪些类型的内容、下载过哪些资料这类数据需要有明确的授权记录。在数据使用上我坚持几个原则不获取可识别个人身份的信息不跨平台拼接用户身份不做精准到个人的定向分析标签体系只到兴趣分组或人群簇层级。把Tracking User变成Understanding Audience语义就从监控变成了理解。2. 核心细节解析与实操要点2.1 广告数据的来源与合法采集姿势做采集器第一步是搞清楚数据从哪来。我实际用过的合法来源包括数据来源类型说明平台公开广告库API/网页部分广告平台提供广告信息公开查询可获取投放素材、投放周期行业公开素材榜网页展示热门广告素材适合做趋势参考自媒体公开页面网页品牌账号公开发布的推广内容注意尊重平台条款自有广告投放后台API自己投放的数据可以合法导出合规风险最低用户行为日志自有系统用户授权后的点击、浏览、转化行为做聚合分析采集姿势上我强烈建议优先用API而不是网页爬虫。API有明确频率限制和数据结构解析稳定网页爬虫容易被反爬机制盯上改版一次就要跟着改一次解析逻辑。但如果必须爬网页也要注意三个细节控制请求频率、设置合理User-Agent、严格遵守robots.txt。这也是很多初学者最容易忽略的点频率太高会直接把出口IP拖黑整个采集任务全挂。2.2 追踪用户的关键指标设计用户追踪落地到工程上其实是一套行为指标。我在设计指标体系时把指标分成三个层级基础行为指标曝光数、点击数、点击率、转化数、转化率、跳出率。内容偏好指标不同广告类别的点击占比、搜索关键词分布、内容反馈正负倾向。人群聚合指标把相似行为用户分到同一分组看分组规模、活跃程度、转化价值。技术实现上我通常给每个匿名用户生成一个不可逆的标识ID不绑定手机号、邮箱等可识别信息。行为事件的结构大致这样{ anonymous_id: a3f9c8d21e, event_type: ad_click, ad_category: beauty, target_url: /beauty/product-A, timestamp: 1718764800, session_duration: 45, device_type: mobile }这个事件流经过聚合之后会生成类似美妆高点击偏好高转化倾向这样的分组标签。注意一点anonymous_id每次访问都重新生成也可以只要标签聚合在足够大的样本上趋势分析依然有效。2.3 采集频率、存储选型与增量策略采集频率不是越快越好。我踩过坑刚开始把定时任务设置成每5分钟跑一轮结果平台接口限流直接警告而且大量重复数据让存储成本翻了几倍。后来按数据变化速度分了三个档数据类型采集频率原因广告素材库每小时增量素材上新快但不需要秒级监控广告投放数据每天全量快照投放周期分析以天为单位用户行为聚合报表每15分钟增量需要观察实时趋势但不能太频繁存储选型这块如果预算有限PostgreSQL完全够了。广告素材和标签都是结构化数据PostgreSQL加JSONB字段可以兼顾灵活性和查询效率。只有当数据量到百万级、需要复杂聚合分析时我才会引入ClickHouse这类列式存储。增量策略用两个字段控制updated_at和fetched_at。每次采集先取最新时间戳只拉取该时间点之后的数据减少无效请求和数据冗余。实测下来同样的数据规模采集请求量能降70%以上。3. 实操过程与核心环节实现3.1 搭建采集管道我用Python搭建整个采集管道主要考虑到生态成熟requests、Scrapy、Pandas这些库都很顺手。核心逻辑不复杂定时触发、请求数据源、解析数据、清洗、入库。下面是一个简化版的采集模块以公开API为例import requests import json import time from datetime import datetime, timedelta API_URL https://api.example.com/v1/ad-library API_KEY your_key_here def fetch_ad_data(since_time): 增量拉取广告数据 since_time: 上次采集时间字符串格式ISO8601 params { api_key: API_KEY, status: active, updated_since: since_time, page_size: 100 } ads [] page 1 while True: params[page] page resp requests.get(API_URL, paramsparams, timeout30) if resp.status_code ! 200: # 触发告警跳过错峰重试 break data resp.json() items data.get(data, []) ads.extend(items) if len(items) params[page_size]: break page 1 time.sleep(0.5) # 控制请求速率 return ads def clean_ad(ad_item): 清洗单条广告数据丢掉无用字段 return { ad_id: ad_item[id], content: ad_item.get(content, ), image_url: ad_item.get(image_url, ), landing_page: ad_item.get(landing_url, ), start_time: ad_item.get(start_time), end_time: ad_item.get(end_time), platform: ad_item.get(platform, ), updated_at: datetime.now().isoformat() } if __name__ __main__: # 第一次跑取最近一周之后取上次更新点 last_run datetime.now() - timedelta(days7) raw_ads fetch_ad_data(last_run.isoformat()) cleaned [clean_ad(a) for a in raw_ads] # 打印前3条检查格式 for c in cleaned[:3]: print(json.dumps(c, ensure_asciiFalse, indent2))这段代码里有几个地方特意加了设计意图分页循环带time.sleep(0.5)目的是避免请求过快触发限流实际数据量大的时候这个间隔要根据接口返回头里的X-Rate-Limit-Remaining动态调整。清洗函数只保留核心字段图片和落地页地址都保留因为后续ChatGPT分析文案时需要原文本而落地页用于转化归因。增量拉取用updated_since参数而不是每次都全量这是控制数据量和成本的关键。3.2 设计广告解析的Prompt模板纯采集没有灵魂真正的难点是让ChatGPT把一条广告文案结构化。我试过很多种Prompt写法最终稳定下来的方案是角色限定输出约束示例引导三段式。先看第一版失败的Prompt请分析以下广告文案并输出广告类型、目标人群、促销力度的JSON。这个Prompt的问题在于没有定义字段取值范围模型容易输出自由文本没有示例模型对促销力度这种主观字段的理解会漂移没有强调只输出JSON模型经常多解释两句废话。后来改成了这样子AD_ANALYSIS_PROMPT 你是一个广告投放分析师。请分析给定的广告文案输出结构化JSON。 字段定义 - industry: 行业分类取值[美妆, 3C数码, 服饰, 食品饮料, 教育, 医疗健康, 汽车, 金融, 家居, 其他] - ad_type: 广告类型取值[品牌广告, 效果广告, 新品推广, 促销活动, 节日营销, 内容种草] - promotion_level: 促销力度取值[无, 弱, 中, 强]满减或折扣可视为强 - target_audience: 目标人群用简短标签描述最多3个逗号分隔 - key_selling_points: 核心卖点最多3个 - sentiment: 情感倾向取值[正面, 中性, 负面] 要求 1. 只输出JSON不要额外解释。 2. 如果信息不足字段用null填充。 3. 严格使用我给出的取值不要自行发明新类别。 广告文案 {ad_content} 示例 输入限时5折熬夜急救精华第二天容光焕发 输出{industry:美妆,ad_type:促销活动,promotion_level:强,target_audience:熬夜人群, 护肤人群,key_selling_points:[急救,折扣],sentiment:正面} 实际使用Prompt时有个非常关键的动作必须给temperature设成0或者很接近0的值。因为广告分类任务要的是稳定不是创意温度越高输出越飘。3.3 接入ChatGPT生成用户兴趣标签广告文案分析完成之后会把结果和用户行为事件关联起来生成用户兴趣标签。这一块是在批处理任务里完成的不是实时同步调用。实现思路是先拉一段时间内用户点击过的广告列表把广告ID汇总后通过ChatGPT分析每条广告的行业和卖点再把行业标签按点击次数加权汇总到用户分组上。示例代码如下import openai from collections import Counter openai.api_key your_openai_api_key openai.base_url https://api.openai.com/ def analyze_ad_content(content): 调用ChatGPT分析单条广告返回结构化字典 prompt AD_ANALYSIS_PROMPT.format(ad_contentcontent) response openai.chat.completions.create( modelgpt-4o-mini, temperature0, messages[ {role: system, content: 你是一个数据处理助手只返回JSON。}, {role: user, content: prompt} ], response_format{type: json_object} ) return json.loads(response.choices[0].message.content) def build_interest_tags(user_ad_click_logs): user_ad_click_logs: 用户点击过的广告记录列表 返回用户分组的兴趣标签权重 ad_content_map {} for log in user_ad_click_logs: ad_content_map[log[ad_id]] log[content] tag_counter Counter() for ad_id, content in ad_content_map.items(): analysis analyze_ad_content(content) industry analysis.get(industry) if industry: tag_counter[industry] 1 total sum(tag_counter.values()) if total 0: return {} # 转换为权重按点击次数归一化到0-1 return {tag: round(count / total, 3) for tag, count in tag_counter.items()}这段代码背后有两个成本控制逻辑先对广告内容做Map去重同一批用户点击的广告去重后ChatGPT调用次数大幅减少成本直接降下来。用gpt-4o-mini而不是最强的模型广告打标任务难度适中小模型足够而且响应速度和价格都更有优势。如果团队自身有条件接入私有化部署的轻量模型效果会更好因为广告数据属于商业敏感信息完全不建议直接传给它不可信的外部服务。我这里只是展示通用做法生产环境务必做好数据脱敏和传输加密。3.4 数据落库与画像更新标签生成之后要落到数据库。我用PostgreSQL存储表结构分三张ads表存储广告基础信息和ChatGPT打标结果。user_groups表存储匿名用户分组ID和各类标签权重。tag_trend表按日期记录标签权重的变化方便做趋势分析。CREATE TABLE IF NOT EXISTS ads ( ad_id VARCHAR(64) PRIMARY KEY, content TEXT, image_url TEXT, landing_page TEXT, industry VARCHAR(32), ad_type VARCHAR(32), promotion_level VARCHAR(16), sentiment VARCHAR(16), analyzed_at TIMESTAMP DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS user_groups ( group_id VARCHAR(64), tag_name VARCHAR(64), tag_weight NUMERIC(5,3), updated_at TIMESTAMP DEFAULT NOW(), PRIMARY KEY (group_id, tag_name) );画像更新的方式我推荐用增量追加定期重算。每15分钟跑一次行为聚合得到新标签同时每天凌晨对存量标签做一次重算避免某个标签因为一次异常点击长期霸占权重。这个双轨机制能兼顾实时性和稳定性。4. 常见问题与排查技巧实录4.1 ChatGPT调用过程中的常见报错这个环节几乎每个人都踩过坑我把自己在项目里遇到的几类问题整理成速查表。现象可能原因处理办法报model not found/ model is not supported请求的模型名不存在或者账号无权限访问该模型检查模型名拼写降到当前账号可用的模型payment was not approved账号付费方式校验失败可能是绑卡异常更新支付方式确认扣款授权通过后再调用You have no credits remaining账号额度用尽检查用量确认余额充值或切换计费方式请求超时/连接失败网络环境不稳定或代理配置异常检查出口网络和超时时间设置重试机制返回内容只有一段废话没有JSONPrompt没有强制约束输出格式在Prompt里显式写明只输出JSON并在代码里用json.loads兜底特别提醒一下每次调用ChatGPT都要在代码里做重试和降级处理。例如遇到临时限流错误等几秒重试连续失败三次就把该条任务扔到一个待重试队列不要 무한阻塞主流程。4.2 数据质量与模型幻觉处理ChatGPT解析广告文案时会产生幻觉比如把买一送一理解成促销力度弱把不限量理解成没有促销。这就是为什么我在最开始就强调AI只做打标不做决策。为了降低幻觉影响我做了三件事Few-shot引导。在Prompt里放三个不同类型的示例模型模仿示例的输出风格准确率能提升不少。字段约束。把industry、ad_type这些字段的枚举值全部列出来强制取值。模型不认识的分类就返回null由后续规则兜底。人工抽检机制。每天随机抽取50条已打标数据人工复核如果准确率低于90%就调整Prompt示例或加一条相似样本。实际上经过一段时间的策略调整后ChatGPT打标的准确率大概稳定在85%到95%之间主要误差集中在行业分类的边界比如穿搭博主推荐可能既算服饰又算美妆。这类情况我不急着改Prompt而是在数据库里加了alternative_tags字段允许一条广告同时挂多个标签后续分析取交集。4.3 合规与安全避坑清单这块可能是相关从业者最容易忽视又最不能忽视的部分。如果你要构建类似的广告采集或用户分析系统请把下面几条当成硬性红线不加设备指纹、不加cookie追踪第三方用户。只分析自己业务范围内产生的数据。严格匿名化。用户标识ID生成一次变一次不做跨会话关联不存储IP、手机号这类可识别信息。数据保留期限一定要明确。我采集的广告数据最多保留180天之后只保留聚合统计结果原始数据自动清除。不要拼凑用户隐私画像。一个标签是偏好健身是没问题的但如果标签串起来能定位到某个具体的人就已经越界了。在我这个项目里合规方案其实很简单就是少拿数据。能只拿聚合结果就绝不拿明细能只拿匿名ID就绝不拿可识别ID。这个原则让我后来在数据安全审查时省了非常多麻烦。4.4 成本控制与token消耗问题ChatGPT接入广告采集器最大的疑虑就是费用。很多做广告投放的人一听到把文案发给AI分析就担心会不会烧钱实际上只要控制好调用方式成本低得惊人。核心是两个策略缓存。同一段广告文案不管被哪个用户点击过只分析一次。项目实际跑下来调用量直接少了三分之二。批处理而不是流式处理。每条广告单独调用API其实是一种浪费可以攒够一定数量后把多条广告组合成一次Prompt请求让模型输出一个JSON数组。这种方法能把token消耗压到接近单条的瓶颈但效率提升非常明显。token用量还有一个隐藏坑如果你在Prompt里塞了太长的示例虽然准确率上去了但每个请求的token消耗都会增加。要平衡一下示例数量和内容长度我最终选择在Prompt里放两个短示例、一个长示例这样既能稳住输出质量又控制了成本。收尾的个人体会我在实际跑这个项目时最大的体会是工具链本身不难难的是把采集、解析、打标、落库这四步串联起来时每一步都可能出现数据质量断层。尤其ChatGPT这种外部依赖一旦输出不稳定后续的标签聚合、趋势报表就全乱了。所以我现在养成了一个习惯哪怕只是本地小实验也一定要把所有原始请求和模型返回结果记录到日志文件里。前期多存一条日志排查问题时就能少掉一根头发。最后再分享一个实用小技巧Prompt版本管理非常值得做。我会给每次调整后的Prompt起一个版本号像ad-analyze-v3这种并把每次版本的输出结果放到一个对比表格里。调了几次后你就知道哪些字段适合让模型输出、哪些字段需要用规则做后处理。这个小习惯帮我省掉了大量重复试错的时间也推荐给你。
返回列表