当前位置:   article > 正文

互联网DSP广告系统架构及关键技术解析 | 广告行业资深架构师亲述_广告平台数据处理架构

广告平台数据处理架构

http://www.360doc.com/content/15/0806/07/2909773_489803369.shtml

此文是根据付海军在【QCON高可用架构群】中的分享内容整理而成,转发请注明出处。

付海军,现就职于时趣互动,任技术总监,负责移动原生广告平台引擎开发和数据挖掘工作,06年毕业于兰州大学,曾就职于阿里巴巴集团万网从事主机面板和云计算底层开发;之后加入亿玛在线从事互联网广告程序化购买相关的工作,负责RTB竞价投放系统和大数据平台。对于系统架构设计和技术团队建设感兴趣,关注高并发实时系统,海量数据处理。

前言

大家好,感谢主持人,今天我讲的内容是DSP广告系统架构及关键技术,分享一下我过去几年在做DSP广告系统过程中的一些体会和经历,涉及到的内容如果后续想做广告系统的人员应该是可以做一些参考的,后续如果有疑问在分享结束后也可以跟大家私下交流,下面我就开始今天的分享了。

广告和网络游戏是互联网企业主要的盈利模式

广告是广告主通过媒体以尽可能低成本的方式与用户达成接触的商业行为。也就是说按照某种市场意图接触相应人群,影响其中潜在用户,使其选择广告主产品的几率增加,或对广告主品牌产生认同,通过长期的影响逐步形成用户对品牌的转化。

一个好的DSP系统需要满足:

  1. 拥有强大的RTB(Real-Time Bidding)的基础设施和能力。

  2. 拥有先进的用户定向(Audience Targeting)技术。

首先,DSP对其数据运算技术和速度要求非常之高。从普通用户在浏览器中地址栏输入网站的网址,到用户看到页面上的内容和广告这短短几百毫秒之内,就需要发生了好几个网络往返(Round Trip)的信息交换。

Ad Exchange首先要向DSP发竞价(bidding)请求,告知DSP这次曝光的属性,如物料的尺寸、广告位出现的URL和类别、以及用户的Cookie ID等;DSP接到竞价请求后,也必须在几十毫秒之内决定是否竞价这次曝光, 如果决定竞价,出什么样的价格,然后把竞价的响应发回到Ad Exchange。

如果Ad Exchange判定该DSP赢得了该次竞价,要在极短时间内把DSP所代表的广告主的广告迅速送到用户的浏览器上。整个过程如果速度稍慢,Ad Exchange就会认为DSP超时而不接受DSP的竞价响应,广告主的广告投放就无法实现。

其次,基于数据的用户定向(Audience Targeting)技术,则是DSP另一个重要的核心特征。从网络广告的实质上来说,广告主最终不是为了购买媒体,而是希望通过媒体与他们的潜在客户即目标人群进行广告沟通和投放。

服务于广告主或者广告主代理的DSP,则需要对Ad Exchange每一次传过来的曝光机会,根据关于这次曝光的相关数据来决定竞价策略。这些数据包括本次曝光所在网站、页面的信息,以及更为关键本次曝光的受众人群属性,人群定向的分析直接决定DSP的竞价策略。DSP在整个过程中,通过运用自己人群定向技术来分析,所得出的分析结果将直接影响广告主的广告投放效果。

此次分享主要针对以下几个方面,描述DSP广告系统架构及关键技术:

  1. 广告系统概念介绍

  2. 广告系统业务流程

  3. DSP系统架构

  4. RTB竞价引擎结构

  5. 点击率预测

  6. DMP数据处理架构

  7. 受众定向划分

  8. 用户画像与广告系统反作弊

程序化购买的特点

下图是在DSP产生之前和产生之后广告行业的两种最常见产业链

传统的广告投放模式的产业链是广告主通过广告代理,以广告网络/联盟为渠道在媒体网站展示广告,达到接触受众的目的的过程。

