2018-12-18 10:45:04 +00:00
|
|
|
|
package parser
|
|
|
|
|
|
2018-12-18 17:49:23 +00:00
|
|
|
|
import (
|
2018-12-19 09:51:39 +00:00
|
|
|
|
"encoding/json"
|
|
|
|
|
"io/ioutil"
|
2018-12-18 17:49:23 +00:00
|
|
|
|
"log"
|
2018-12-19 10:55:10 +00:00
|
|
|
|
"sync"
|
2018-12-18 17:49:23 +00:00
|
|
|
|
|
2018-12-19 09:51:39 +00:00
|
|
|
|
"gopkg.in/yaml.v2"
|
|
|
|
|
|
2018-12-18 17:49:23 +00:00
|
|
|
|
"474420502.top/test/logdb"
|
|
|
|
|
)
|
|
|
|
|
|
2018-12-18 10:45:04 +00:00
|
|
|
|
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"`
|
2018-12-19 09:51:39 +00:00
|
|
|
|
}
|
2018-12-18 17:49:23 +00:00
|
|
|
|
|
2018-12-19 09:51:39 +00:00
|
|
|
|
// ToJSON 返回序列化的json格式
|
|
|
|
|
func (adp *ADParser) ToJSON() ([]byte, error) {
|
|
|
|
|
data, err := json.Marshal(adp)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return data, nil
|
2018-12-18 17:49:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IParser 要实现的解析接口
|
|
|
|
|
type IParser interface {
|
2018-12-19 09:51:39 +00:00
|
|
|
|
ToDoParser(adstring string) (string, error)
|
2018-12-18 17:49:23 +00:00
|
|
|
|
GetSpiderID() int
|
2018-12-19 09:51:39 +00:00
|
|
|
|
GetLogDB() *logdb.LogDB
|
|
|
|
|
GetQueue() *Queue
|
2018-12-18 17:49:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-19 09:51:39 +00:00
|
|
|
|
type Parser struct {
|
|
|
|
|
que *Queue
|
|
|
|
|
db *logdb.LogDB
|
|
|
|
|
IParser
|
2018-12-18 17:49:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-19 09:51:39 +00:00
|
|
|
|
// ConfigLogDB 加载LogDB配置
|
|
|
|
|
func (p *Parser) ConfigLogDB(yamlpath string) {
|
|
|
|
|
p.db = logdb.New(yamlpath)
|
|
|
|
|
p.db.Ping()
|
|
|
|
|
}
|
2018-12-18 17:49:23 +00:00
|
|
|
|
|
2018-12-19 09:51:39 +00:00
|
|
|
|
// ConfigQueue 加载队列MQ配置
|
|
|
|
|
func (p *Parser) ConfigQueue(yamlpath string) {
|
|
|
|
|
p.que = &Queue{}
|
|
|
|
|
data, err := ioutil.ReadFile(yamlpath)
|
|
|
|
|
if err != nil {
|
|
|
|
|
panic(err)
|
2018-12-18 17:49:23 +00:00
|
|
|
|
}
|
2018-12-19 10:20:03 +00:00
|
|
|
|
|
2018-12-19 10:22:40 +00:00
|
|
|
|
err = yaml.Unmarshal(data, p.que)
|
2018-12-19 09:51:39 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
panic(err)
|
|
|
|
|
}
|
2018-12-19 10:17:30 +00:00
|
|
|
|
|
|
|
|
|
if err := p.que.Connect(); err != nil {
|
|
|
|
|
panic(err)
|
|
|
|
|
}
|
2018-12-18 17:49:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-19 09:51:39 +00:00
|
|
|
|
func (p *Parser) GetLogDB() *logdb.LogDB {
|
|
|
|
|
return p.db
|
|
|
|
|
}
|
2018-12-18 17:49:23 +00:00
|
|
|
|
|
2018-12-19 09:51:39 +00:00
|
|
|
|
func (p *Parser) GetQueue() *Queue {
|
|
|
|
|
return p.que
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-19 10:55:10 +00:00
|
|
|
|
// ADParserServer 主入口循环
|
2018-12-19 09:51:39 +00:00
|
|
|
|
func ADParserServer(adp IParser) {
|
2018-12-19 10:55:10 +00:00
|
|
|
|
|
2018-12-19 15:28:02 +00:00
|
|
|
|
adresponse := adp.GetLogDB().ADParserSelect(adp.GetSpiderID()) // select from db
|
|
|
|
|
adrChan := make(chan logdb.ADResonse, 100)
|
|
|
|
|
|
2018-12-19 10:55:10 +00:00
|
|
|
|
wg := new(sync.WaitGroup)
|
|
|
|
|
|
2018-12-19 15:28:02 +00:00
|
|
|
|
for i := 0; i <= 10; i++ {
|
2018-12-19 10:55:10 +00:00
|
|
|
|
wg.Add(1)
|
2018-12-19 15:28:02 +00:00
|
|
|
|
go parserAndSendMQ(adp, adrChan, wg)
|
2018-12-19 10:55:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-19 09:51:39 +00:00
|
|
|
|
for _, adr := range adresponse {
|
2018-12-19 15:28:02 +00:00
|
|
|
|
adrChan <- adr
|
2018-12-19 09:51:39 +00:00
|
|
|
|
}
|
2018-12-19 15:28:02 +00:00
|
|
|
|
|
|
|
|
|
close(adrChan)
|
|
|
|
|
wg.Wait()
|
2018-12-19 09:51:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-19 15:28:02 +00:00
|
|
|
|
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)
|
2018-12-19 09:51:39 +00:00
|
|
|
|
}
|
2018-12-18 10:45:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-19 10:55:10 +00:00
|
|
|
|
// NewADParser 创建一个ADParser的类, 包含很多传到终端的所有结构
|
2018-12-18 17:49:23 +00:00
|
|
|
|
func NewADParser(SpiderID int) *ADParser {
|
2018-12-18 10:45:04 +00:00
|
|
|
|
adp := &ADParser{}
|
|
|
|
|
adp.Resources = make([]Resource, 0)
|
|
|
|
|
adp.Format = make([]int, 0)
|
|
|
|
|
return adp
|
|
|
|
|
}
|