ad_parser/parser.go
2018-12-19 23:28:02 +08:00

218 lines
7.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package parser
import (
"encoding/json"
"io/ioutil"
"log"
"sync"
"gopkg.in/yaml.v2"
"474420502.top/test/logdb"
)
type Resource struct {
Rawurl string `json:"url"` // 当前采集的素材资源 url 是
Type string `json:"type"`
//当前采集的素材资源类型, 对应值详见 资源类型Resource
//若主要素材资源类型为图片或动图,传 IMAGE
//若主要素材资源类型为 Canvas 动态图片,传 CANVAS
//若主要素材资源类型为视频,传 VIDEO
//若主要素材资源类型为视频流,传 STREAM
//若主要素材资源类型为网页链接或网页字符串,传 HTML
//若主要素材资源类型为压缩文件,传 ZIP
//若主要素材资源类型为原生页面,传 NATIVE
Markup string `json:"markup"` //HTML 素材资源的网页字符串 或 Native 素材资源的相关数据 否
}
// Advertiser 广告商
type Advertiser struct {
Name string `json:"name"` //广告商名称
// 后续根据推广目的,类型请看 推广目的Promotional Purpose
// 若是应用推广,广告数据有则上报,若没有后续根据应用商店匹配获取
// 若是活动推广,广告数据有则上报,若没有后续根据推广域名匹配获取
// 若是商品推广,后续根据推广域名匹配获取
// 若是公众号推广,根据原始 ID 抓取上报
Logo string `json:"logo"` // 广告商 Logo 否
// 后续根据推广目的,类型请看 推广目的Promotional Purpose
// 若是应用推广,广告数据有则上报,否则不用上报
// 若是活动推广,广告数据有则上报,否则不用上报
// 若是商品推广,广告数据有则上报,否则不用上报
// 若是公众号推广,根据原始 ID 抓取上报
BrandName string `json:"brand_name"` // 广告商品牌名
BrandLogo string `json:"brand_logo"` // 广告商品牌logo
}
type DeviceInfo struct {
IDFA string `json:"idfa"` // iOS 设备的 IDFA 是 iOS 设备时,获取 IDFA 作为设备 ID
IMEI string `json:"imei"` // Android 设备的 IMEI 是 Android 设备时,获取 IMEI 作为设备 ID
IP string `json:"ip"` //采集广告设备使用的对外 IP 地址 是
Area string `json:"area"` // 采集广告时所在地区的cc字段详见agconstants库的area表 是 新数据需要加入地区信息,旧数据地区信息为广州地区
}
type SectionInfo struct {
SID string `json:"sid"` // 频道栏目 ID对应值详见 频道栏目Sections
CID string `json:"cid"` // 视频节目 ID 否
}
// Schedule 广告投放时间表
type Schedule struct {
BeginTime string `json:"beginTime"` // 广告投放开始时间,格式 yyyy-MM-dd HH:mm:ss 否
EndTime string `json:"endTime"` // 广告投放结束时间,格式 yyyy-MM-dd HH:mm:ss 否
DayDisplay int `json:"dayDisplay"` // 广告一天内允许展示量 否
}
type ADParser struct {
ID string `json:"id"` // 采集广告所在广告平台的广告 ID唯一标识 是 使用字符串,预防出现某个流量平台的 adId 为非整型数字
Platform string `json:"platform"` // 推广设备平台,详见 设备平台Platforms 是 "Android" 或者 "iOS" 或者 "OTT"
Channel int `json:"channel"` //采集广告所在的流量渠道/流量平台,对应值详见 流量平台Channels
Media int `json:"media"` //采集广告媒体在数据库的标识 ID对应值详见 广告媒体Medias
Position int `json:"position,omitempty"` //采集广告所在流量平台的广告位置,对应值详见 投放规格 否 预留
Format []int `json:"format"` //采集广告的广告形式,对应值详见 广告展现形式Ad Formats 是 [106, 303],可多种广告形式
MaterialType int `json:"materialType"` //采集广告的素材类型,对应值详见 素材类型Material Types
Icon string `json:"icon,omitempty"` //采集广告的图标 url 否
Slogan string `json:"slogan,omitempty"` //采集广告的广告语 否 有可能是图片
Desc string `json:"desc,omitempty"` //采集广告的广告描述 否
Resources []Resource `json:"resources"` //采集广告的素材资源 是 素材资源会根据 materialType 素材类型相应处理
Advertiser Advertiser `json:"advertiser,omitempty"`
Purpose int `json:"purpose"` // 采集广告的推广目标/类型,对应值详见 推广目的Promotional Purpose 是 无法判断时,默认活动推广
RedirectURL string `json:"redirectUrl,omitempty"` // 采集广告的跳转/推广链接 否 帐号推广不一定有推广链接,其他基本都有
RedirectType int `json:"redirectType,omitempty"`
// 采集广告的推广链接类型,详见 推广目的Promotional Purpose
// 当推广链接类型是网页地址时值为0
// 当推广链接类型是应用下载地址APK 或 应用商店详情页,详见 应用商店白名单值为1
// 当推广链接类型是商品购买页(商平台商品购买页,相见 电商平台白名单值为2
// 当推广链接类型是 URI 地址值为4不过一般已经被过滤
// 当推广链接类型是社交账号关注页或活动页值为8
// 当推广链接类型是原生推广页值为16
Ext string `json:"ext,omitempty"`
DeviceInfo DeviceInfo `json:"deviceInfo"`
SectionInfo SectionInfo `json:"sectionInfo,omitempty"`
}
// ToJSON 返回序列化的json格式
func (adp *ADParser) ToJSON() ([]byte, error) {
data, err := json.Marshal(adp)
if err != nil {
return nil, err
}
return data, nil
}
// IParser 要实现的解析接口
type IParser interface {
ToDoParser(adstring string) (string, error)
GetSpiderID() int
GetLogDB() *logdb.LogDB
GetQueue() *Queue
}
type Parser struct {
que *Queue
db *logdb.LogDB
IParser
}
// ConfigLogDB 加载LogDB配置
func (p *Parser) ConfigLogDB(yamlpath string) {
p.db = logdb.New(yamlpath)
p.db.Ping()
}
// ConfigQueue 加载队列MQ配置
func (p *Parser) ConfigQueue(yamlpath string) {
p.que = &Queue{}
data, err := ioutil.ReadFile(yamlpath)
if err != nil {
panic(err)
}
err = yaml.Unmarshal(data, p.que)
if err != nil {
panic(err)
}
if err := p.que.Connect(); err != nil {
panic(err)
}
}
func (p *Parser) GetLogDB() *logdb.LogDB {
return p.db
}
func (p *Parser) GetQueue() *Queue {
return p.que
}
// ADParserServer 主入口循环
func ADParserServer(adp IParser) {
adresponse := adp.GetLogDB().ADParserSelect(adp.GetSpiderID()) // select from db
adrChan := make(chan logdb.ADResonse, 100)
wg := new(sync.WaitGroup)
for i := 0; i <= 10; i++ {
wg.Add(1)
go parserAndSendMQ(adp, adrChan, wg)
}
for _, adr := range adresponse {
adrChan <- adr
}
close(adrChan)
wg.Wait()
}
func parserAndSendMQ(adp IParser, adrChan chan logdb.ADResonse, wg *sync.WaitGroup) {
defer wg.Done()
for adr := range adrChan {
pjson, err := adp.ToDoParser(adr.Response)
if err != nil {
log.Println("uid:", adr.UID, "err:", err)
adp.GetLogDB().ADError(adr.UID, err.Error())
continue
}
// send pjson to mq
// update UID status finish
que := adp.GetQueue()
err = que.Push([]byte(pjson))
if err != nil {
log.Println("uid:", adr.UID, "err:", err)
adp.GetLogDB().ADError(adr.UID, err.Error())
continue
}
adp.GetLogDB().ADParserSuccess(adr.UID, pjson)
}
}
// NewADParser 创建一个ADParser的类, 包含很多传到终端的所有结构
func NewADParser(SpiderID int) *ADParser {
adp := &ADParser{}
adp.Resources = make([]Resource, 0)
adp.Format = make([]int, 0)
return adp
}