这种模式的好处是媒体网站可以通过通过包段或CPS的模式可以售出自己的广告位,但是这类售出是偏粗放型的,长期同类型的广告投放,受众会视觉疲劳,点击率会下降,转化也会随之下降。为了能够获得更多的收益,媒体必须通过差异化销售细分自己的广告位和受众。而事实上显示广告领域最初的定向投放的最初动机是供给方拆分流量以获得更高的营收。好的位置,通过包段通常会供不应求,但是对于长尾流量通常是会无人问津,即便是对于广告主来说同一个潜在客户在大媒体出现会有广告主包段进行购买,但是在小网站出现就会没人买。事实上潜在客户在哪里出现对于广告主都是同一个人,如果能显示与客户需求相吻合或接近的广告就有可能产生转化。在将优质广告位包段售出后,如果对用户有足够的认识,有足够多不同类型的广告主,在流量可以拆分到单次展现的购买粒度,就有可能依据不同的受众定向为每个广告主找到合适的人群和流量。

程序化购买颠覆了原有广告产业链,形成了全新的产业链。

鉴于群里有很多人不是做广告系统的,为了能够在后续的介绍过程中更容易理解介绍的内容,这里先介绍一些广告行业中常见的一些概念。

DSP(Demand Side Platform),是广告需求方平台,DSP为广告主提供跨媒介、跨平台、跨终端的的广告投放平台,通过数据整合、分析实现基于受众的精准投放,并且实时监控不断优化。

RTB(Real Time Bidding)实时竞价是DSP、广告交易平台等在网络广告投放中采用的主要售卖形式,会在极端的时间内(通常是50~100毫秒以内)通过对目标受众竞价的方式获得该次广告的展现,RTB的购买方式无论在PC端或是移动端均可以实现。

程序化购买(Programmatic Buying)根据广告主定义的期望受众,系统帮助其找出优选的媒体来购买受众,为广告主提出最优媒介采买计划,通过程序化购买的方式执行,并按照期望的周期反馈监测结果,并对后续投放进行优化。包括但不仅限于RTB购买。

最常见的DSP行业中的供需业务流,广告主作为需求方,潜在客户是最终的受众,中间穿插着代理机构,DSP,AdNetwork,AdExchange,SSP和供应方也就是媒体。

下图是DSP平台的广告投放流程,投放过程中涉及到广告受众,媒体网站,adx和dsp,分别标注了广告投放各阶段伴随发生的事件。从1~7步之间只允许100ms之内的延时,否则广告受众就会觉得网页加载速度太慢而选择离开。

在线广告的核心问题

需要在特定用户,在指定上下文的环境下,找到最合适的广告,进行投放,并尽可能产生转化。

在线广告的挑战

大规模

百万量级页面,十亿量级用户,需要被分析处理

高并发在线投放(每天处理百亿次广告交易请求)

时延要求严格(adx通常要求竞价响应时间在100ms完成)

用户定向动态变化

用户的关注点和购物兴趣变化会比较频繁,需要能够及时更新用户画像

上下文条件变化频繁

用户和上下文多样化的环境一起用于广告候选检索


DSP系统架构


上图是主要模块的流程图涉及到的角色包括广告主网站,媒体网站,广告网络和DSP,以及DSP内部的相关模块,如:RTB引擎,业务平台,日志收集系统,DMP,CM和反作弊系统。

  1. 投放前DSP会要求在广告主网站布码,同时在DSP的业务平台中录入广告投放的需求,如投放金额,投放排期,投放定向(如地域,兴趣,年龄等),最高限价。

  2. 当访客(即潜在的消费者)从左上角访问广告主网站开始,访客在广告主网站上的行为会被收集,同时DSP会与ADX和SSP进行Cookie Mapping,形成日志进行处理,形成回头客相关的行为数据标签。

  3. 当访客完成对广告主网站的访问,去其他媒体网站进行访问时,相应的媒体广告位根据事先嵌入的广告代码向广告网络发起广告请求,广告网络会将广告请求封装成http头 pb体的格式向多个DSP发起竞价请求。

  4. 当DSP接到竞价请求时会根据与广告网络约定的pb格式进行解包,拆解出相关的字段进行匹配,根据之前相关媒体积累的点击率结合点击率预测模型对出价进行预测,找出平台内在此次竞价请求能让平台利益最大化的广告主的创意进行投放,返回给广告网络出价与广告代码

  5. 广告网络会在特定时间内(通常是50~100毫秒)根据多个DSP的出价高低,以第二名价格多一分的价格让出价最高的dsp胜出,并将广告代码中的展现宏和点击宏进行替换(替换过程中会根据事先与dsp约定好的公钥对价格进行加密,以防止第三方篡改和窃听)

  6. 广告网络将广告代码返回给媒体,媒体会将广告代码放置在js对应的位置进行展现,展现和点击的过程中会先后触发广告网络和胜出DSP的展现代码,广告网络和DSP分别接收到展现请求会对相应的展现进行计费操作(月底会相互进行对账)

  7. DSP内部会根据收集到的展现和点击进行计费操作,形成相应的报表;而浏览、展现、点击的记录会分别进行收集形成日志,经过ETL由DMP进行抽取和分析,形成媒体数据,用户标签,CookieMatch数据以及回头客用户标签数据,这些数据会在投放过程中作为RTB竞价的参考依据。

