程序化广告的运作原理
大多数关于 程序化广告 的教程都只停留在网页横幅这个层面。其实这很可惜,因为一旦你将这种概念应用到现实世界中,它会变得有趣得多。 如果你之前从未从事过广告行业的工作,也无需担心。你不需要任何广告行业的背景知识就能理解这些内容。只要你能阅读基本的Python代码,那就已经具备了所需的一切条件。 广告本身只是实现这一目标的一种手段而已。真正重要的技能是:如何将现实世界中那些杂乱无章的信息转化为软件能够处理的数据。 在这篇文章中,你将会了解什么是程序化广告,以及为什么它在网页上能够取得如此好的效果。你还会明白,为什么将这种技术应用到户外广告牌上实际上是一个数据建模的问题,并且你会通过编写简单的Pyt
大多数关于程序化广告的教程都只停留在网页横幅这个层面。其实这很可惜,因为一旦你将这种概念应用到现实世界中,它会变得有趣得多。
如果你之前从未从事过广告行业的工作,也无需担心。你不需要任何广告行业的背景知识就能理解这些内容。只要你能阅读基本的Python代码,那就已经具备了所需的一切条件。
广告本身只是实现这一目标的一种手段而已。真正重要的技能是:如何将现实世界中那些杂乱无章的信息转化为软件能够处理的数据。
在这篇文章中,你将会了解什么是程序化广告,以及为什么它在网页上能够取得如此好的效果。你还会明白,为什么将这种技术应用到户外广告牌上实际上是一个数据建模的问题,并且你会通过编写简单的Python代码来实践每一个步骤。
我们将涵盖的内容:
什么是程序化广告?
广告活动包含两个方面:一方面是拥有广告位的一方,比如新闻网站;另一方面则是希望投放广告的一方,比如鞋类品牌。几十年来,连接这两者通常需要通过电话、电子邮件和纸质文件来完成。
而程序化广告则用软件取代了这种人工操作的方式。没有人需要亲自去协商广告的投放位置,系统会自动分析广告位的情况,并在几毫秒内决定是否购买以及以什么价格购买。
当你打开一个网页时,这个网页会告诉广告交易平台某个广告位是空闲的,同时还会提供关于该页面及浏览者的相关信息。广告商的系统会实时参与竞标,最终胜出的广告会在页面完全加载之前显示出来。这个过程被称为实时竞价,而且每天会有数十亿次这样的交易发生。
有两个术语可以帮助你更好地理解这一概念:“库存”指的是卖家可以提供的广告位数量;“展示次数”则是指一个人看到某条广告的次数。
在互联网上,这种模式的运用速度非常快,而且几乎毫不费力。了解其中的原因是很有必要的。
为什么互联网让程序化购买变得如此简单
互联网在无意中使程序化购买成为可能。每一个网页广告位都带有预先设定的结构:它们都有地址,也就是URL,同时也有在页面上的具体位置。这些广告位都存在于一种结构明确的文档中,这种文档就是文档对象模型。此外,这些广告位还能反馈广告是否已经加载并被人看到。
从诞生之初,整个互联网环境就具备被机器读取的能力,因为当时就已经有机器在为它提供服务了。当自动购买系统出现时,它已经拥有一个结构清晰、便于操作的平台——因为这种媒介本身就已经完成了所有的数据建模工作。
请记住这一点,这是理解整个道理的关键。
广告牌带来的问题
现在,把同样的思路应用到广告牌上吧。你会发现,广告牌根本不具备那种方便的数据结构。
一个物理广告牌并不会标明自己的位置或朝向方向,也不会说明本周的收费标准或是否还有空位。在它的历史中,这些信息都存在于价格表和销售人员的记忆中,而不是任何程序可以查询的数据中。
关键在于:户外广告这种媒介之所以落后于互联网,并不是因为它的效果较差,而是因为它没有可供机器读取的信息接口。目标受众本来就在那里,但缺乏结构化的数据才是真正的问题所在。
因此,将程序化购买模式应用到现实世界中,真正的关键并不在于复杂的竞价算法,而在于数据建模。
让我们具体来看一下这个过程。整个流程分为四个步骤,每个步骤都体现了许多工程问题中常见的处理方式。
第一步:确定实体身份
同一个广告牌可能会出现在不同供应商提供的数据集中。每个供应商会给它起不同的名称,并给出略有差异的坐标信息。在进一步进行处理之前,必须先将这些物理对象统一成一条记录。这个过程被称为记录关联,在这里主要是根据地理位置来进行关联。
一个简单的判断方法是:如果两个记录所处的位置相近,并且名称相似,那么就可以认为它们代表的是同一个广告牌。要计算两个坐标之间的距离,可以使用哈弗辛公式。
from math import radians, sin, cos, asin, sqrt
def haversine_m(lat1, lon1, lat2, lon2):
"""计算两个坐标之间的距离,单位为米。"""
lat1, lon1, lat2, lon2 = map(radians, [lat1, lon1, lat2, lon2])
a = sin((lat2 - lat1) / 2) ** 2 + \
cos(lat1) * cos(lat2) * sin((lon2 - lon1) / 2) ** 2
return 6371000 * 2 * asin(sqrt(a))
def same_panel(a, b, max_distance_m=25):
close = haversine_m(a["lat"], a["lon"], b["lat"], b["lon"]) <等于 max_distance_m
similar_name = a["name"].lower().split()[0] == b["name"].lower().split()[0]
return close and similar_name
vendor_a = {"name": "I-95 North Bulletin", "lat": 25.7907, "lon": -80.1300}
vendor_b = {"name": "I-95 Bulletin #4421", "lat": 25.7908, "lon": -80.1301}
print(same_panel(vendor_a, vendor_b)) # True – 同一个广告牌,对应同一条记录在实际系统中,会使用更为模糊的匹配规则以及更多的数据信号,但原理是一样的。首先需要进行实体识别;否则,后续的所有步骤都会导致重复计算同样的信息。
步骤2:将位置视为可计算的上下文来建模
一个坐标本身并不能代表目标受众。要想让某个广告位对购买系统来说具有实际意义,就必须将其表示为一个带有方向信息的点。然后,通过结合道路交通数据,才能判断究竟有哪些人会经过这个广告位。
有用的信息是需要通过计算得出的,而不是预先给定的:
def estimate_impressions(panel, traffic_by_road):
"""根据道路交通数据估算每日广告展示次数。"""
daily_vehicles = traffic_by_road[panel["road_id."]
# 只有朝广告位正面方向行驶的车辆才能看到它
facing_share = 0.5
avg_occupancy = 1.4 # 每辆车上的乘客人数
return int(daily_vehicles * facing_share * avg_occupancy)
panel = {"id": "P-4421", "road_id": "I-95-N", "facing": "south"}
traffic = {"I-95-N": 120000}
print(estimate_impressions(panel, traffic)) # 84000
请注意发生了什么:原始数据只不过是地图上的一个点,而经过处理后,它就变成了购买系统可以用来进行分析的信息——也就是84,000次每日预计的广告展示次数。这种处理方式在数据分析中非常常见:原始数据加上外部信息,就能生成有用的信息。
步骤3:将可用性表示为时间安排,而不是布尔值
一个网络广告位要么当前是可使用的,要么不可使用。在代码中,这种状态通常用布尔值来表示,即“真”或“假”。然而,广告位的实际使用情况往往是按时间段来安排的,其状态也会随着时间的推移而发生变化。库存数量也是会被预订、释放的,因此我们需要实时数据,而不是某个静态的快照。
from datetime import date
class PanelSchedule:
def __init__(self):
self.bookings = [] # 一个包含(开始时间, 结束时间)元组的列表
def book(self, start, end):
if not self.is_available(start, end):
raise ValueError("该时间段内广告位不可使用")
self.bookings.append((start, end))
def is_available(self, start, end):
return all(end < b_start or start > b_end
for b_start, b_end in self.bookings)
schedule = PanelSchedule()
schedule.book(date(2026, 8, 1), date(2026, 8, 14))
print(schedule.is_available(date(2026, 8, 10), date(2026, 8, 20))) # False
printschedule.is_available(date(2026, 8, 15), date(2026, 8, 31))) # True
这个道理在很多地方都适用。每当你对现实世界进行建模时,都要思考某个数值是否真的是固定的。实际上,很多数值都会随着时间而发生变化。可用性、库存数量以及座位分布情况等等,其实都属于需要按时间段来表示的信息,而不是简单的布尔值。
步骤4:将价格表示为函数,而不是一个固定的数字
价目表上只显示了一个数字,但实际价格会根据日期、需求以及剩余库存量等因素而发生变化:
def price_for(base_rate, start, weeks_out, occupancy):
"""根据交货期和需求来计算价格。"""
demand_multiplier = 1 + occupancy # 市场越繁忙,价格越高
urgency_discount = 0.9 if weeks_out > 8 else 1.0 # 提前预订可享受折扣
return round(base_rate * demand_multiplier * urgency_discount, 2)
print(price_for(base_rate=3000, start=date(2026, 12, 1),
weeks_out=19, occupancy=0.85)) # 4995.0
print(price_for(base_rate=3000, start=date(2026, 8, 1),
weeks_out=2, occupancy=0.40)) # 4200.0
一旦价格计算成为一种函数,软件就能瞬间对比成千上万的广告位和日期。而这正是自动购买功能所需要的。
整合各项要素
现在你们已经解决了实体识别、目标受众分析、实时可用性检测以及动态定价等问题。有了这些基础,程序化数字户外广告在现实世界中的运作方式与在线上是一样的。软件可以规划跨各种物理屏幕的广告活动,自动购买广告位,近乎实时地进行调整,并测量广告效果。
其实,这一切都与互联网本身无关。关键在于这些数据是否具有结构化的框架,也就是说,这些数据是否拥有明确的格式,能让软件理解每条数据的含义。一旦为现实世界的数据建立起这样的结构化框架,自动化处理也就成为了可能。
通过练习培养直觉
进行这种练习并不需要特殊的权限。你可以选择任何一份杂乱无章的、基于地理位置的公共数据集,然后按照上述四个步骤来操作。一个很好的数据来源是OpenStreetMap,它提供了数百万个真实地点的免费数据。
首先,通过合并描述同一实际对象的记录来消除重复数据;其次,为每个数据点添加计算得出的上下文信息,而不要将原始记录视为完整的信息;第三,将某个字段建模为会随时间变化的变量,而不是固定值;最后,将处理后的结果封装在一个清晰的接口中,比如一个类或一个小型的API,以便其他系统能够使用它。
虽然你并没有真正构建出一个广告平台,但你已经掌握了那些让自动购买功能得以扩展到新领域的关键技能。
总结
一个好的抽象模型在面对现实世界时依然能够发挥作用。
当你在一个整齐有序的环境中初次学习某个概念时,很容易认为这种整齐性就是该概念本身的一部分。但实际上往往并非如此。只有当你将这个概念应用到混乱的环境中去,看看它是否仍然能够正常运作时,你才能真正了解这个概念的通用性。
程序化购买技术就是一个很好的例子——它从屏幕上转移到了道路旁的墙上。在其他领域,你也可能会发现类似的规律:一个充满潜力的领域,只需要一个结构化的框架就能被有效利用。
希望你们喜欢这篇文章。你可以通过在LinkedIn上与我联系。
相关文章
每位开发人员都应该了解的关于产品数据追踪的相关知识
产品数据记录了您的应用程序或网站内部实际发生的情况。它展示了用户的行为、系统的运行状态,以及业务的运营表现。 在本文中,您将了解什么是产品数据、哪些部分值得追踪、哪些部分可以忽略不计,同时也会明白:编写代码的开发者实际上承担着比他人认为的更大的责任。 目录 什么是产品数据? 为什么应该追踪产品数据? 还有谁会使用您所追踪的数据? 为什么应该尽早开始数据追踪? 为什么数据追踪永无止境? 在您的产品中应该追踪哪些内容? 有哪些内容是不应该被追踪的? 如何安全地处理用户数据? 总结 什么是产品数据? 产品数据指的是您的应用程序或网站内部实际发生的情况。它能够回答一些简单的问题:用户喜欢哪些功能?他们
阅读全文
构建一个“市场时间机器”:使用Python和WebSockets重新模拟交易过程
历史市场数据通常会以已完成的数据集的形式提供。这种格式便于进行分析,但它与交易软件体验实时市场的方式截然不同。在实际情况中,各种事件是依次发生的,未来的发展方向是不可预测的,因此每一个决策都只能基于迄今为止发生的事情来做出。 在本教程中,我们将利用历史成交数据来重现这种交易环境。我们会选取EODHD提供的完整AAPL交易日数据,将超过一百万笔交易转化为有序的事件序列,并通过一个可控制的市场时钟按照这些事件发生的原始时间顺序重新播放它们。 在这个过程中,我们会添加可调节的播放速度、暂停与继续播放的功能、搜索机制,还会开发一个FastAPI服务,该服务能够通过REST接口提供这些控制功能,同时通过
阅读全文
在模型查看医学图像之前和之后,这些图像会发生哪些变化?
医学影像领域的论文中充斥着一些看起来很熟悉的术语:标准化、标签标注、验证、注释以及预处理。 如果你有机器学习的背景,你可能会认为自己已经理解这些术语的含义了。有时候确实如此。 但医学影像领域有一些特殊的之处。有些术语的含义有所不同,而有些术语则会根据具体的使用场景而有不同的用法。 本文将以一张胸部X光片为例,从它被拍摄下来的那一刻开始,一直讲到模型做出预测的整个过程。在这个过程中,我们将了解在医学影像论文中常见的那些术语以及它们真正的含义。 还有一个配套的 笔记本 ,你可以利用它亲自尝试完成这些步骤,而不仅仅是阅读相关内容而已。 我们将涵盖的内容: 你将学到的知识 从图像到数据集 1. 数据采
阅读全文
从数据到价值:通过一个实际应用案例来理解数据管理[完整书籍]
如今,数据已成为一种极其宝贵的资源。它使企业能够在市场中展开竞争,并推动创新,从而提升所提供产品与服务的质量。 数据处理能让团队自动化各种流程。它还能辅助决策制定,为终端用户带来更加个性化的体验,在诸如银行欺诈防范或风险控制等诸多领域帮助人们发现其中的规律。企业必须明白如何以有效、安全且合法的方式收集和利用数据。 你很可能目前正在使用或曾经使用过各种各样的产品与服务。你也知道,那些涉及数据的流程几乎与我们身边的所有事物都息息相关。此外,你或许已经熟悉“大数据”、“数据分析”、“人工智能”以及“机器学习”这些术语了。 但除非你是这些领域中的专家,否则其中一些概念可能会让你感到难以理解。毕竟,这些
阅读全文