整个投放过程中其实还有一些其他的模块出现如CookieMapping、反作弊,动态创意、网站分析系统。只不过这些系统不是在主干流程上,后续单独进行描述和分析。

为了保证投放,DSP系统实现了多机房部署的结构,南北方机房分别在杭州和北京部署RTB引擎、点击率预测与相关的展现点击收集节点。投放活动相关数据通过Redis进行缓存,多机房进行准实时同步,媒体展现点击数据通过kafka队列进行推送,通过Consumer进行消费统计,最后通过媒体数据分发集群分发到多个机房进行使用。

RTB投放引擎的架构

RTB引擎是DSP系统的核心,是实现高并发实时反馈的关键,RTB对外以HTTP服务形式暴露接口,当媒体上的js被触发,adx/ssp收到js请求后会将请求封装成http头 pb体(protocol buffer,谷歌定义的序列化数据交换格式)的方式作为客户端连接RTB,RTB对http消息按照事先约定解包在内部依靠相关数据进行计算,最终返回pb或json格式的出价和广告代码给广告交易平台。RTB 需要支持高并发(每天百亿级别请求)和低延时(50ms之内需要反馈)。

当时我们的RTB采用Linux C 开发,通过Adapter适配器层解耦适应不同的SSP/adx,算法池内部拆分成五层,五层之间相互正交,算法模块允许热插拔,编译完成的动态链接库可根据配置文件的变化实时进行加载和卸载,允许多算法链并行拆分流量进行A/B测试,流量处理过程中会对流经不同算法链的流量打上不同的算法标签,并在后续展现,点击过程中持续带上此标签用于后续效果的跟踪和分析。

下面说一下在针对RTB进行架构设计过程中涉及到的一些技巧:


由于一个dsp要接触到尽可能多的流量和用户才有可能找到符合广告主定向的目标受众,那dsp一定要对接很多的adx和ssp,来接受尽可能多的流量。设计适配器层的目的就是将不同adx之间的流量格式差异消灭在适配器这一层,对于进入系统内部的流量都一视同仁,简化了rtb系统的复杂性。RTB系统在设计之初就考虑了AB测试的环节,让算法的效果能够进行横向比较,方便算法进行优化。RTB本身是不带状态的,也就是说,它只能依靠外部的辅助系统提供的信息,如点击率预测,人群定向和反作弊这类模块提供的数据才能实现快速反馈的同事能正确反馈。

DMP

对于RTB的设计在后续提问和讨论的环节我们再做进一步分析,下面讲一下DSP系统中除了RTB之外的另外一个核心:DMP

首先需要定义一下广告投放过程中关键的一些数据:

广告系统DMP数据处理的架构

跟大多数的大数据相关的系统很相似,基本上逃不开那几样东西Hadoop,storm,redis等等:

数据处理部分结合了Hadoop的离线计算、Spark的批处理和Storm的流式计算。

HBase和MySQL用于最终结果落地用于前端查询。

ElasticSearch 有准实时索引,用于明细数据实时查询和时间序列历史回溯统计。

Spark内置的机器学习算法库MLLib主要使用分类,聚类KMeans,协同过滤,决策树,逻辑回归。

由于之前在群里的分享中,王新春@大众点评 ,王劲@酷狗音乐 讲了很多storm实时处理和大数据架构的内容,他们二位都是大数据领域的大佬了,我在这里就不班门弄斧了,简单提一下广告行业里是怎么做的,基本上大同小异,大家用的东西都差不多。

对于广告投放要投放的目标,落实在dmp中就是需要找出相应的受众定向,下面简单分析一下几类受众定向:

上图是广告有效性模型根据受众定向的定性评估表,水平方向是定向技术在广告信息接受过程中所起作用的阶段,垂直方向是大致的效果评价(从下往上效果依次升高)。

按照计算框架不同这些受众定向可以分为三类:

  1. 用户标签t(u),即在时间序列上用户历史行为为依据,为用户打上的标签。

  2. 上下文标签t(c),即当前用户联系上下文在当前的访问行为达到的即时标签。

  3. 广告主定制化标签t(a,u),是根据特定广告主提供的特定用户群在其网站上的访问行为数据加工所得。

其中:地域定向、频道定向和上下文定向属于t(c)的定向方式;人口属性定向、行为定向属于t(u)的定向方式;
而重定向和Look-alike则是t(a, u)的定向方式。
地域定向主要用于商家销售目标局限于特定区域的情况下;

人口属性主要包括年龄,性别,收入,学历等;频道定向主要是针对媒体侧特点,对相应受众进行划分;上下文定向主要是根据当前网页的内容上下文推送相关广告;行为定向是根据用户历史访问行为,了解用户喜好,进而推送相关广告;精确位置定向是在移动设备上根据精确的地理位置投放广告,更聚向与地域性非常强的的本地生活类广告主;

重定向是对特定广告主一定时间段内访客投放广告以提升效果的广告投放方式,人群规模由广告主固有用户量和媒体重合量共同决定;新客推荐是在重定向规模太小,无法满足广告主接触用户需求的情况下,以重定向用户为种子,根据广告平台数据积累,为广告主找出行为相似用户的定向条件。

用户画像的方法

接下来基于上面提到的积累受众定向介绍一下用户画像的方法

我们能够看到用户画像其实也就是对于用户特征的提取,涉及到人口,设备,运营商,位置以及用户的浏览,点击购买等行为数据。用户画像是通过对用户特征的提取对用户行为进行定性和定量的描述,形成:【用户ID:用户标签:标签权重】形式的用户画像标签,在广告投放过程中,根据提取流量对应用户权重较高的若干个标签反向对广告主进行筛选,找出适合流量特点的广告素材。 用户标签用于广告主对于受众的选择,而权重用于在海量用户标签里选取重点的标签进行投放。

同时要注意用户的画像随时间的推移会有衰减,需要在用户画像的过程中考虑时间衰减的因素,因为用户的爱好和习惯会随着时间变长而有变化,同时数据的时效性也决定了用户画像的准确程度,进而影响广告的投放。

事实上在广告平台中收集到的最多的数据是用户的浏览数据,在拿到这么多的浏览数据的情况下,想要分析出用户的爱好和兴趣以及需求,那就需要对网页的内容进行分析和抽取,下面介绍一下用户画像中非常重要的行为标注部分的架构:

用户在浏览一系列网站的过程中是多少会带着一些目的性进行浏览的,即便是没有明确目的,也会带有一些个人喜好,有了这些目的和喜好,就会进一步缩短我们在推送广告过程中对于用户定向的选择难度。上图就是在上下文定向中对网页关键字提取的子系统的架构。【上下文定向】可以通过网页关键字提取,建立一个cache,根据URL建立对应标签,当广告请求到来时,命中相应URL则返回cache的命中内容,如果URL未缓存则返回空集合,同时将URL添加到后台抓取队列,在URL被抓取,并打上标签存入cache,为cache设置TTL,当长期不访问则将该URL的记录清楚,而热点内容URL的关键词是始终被缓存的,运行较长的时间则大多数热点URL大多会被缓存。在抓取到内容之后,需要对网页内容进行内容挖掘,在挖掘的过程中有以下几个方案可以被选取:

网页文本内容通过扩展语境,引入更多文本进行挖掘;利用语义分类树;建立主题模型。

我们在上面提到了在线广告的核心问题其实是找上下文,用户,广告三者之间的最恰当的匹配。

在展示类广告中比较重要的一个核心考核点就是点击率,因此点击率预测模块在DSP中是非常重要的部分

CTR预估涉及到三种角色:受众用户,媒体,广告主

预估的目标是为特定的受众用户再给定的媒体环境下找到最合适的广告,对媒体来说实现收入最大化,即按照eCPM排序的基本原则来排序。

最简单的CTR预估的模型,根据历史日志,统计出三个维度的CTR对照关系,预测过程中,当一个user访问特定url时,查询词典如果存在的CTR,则返回CTR最高的ad,如不存在,则随机返回ad,积累后续数据。

存在问题:基于统计数据,对旧广告效果还可以,但对冷启动的广告没有预测能力。
事实上,我们在线上做点击率预测模型,使用的算法是逻辑回归,后续可能考虑会用到的广告点击率预测方法有:

  1. 机器学习方法:特征 模型 融合方案

  2. 协同过滤方法:看做推荐系统来处理

排序模型以预测结果为基础,广告排序模型有如下几种:

  1. 点排序(point-wise approach):变成分类问题或者回归模型来处理

  2. 对排序(pair-wise approach):比较两个广告谁的优先级高,不分类

  3. 列排序(list-wise approach):对整个广告候选集学习排序模型

广告行业的反作弊

作弊背后必然有一个或者一堆的人从众有获利,比如制造垃圾站挂广告获利的总是扎堆出现的。如果你抓到了一个网站流量异常,在用工具刷量,那肯定不会只是这一个网站在用这个模式在刷量;如果一个人有多个网站,如果有一个网站在刷量,那他的其他网站也应该检查一下了。

在广告反作弊的过程中,为了找出刷量的垃圾站背后都有哪些人,这些人有哪些网站,针对DSP平台流量80%的网站域名去重,通过whois信息查询到域名注册邮箱,归类出哪些域名属于哪个注册邮箱,发现其中一个刷量,则对同一邮箱下的其他域名进行严查。

上图是主要的一些广告反作弊的思路,广告作弊是有成本的,有人作弊,还是背后有利益驱动,找出利益链条是反作弊的关键
下面对之前我们做广告反作弊工作过程中遇到的几类例子:

P2P流量互刷

互刷作弊有代表性的软件是:流量宝和流量精灵

均通过客户端软件向服务器提交互刷任务请求,客户端收到服务器分发的互刷任务后执行隐藏的浏览任务,每天可达到数千个IP的访问量,IP布局分散,UA随机生成,很难通过浏览记录寻找作弊痕迹。现在唯一有效的反作弊方法需要通过蜜罐主机进行跟踪和分析。下面介绍一下我们对于p2p刷量所采用的蜜罐主机的结构:

其中虚线框中是我们的的蜜罐系统,虚线框外面的灰色部分是我们要寻找的作弊目标
如果是对信息安全有一定了解的人对于蜜罐系统一定不陌生,也就是系统设计上有意抛一些破绽出来,让攻击者自己跳出来,通过对攻击者行为的观摩来寻找破解攻击的思路。

由于流量宝、流量精灵一类的刷量工具多集中于windows平台下,安装windows vm并将系统代理指向nginx反向代理,通过刷量工具提交刷量任务。提交刷量任务的站点没有任何真实流量,只要是访问这个站点的IP基本上都是通过刷量工具来的流量,IP可以在RTB引擎对相关IP端进行封杀,不再进行投放;

Nginx反向代理落详细日志通过Logstash收集、解析发送给ElasticSearch建立索引,通过kibana做可视化,统计出刷量最多的IP,域名和URL地址出来,可以作为后续模式识别的模型输入。搜集相关证据,域名可以向adx反馈对媒体进行封杀,同时可以根据筛选出的刷量作弊域名在DSP投放过程中减少投放以避免自身损失。

CPS引流作弊

我们遇到的另外一种对于DSP投放效果有非常大影响的一类作弊手段是:CPS引流作弊

引流作弊可以帮助引流网站“提高”CPC,“提高”CPS。但对广告主不产生实际有效的流量。

目前发现的引流作弊行为有3种:

  1. 作弊代理通过回帖作弊(对媒体网站无控制权)

  2. 作弊代理伙同媒体网站作弊(对媒体网站有控制权)

  3. 作弊代理伙同媒体网站通过网盟作弊

也就是说在DSP投放了广告的网站里被插入了跳转到CPS计费链接的302跳转的图片,虽然DSP花钱从adx买了流量投放了广告,但是这个页面里还有大量的CPS结算的链接跳转,如果广告主既在网盟,又在DSP投放广告的话,任何看过这类页面的人在广告主网站下的单,就有可能被劫持走。整个过程中,用户都不知道有'广告主'的存在。但是对应的'广告主'会认为是特定CPS链接带来了一个点击,后续的cps应该是记在相应的CPS合作方名下。

Q & A

Q1:请问付总dmp数据存哪里?HBase?

数据分不同的形式存在不同的地方,原始日志存放在硬盘上,经过ETL后写入HDFS,结构化存放在Hive表中进行查询,cookiemapping数据经过hadoop计算过后导出成文件,存放在Tair里让RTB查询,用户行为数据存放在hdfs里,画像之后数据存放在redis供rtb查询,跑出来的统计报表存放在mysql供报表系统调用。CM的cookie对应数据有一部分也是存放在hbase的,hbase和hadoop共用hdfs,所以查询速度也会受到hadoop集群资源多少的影响。

Q2:请问 RTB算法模块热插拔大概是怎么实现的?

上面我曾经提到过RTB系统是用Linux C 开发的,如果对于Linux C 比较熟悉的人应该知道Linux下是可以动态加载动态链接库的使用的主要是:

dlopen:打开动态加载库

dlsym:获取接口函数指针

dlcose:关闭库

这三个函数就可以在程序运行时加载动态链接库了。为了达到模块准实时热插拔的目标我们还使用了Linux下的inotify,
inotify是一种文件系统的变化通知机制,如文件增加、删除等事件,可以立刻让用户态得知。我们在RTB程序启动过程中向系统注册了inotify事件来监控配置文件,当配置文件被修改的时候立即通知程序重新加载配置文件

Q3:请问cookiemap是离线map还是实时map?map后数据正确率有多少?移动端map 主要根据那些key来map?

cookieMapping分在线和离线两种,通常情况下广告投放过程中会有几个场景会发起cm

第一种,广告主网站上布码之后当访客访问广告主网站时触发js,dsp会主动向各家对接过后的adx进行cookiemapping

第二种,广告投放过程中,当dsp的出价的同时会带上广告展现代码里面也包含有cm代码,当出价高于其他dsp的时候,广告代码会被吐到媒体网站,相应的也会触发cm

第三种,当在adx消耗金额达到一定水平,像Tanx会按照消耗比例每天向dsp发起一定比例的dsp无法识别用户的cm请求,这个时候dsp也会向其他adx发起cm

除此之外对于运营商数据的使用过程中通常就是离线匹配的了,方法通常是运营商的浏览数据来自于路由设备的DPI信息,里面有用户的adsl账号信息,运营商会找出一定时间内访问过dsp指定的几个域名的人,通常会在这个域名下面的所有页面都布上cm代码,通过http头就能找出dsp的cookieID,找出的这些人都会有adsl账号标识,通过账号就能建立与dsp的cookieID的关系,这类cm就是离线的了。

Q4:请问怎么识别是同一个用户?通过cookie,还是有其他先进的办法?

PC端的用户识别通常是依靠cookie,这类cookie好植入,但生命周期比较短,无法直接跨浏览器/跨设备,同时容易被各类电脑管家/助手清理,所以很容易出现信息苦苦画好的用户画像,过两天这个id就再也不出现了。

在PC端还会用flash cookie的方法来打通不同的浏览器,因为flash storage是同一块存储不同的浏览器可以跨浏览器打通。
当然还有一种叫evercookie的手段集合了包括flash cookie 之内的多种标识方式,感兴趣的可以了解一下这个网址 http://samy.pl/evercookie/

移动端的身份标识,安卓的包括android id,mac地址IMSI和IMEI,而iOS是IDFA。由于移动设备上安装的app里可以嵌入SDK,而app有可能在移动端的权限也不同获取到的标识也会有差异,所以最终也会涉及到用户标识统一识别的问题,当然移动端的用户标识会远比PC端要强很多,移动广告化之后用户画像将会更加的准确。

本文策划 秋翾@百姓网, 内容由国忠,陈刚编辑与发布,其他多位志愿者对本文亦有贡献。读者可以通过搜索“ArchNotes”或长按下面图片,关注“高可用架构”公众号,查看更多架构方面内容,获取通往架构师之路的宝贵经验。转载请注明来自“高可用架构(ArchNotes)”公众号。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/862284
推荐阅读
相关标签
  

闽ICP备14008679号