一、达观智能推荐概述
达观数据为应用方提供了功能强大、使用灵活的智能推荐服务,能够有效的提升用户粘性,促进各种业务指标的提升。达观智能推荐服务采用简单易用的HTTP接口,供应用方调用获取推荐结果在网站、APP等终端上展示。目前,达观智能推荐系统提供三种类型的推荐服务:
1、个性化推荐:为每个用户定制的推荐结果,常以“推荐”、“猜你喜欢”、“发现”等形式出现,根据每个用户的兴趣喜好量身定制,达到“千人千面”的效果,一般放在首页。
2、相关推荐:根据当前所浏览的内容,定制相关内容,常以“相关推荐”、“看了还看”、“买了还买”等形式出现,每个用户看到的结果基本上一样,一般放在内容详情页。
3、热门推荐:基于上报的各种数据进行计算,得到的排行榜,支持全局排行以及分类排行等,常以“热点”等形式出现,每个人看到的结果基本一样,位置不限。
同时这三项功能,在达观数据后台系统上也提供了详细的推荐配置和数据统计功能,以充分掌握推荐服务的运行状态。如下分别是业界主流的个性化推荐、相关推荐、热门推荐的展示样式。
二、接入步骤
1、开通账号
1.1、填写申请表方式
点击链接填写免费试用申请表或屏幕上方菜单栏申请试用
进入申请试用表填写页面,我们业务人员会根据您填写的信息,在48小时内跟您联系,确定需求、达成初步合作意向后为您开通账号。
1.2、主动联系方式
点击屏幕右侧的在线咨询
或电话咨询(400 175 9889)
与我们取得联系,业务人员会在与您确定需求、达成初步合作意向后为您开通账号。
2、访问设置
appid和appname是联系达观后自动分配的
,可以用于调用数据上报接口和推荐接口进行参数设置以进行服务校验。IP白名单
用于在调用达观接口时进行IP验证以确保是合法调用。
3、上报数据
3.1、数据格式说明
达观数据预先定义了2个数据表(物品信息表和用户行为数据表)供推荐服务使用,以下给出每个表格的字段定义,以及取值的格式,请严格按照以下规定进行数据上报。如果上报的数据字段和数据表的字段含义不一致,请务必按照本文档规定的字段名进行上报,否则可能会影响推荐服务的效果。
3.1.1、item(物品信息表)
用于存放所有可被推荐的物品信息数据,一切可被推荐的对象统称为物品,在电商行业中物品表示商品,在视频行业中物品表示视频,在直播行业中物品表示主播,媒体行业中表示文章等。在此表中的物品,都默认是可被推荐的,也是所有推荐结果的原始候选集合。
3.1.1.1、表结构
参数 | 类型 | 必需 | 描述 |
---|---|---|---|
itemid | string | 是 | item的唯一id |
cateid | string | 有则上报,有助于提升推荐效果 | item所属分类,多级分类用“_”进行分隔 。如:“1_2”,表示一级分类为1,二级分类为2。如果同时属于多个分类,用英文分号“;”分隔 ,如:“1_2;3_1” |
score | int | 有则上报,有助于提升推荐效果 | item的质量分,0~1000的整数。值越大,被推荐出来的可能性越大 |
title | string | 有则上报,有助于提升推荐效果 | item的标题 |
content | string | 否 | 正文,比如帖子或新闻的正文 |
price | int | 有则上报,有助于提升推荐效果 | item的价格,单位为分 |
item_tags | string | 有则上报,有助于提升推荐效果 | item的标签信息,多个标签以英文分号“;”分割 。如“变形金钢5;擎天柱;大黄蜂”,item_tags一般是一组主题关键词。 |
item_modify_time | int | 有则上报,有助于提升推荐效果,同时可以控制推荐结果的时效性 | item最新修改时间,unix时间戳,精确到秒 。上报该字段可以提高推荐的时效性 。 |
dg_start_time | int | 否 | item开始推荐的时间,unix时间戳,精确到秒 。有值的话,没到此时间则不能被推荐出来。无值的话,开始推荐的时间不受限制 |
dg_end_time | int | 否 | item结束推荐的时间,unix时间戳,精确到秒 。有值的话,超过此时间则不能被推荐出来。无值的话,结束推荐的时间不受限制 |
publisher | string | 有则上报,有助于提升推荐效果 | item的上传者信息,如可以对应视频或者文章的发布者、小说的作者等 |
province | string | 如果有地域相关需求,有则上报 | item所属的地域信息,这里指省级地域,如江苏省、广东省等 |
city | string | 如果有地域相关需求,有则上报 | item所属的地域信息,这里指市级地域,如苏州市、杭州市等 |
其他 | string | 否 | 其他字段也可以进行上报,如果有时间字段,需要采用unix时间戳(精确到秒)。自定义字段不能和达观的已有字段重复 |
3.1.1.2、注意事项
1)item_modify_time、dg_start_time、dg_end_time必须是秒级的时间戳,不是毫秒
2)cateid不要错写成cate
3)cateid和item_tags必须使用英文分号分隔,不能用逗号或者其它
3.1.1.3、行业item表字段demo
这里列出几个行业的需要上报的item表常用字段以供参考。
短视频行业
上报字段 | 对应含义 |
---|---|
itemid | 视频id,如 “55036952” |
title | 视频标题,如 “【硬核科普】HPV疫苗是如何保护宫颈的” |
cateid | 视频分类, 如 “健康” |
duration | 视频时长,单位为秒,如 15 |
item_tags | 视频标签,如 “科普;疫苗;HPV” |
item_modify_time | 视频最新修改时间,如 1512015208 |
create_time | 视频创建时间,如 1499082274 |
publisher | 视频上传者,如 “u12isa809” |
长视频行业
上报字段 | 对应含义 |
---|---|
itemid | 剧目id,如 “tele_vip_1581258” |
title | 剧目标题,如 “生活大爆炸第一季” |
cateid | 剧目分类, 如 “电视剧” |
item_tags | 剧目标签,如 “喜剧;现代” |
duration | 剧目时长,剧集可以取平均时长,如 5052 |
item_modify_time | 剧目上线时间,如 1499082274 |
publisher | 剧目上传者,如 “u12isa809” |
video_count | 该剧目一共有多少集,如 20 |
series_count | 完整剧目一共有多少季,如 3 |
电商行业
上报字段 | 对应含义 |
---|---|
itemid | 商品id,如 “iakaamc1e3” |
title | 商品标题,如 “SK-II 微肌因赋活修护精华霜 50ml” |
cateid | 商品分类, 如 “217_220_424” |
item_tags | 商品标签,如 “SK-II;保湿;补水;抗衰老;小红瓶;精华露” |
item_modify_time | 商品最新修改时间,如 1515411180 |
price | 商品价格,如 130390 |
origin_price | 商品原价,如 15500 |
spu_id | spu维度的id,如 “g1_7688g” |
pub_time | 商品上架时间,如 1515411180 |
detail_pic_num | 商品图片数量,如 8 |
free_shipping | 商品是否包邮,可以是1:包邮 2:不包邮 3:满足条件包邮,如 “1” |
sale_number | 商品累计销量,如 1008 |
shipping_money | 商品运费,如 500 |
shop_id | 商品所属店铺id(如有),如 “tb202201001” |
source_id | 商品来源类型,如“自营” |
媒体行业
上报字段 | 对应含义 |
---|---|
itemid | 文章id,如 “389012785” |
title | 文章标题,如 “增强学习丰富运动行为 DeepMind教AI学习跑酷” |
cateid | 文章分类, 如 “科技” |
item_tags | 文章标签,如 “增强学习;人工智能;DeepMind;AI;跑酷” |
item_modify_time | 文章最新修改时间,如 1499762643 |
publisher | 文章上传者,如 “w091Mac” |
网络小说行业
上报字段 | 对应含义 |
---|---|
itemid | 小说id,如 “8091635” |
title | 小说标题,如 “绝世武林之至尊天下” |
cateid | 小说分类, 如 “仙侠” |
item_tags | 小说标签,如 “爽文;修炼;热血;异世” |
item_modify_time | 小说最新修改时间,如 1512015208 |
publisher | 小说作者,如 “mc89Jars2” |
内容社区行业
上报字段 | 对应含义 |
---|---|
itemid | 内容id,如 “8091635” |
title | 内容的标题,如 “ootd|一周穿搭不重样” |
cateid | 内容分类, 如 “图文” |
item_tags | 内容标签,如 “夏日穿搭;牛仔裤;ootd” |
create_time | 内容创建时间,如 1512015208 |
item_modify_time | 内容最新修改时间,如 1512015208 |
publisher | 内容发布者,如 “mc89Jars2” |
doc_type | 内容类型,如 “video” |
source_id | 内容来源类型,如 “签约作者” |
3.1.2、user_action(用户行为数据表)
用于存放用户行为数据,这部分数据对推荐效果有极大影响,需要按照预定的格式上报,并且最好做到实时上报
。
3.1.2.1、表结构
参数 | 类型 | 必需 | 描述 |
---|---|---|---|
userid | string | 有则上报,否则对推荐结果有负面影响 | 用户登陆后的id |
imei | string | 有则上报,否则对推荐结果有负面影响 | 用户的手机IMEI号 |
cid | string | 有则上报,否则对推荐结果有负面影响 | 用户的cookieid,(userid、imei、cid不能全部为空,否则会对推荐效果有负面影响) |
itemid | string | 除了搜索行为之外,此字段不能为空 | 对应item表的itemid |
action_type | string | 是 |
用户对item的具体行为,必须是有意义的字符串,上报用户对达观推荐结果的点击请填“rec_click”,用于统计推荐点击率及推荐效果优化 |
action_num | int | 否 | 行为数量。对于购买行为,可以是购买数量 |
action_detail | string | 否 | 该行为的一些描述信息,该字段可以自行定义,比如登录的话,可以是qq登录或者微信登录,发送短信可以是短信发送成功或者失败等等。在达观数据后台系统会对这些数据进行汇总,以英文分号进行分隔 |
scene_type | string | 否 | 场景类型,用于标识不同的场景,常用的包括pc_home(PC首页个性推荐),android_detail(安卓详情页个性化推荐)等。不在上述中的可以自行添加 |
device_type | string | 否 | 设备类型,用于表示不同设备型号,常见的包括ios_13pro、huawei_mate40pro等 |
timestamp | timestamp | 否 | 行为发生的时间,unix时间戳,精确到秒 ,没有传则置为收到请求的时间 |
rec_requestid | string | 否 | 如果此条行为是由达观推荐带来的,则此字段对应调达观推荐接口返回itemid所带的request_id |
type | string | action_type是search或dislike或follow或unfollow 的话,有则需要上报该字段 |
对于search,该值支持type="cate"(类别);对于dislike,该值可以是"cate"、"publisher"、"item";对于follow、unfollow,该值支持type="publisher" |
value | string | action_type是search或是dislike 的话,有则需要上报该字段 |
该字段配合着type字段进行上报 ,type目前支持cate、publisher、item。如果type是publisher,则value对应的是publisher id,多个的话以英文分号分隔,如”100;101″;如果type是item,则value对应的是itemid。如果type是cate,则value对应的是类目id,多个类目的话以英文分号分隔,如1_1;1_2,另外,action_type为search,表示在1_1,1_2类目下有搜索行为,action_type为dislike,表示不喜欢类目1_1,1_2 |
keyword | string | action_type是search ,则需要上报该字段 |
表示用户所搜索的内容 |
其他 | string | 否 | 其他字段也可以进行上报,如果有时间字段,需要采用unix时间戳(精确到秒)。自定义字段不能和达观的已有字段重复 |
3.1.2.2、常用action_type
action_type | 含义 |
---|---|
view | 点击进入物品详情页。对于资讯,表示进入资讯阅读页面;对于短视频,表示进入播放页;对于直播,表示进入直播间;对于小说,表示进入书籍详情页等等 |
reading | 阅读,仅对小说类场景使用,表示进入章节阅读页面 |
play | 播放,一般对于视频类场景使用,表示对视频进行播放。为了提升效果,建议在上报play行为的时候也上报下play_time和play_integrity字段,分别表示播放时长和播放完成度,后者取值范围为0到1。 |
rec_click | 点击达观推荐结果,此时最好将此次推荐结果对应的request_id上报到user_action的rec_requestid中 |
rec_show | 用户浏览过达观推荐结果,此时最好将此次推荐结果对应的request_id上报到user_action的rec_requestid中。主要标示用户浏览了哪些推荐结果 |
collect | 收藏 |
subscribe | 订阅 |
comment | 评论 |
gift | 送礼物 |
share | 分享 |
like | 点赞 |
dislike | 取消点赞或不喜欢 |
cart | 加入购物车或加入书架 |
buy | 购买 |
search | 搜索 |
follow | 关注 |
unfollow | 取消关注 |
上面4个图,从左到右分表表示:
1)请求达观推荐结果,得到推荐的10个itemid及request_id;
2)用户在APP上通过下拉刷新看到了新的推荐结果,由于屏幕大小限制,一屏只能到10条推荐结果中的4条;
3)虽然用户看到了4条,但是用户对第3条感兴趣点,就点击进入了文章详情页查看详细内容;
4)用户看完这篇文章觉得很好,就进行了收藏(图4中右下方红圈所示)。
接着,用户没有看后面的6条,又开始了新一次的“下拉”刷新请求新的推荐结果。
整个过程,所需要上报的用户行为如下:
1)上报4条“rec_show”,并带上rec_requestid
。解释:虽然一次请求了10条,但是用户看到了前面4条,后面6条并没有看到。这个数据要看是否可以采集,如果采集就上报,这样的话我们就知道用户只看了10条中的4条。rec_requestid对应我们推荐接口返回的request_id。
2)上报1条“view”
。解释:用户点击了第3条推荐结果进入了文章详情页。
3)上报1条“rec_click,并带上rec_requestid”
。解释:用户点击了第3条推荐结果进入了文章详情页,同时这条推荐结果又是来自达观推荐接口返回的。rec_requestid对应我们推荐接口返回的request_id。
4)上报1条“collect”
。解释:用户收藏里第3篇文章。
3.1.2.3、注意事项
1)上报非搜索行为时,上报的itemid不能为空
2)userid、 imei 、cid三个用户id至少有一个不能为空,为了得到更好的推荐效果,强烈建议三者都上报
3)timestamp必须是秒级的时间戳,不是毫秒
4)action_type必须是有意义的字符串,如果用户的行为是上面表格所列的,请按照表格规定进行上报
3.1.2.4、行业user_action表action_type字段demo
这里列出几个行业的需要上报的user_action表中action_type的常见取值以供参考。
媒体行业
上报字段 | 对应含义 |
---|---|
view | 进入文章详情页 |
rec_click | 点击达观推荐结果 |
collect | 收藏文章 |
comment | 评论文章 |
share | 分享文章 |
like | 对文章点赞 |
视频行业
上报字段 | 对应含义 |
---|---|
view | 进入视频详情页 |
play | 播放视频 |
rec_click | 点击达观推荐结果 |
collect | 收藏视频 |
comment | 评论视频 |
share | 分享视频 |
like | 对视频点赞 |
电商行业
上报字段 | 对应含义 |
---|---|
view | 进入商品详情页 |
rec_click | 点击达观推荐结果 |
collect | 收藏商品 |
comment | 评论商品 |
share | 分享商品 |
cart | 把商品加入购物车 |
buy | 购买商品 |
网络小说行业
上报字段 | 对应含义 |
---|---|
view | 进入书籍详情页 |
reading | 进入章节阅读页面 |
rec_click | 点击达观推荐结果 |
subscribe | 订阅书籍 |
collect | 收藏书籍 |
comment | 评论书籍 |
share | 分享书籍 |
like | 对书籍点赞 |
cart | 把书籍加入书架 |
3.1.3、user(用户信息表)
用于存放用户的属性信息数据。`
3.1.3.1、表结构
参数 | 类型 | 必需 | 描述 |
---|---|---|---|
userid | string | 是 | 用户的唯一id |
user_tags | string | 否 | 用户的标签列表,多个标签以英文分号“;”分隔,例如“经典;美观;科学” |
tel | string | 否 | 用户的手机号 |
nick_name | string | 否 | 用户的昵称 |
string | 否 | 用户的邮箱 | |
birthday | string | 否 | 用户的生日日期,格式建议采用“19901123”(生日为1990年11月23日) |
sex | int | 否 | 用户的性别,值为1表示是男性,值为2表示女性,值为0表示未知 |
city | string | 否 | 用户所在城市,例如“杭州” |
province | string | 否 | 用户所在省份,例如“浙江” |
register_time | int | 否 | 用户注册时间戳 |
id_type | int | 否 | id类型,例如“微信/手机/邮箱” |
user_type | int | 否 | 用户类型,例如“1:登陆用户 2:访客” |
source | string | 否 | 用户来源,例如“新浪微博” |
content | string | 否 | 用户描述 |
其他 | string | 否 | 其他字段也可以进行上报,如果有时间字段,需要采用unix时间戳(精确到秒)。自定义字段不能和达观的已有字段重复 |
3.2、上报数据的接口列表
3.2.1、接口描述
上报数据的统一接口,物品信息数据、用户行为数据和用户属性数据都是通过该接口进行上报。接入达观推荐服务首先需要完成数据上报
。
3.2.2 URL
http://datareportapi.datagrand.com/data/YOUR_APP_NAME
* 注:YOUR_APP_NAME
请填您的达观账号名。
3.2.3、Http Method
POST
3.2.4、Http 返回格式
JSON
3.2.5、Http 请求参数
参数 | 类型 | 是否必需 | 描述 |
---|---|---|---|
appid | int | 是 | 您的达观账号对应的id |
table_name | string | 是 | 要上传数据的表名 |
table_content | string | 是 | 上报的数据内容,JSON格式 |
3.2.6、请求参数详细说明
3.2.6.1、table_name
table_name字段表明数据所要上传到的表格。使用推荐服务只需要上报以下2个表的数据: item
、user_action
,table_name字段 需要是以下表格给出的值
。请对照数据表各个字段的含义,准确地上报数据。
table_name | 含义 |
---|---|
item | 物品信息表 |
user_action | 用户行为数据表 |
user | 用户属性信息表 |
3.2.6.2、table_content
table_content字段的值对应的是上报的数据内容,必须是UTF8编码
。
支持批量上报,即一次请求上报多条数据,因此table_content是一个列表(list)的JSON字符串
。
table_content列表的每一个元素是一个字典(dict)
,每个dict必须包含“cmd”和“fields”两个字段
,“fields”包含数据记录的具体内容,“cmd”是对记录的操作。
(1)cmd可能的取值和定义如下:
cmd | 含义 |
---|---|
add | 新增或更新一条记录,如果主键对应的记录已经存在,则对该记录做更新操作 |
delete | 删除一条记录,如果主键对应的记录不存在,则认为删除成功,user_action表不支持delete操作 |
refresh_all | 批量下线item数据,仅对item表有效 |
(2)fields 字段的值为一个词典(dict),是具体上报的数据内容,请将您所要上报的字段及相应的值构建成词典,比如 { “itemid”: “28394556”, “cateid”: “9_2_1”, “score”: 459, “title”: “天穿修炼记最新版”, “item_tags”: “修仙”}。
*注:根据上报的table_name的不同,fields 应包含不同的字段,详见后文“上报数据表详细说明”。
3.2.7 Http 返回结果说明
参数 | 类型 | 描述 |
---|---|---|
status | string | 执行结果,OK为成功。FAIL为失败,数据不会入库。WARN为有部分非重要字段异常,数据会正常入库,但请根据返回错误信息进行排查。 |
errors | string | 错误信息 |
request_id | string | 该条上报记录的序号,仅用于排查问题使用 |
3.2.8、数据上报示例
3.2.8.1、item表上报
CURL调用示例
Content-Type: multipart/form-data方式:
1 2 |
curl -i -X POST -d 'appid=YOUR_APP_ID&table_name=item&table_content=[{"cmd":"add", "fields": { "itemid": "28394556", "cateid": "9_2_1", "score": 459, "title": "天穿修炼记最新版", "item_tags": "修仙"}}, {"cmd":"add", "fields": { "itemid": "28394557", "cateid": "9_2_1", "score": 434, "title": "比利林恩的中场战事", "item_tags": "战争"}}]' 'http://datareportapi.datagrand.com/data/YOUR_APP_NAME' |
Content-Type: application/json方式:
1 2 |
curl -i -X POST -H "Content-Type: application/json" -d '{"appid":YOUR_APP_ID, "table_name" : "item", "table_content": [{"cmd":"add", "fields": {"itemid": "28394556", "cateid": "9_2_1", "score": 459, "title": "天穿修炼记最新版", "item_tags": "修仙"}}, {"cmd":"add", "fields": { "itemid": "28394557", "cateid": "9_2_1", "score": 434, "title": "比利林恩的中场战事", "item_tags": "战争"}}]}' 'http://datareportapi.datagrand.com/data/YOUR_APP_NAME' |
refresh_all调用示例
注意:
1. refresh_all命令需要在fields中填all_itemid,all_itemid是所有要保持在线
的itemid构成的list,refresh_all会把不在all_itemid中的所有item
都下线,请谨慎使用!
2. all_itemid必须传多于100个itemid
1 2 |
curl -i -X POST -d 'appid=YOUR_APP_ID&table_name=item&table_content=[{"cmd":"refresh_all", "fields": {"all_itemid": ["28394556","23423423"]}}]' 'http://datareportapi.datagrand.com/data/YOUR_APP_NAME' |
成功返回示例:
1 2 3 4 5 |
{ "status":"OK", "receiver_id":"1523877252047365" } |
错误返回示例:
1 2 3 4 5 6 7 8 9 |
{ "status":"FAIL", "errors":{ "code":1012, "message":"table does not exist" }, "receiver_id":"1523877252347365" } |
警告返回示例:
1 2 3 4 5 6 7 8 9 |
{ "status":"WARN", "errors":{ "code":8012, "message":"sex value is incorrect" }, "receiver_id":"1523877252347361" } |
3.2.8.2、user_action表上报
CURL调用示例
Content-Type: multipart/form-data方式:
1 2 |
curl -i -X POST -d 'appid=YOUR_APP_ID&table_name=user_action&table_content=[{"cmd":"add", "fields":{"timestamp":1489040079, "action_type":"view", "userid": "1234", "itemid": "abc12"}}]' 'http://datareportapi.datagrand.com/data/YOUR_APP_NAME' |
Content-Type: application/json方式:
1 2 |
curl -i -X POST -H "Content-Type: application/json" -d '{"appid":YOUR_APP_ID, "table_name" : "user_action", "table_content": [{"cmd":"add", "fields":{"timestamp":1489040079, "action_type":"view", "userid": "1234", "itemid": "abc12"}}]}' 'http://datareportapi.datagrand.com/data/YOUR_APP_NAME' |
3.2.8.3、HTTP请求,JAVA示例代码
1)、普通方式上传
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
package com.datagrand.datareport.test; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.NameValuePair; import org.apache.http.StatusLine; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.GzipDecompressingEntity; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.util.EntityUtils; @SuppressWarnings("deprecation") public class TestHttp{ @SuppressWarnings("resource") public String post(String reqURL, Map<String, String> params) throws ClientProtocolException, IOException{ String responseContent = ""; HttpPost httpPost = new HttpPost(reqURL); if (params != null) { List nvps = new ArrayList(); Set<Entry<String, String>> paramEntrys = params.entrySet(); for (Entry<String, String> entry : paramEntrys) { nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); } httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8")); } httpPost.setHeader("User-Agent", "datagrand/datareport/java sdk v1.0.0"); httpPost.setHeader("Content-Type","application/x-www-form-urlencoded"); HttpClient httpClient = new DefaultHttpClient(); HttpParams httpParams = httpClient.getParams(); HttpConnectionParams.setSoTimeout(httpParams, 60*1000); HttpConnectionParams.setConnectionTimeout(httpParams, 60*1000); HttpResponse response = httpClient.execute(httpPost); StatusLine status = response.getStatusLine(); if (status.getStatusCode() >= HttpStatus.SC_MULTIPLE_CHOICES) { System.out.printf( "Did not receive successful HTTP response: status code = {}, status message = {}", status.getStatusCode(), status.getReasonPhrase()); httpPost.abort(); } HttpEntity entity = response.getEntity(); if (entity != null) { responseContent = EntityUtils.toString(entity, "utf-8"); EntityUtils.consume(entity); } else { System.out.printf("Http entity is null! request url is {},response status is {}", reqURL, response.getStatusLine()); } return responseContent; } public static void main(String[] args){ TestHttp obj = new TestHttp(); Map<String,String> params = new HashMap<String,String>(); params.put("appid", "237389"); params.put("table_name", "item"); String table_content = "[{\"cmd\":\"add\",\"fields\":{\"itemid\":\"10001\"}}]"; params.put("table_content", table_content); String res; try { res = obj.post("http://datareportapi.datagrand.com/data/your_app_name", params); System.out.println(res); } catch (Exception e) { e.printStackTrace(); } } } |
2)gzip压缩上传
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
package com.datagrand.datareport.test; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.zip.GZIPOutputStream; import java.util.Map.Entry; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.NameValuePair; import org.apache.http.StatusLine; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.GzipCompressingEntity; import org.apache.http.client.entity.GzipDecompressingEntity; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.util.EntityUtils; @SuppressWarnings("deprecation") public class TestHttp{ @SuppressWarnings("resource") public String post(String reqURL, Map<String, String> params) throws ClientProtocolException, IOException{ String responseContent = ""; HttpPost httpPost = new HttpPost(reqURL); if (params != null) { List nvps = new ArrayList(); Set<Entry<String, String>> paramEntrys = params.entrySet(); for (Entry<String, String> entry : paramEntrys) { nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); } UrlEncodedFormEntity entity = new UrlEncodedFormEntity(nvps, "utf-8"); httpPost.setEntity(new GzipCompressingEntity(entity)); } httpPost.setHeader("User-Agent", "datagrand/datareport/java sdk v1.0.0"); httpPost.setHeader("Content-Type","application/x-www-form-urlencoded"); httpPost.setHeader("Content-Encoding","gzip"); HttpClient httpClient = new DefaultHttpClient(); HttpParams httpParams = httpClient.getParams(); HttpConnectionParams.setSoTimeout(httpParams, 60*1000); HttpConnectionParams.setConnectionTimeout(httpParams, 60*1000); HttpResponse response = httpClient.execute(httpPost); StatusLine status = response.getStatusLine(); if (status.getStatusCode() >= HttpStatus.SC_MULTIPLE_CHOICES) { System.out.printf("Did not receive successful HTTP response: status code = {}, status message = {}", status.getStatusCode(), status.getReasonPhrase()); httpPost.abort(); } HttpEntity entity = response.getEntity(); if (entity != null) { responseContent = EntityUtils.toString(entity, "utf-8"); EntityUtils.consume(entity); } else { System.out.printf("Http entity is null! request url is {},response status is {}", reqURL, response.getStatusLine()); } return responseContent; } public static void main(String[] args){ TestHttp obj = new TestHttp(); Map<String,String> params = new HashMap<String,String>(); params.put("appid", "237389"); params.put("table_name", "item"); String table_content = "[{\"cmd\":\"add\",\"fields\":{\"itemid\":\"10001\"}}]"; params.put("table_content", table_content); String res; try { res = obj.post("http://datareportapi.datagrand.com/data/YOUR_APP_NAME", params); System.out.println(res); } catch (Exception e) { e.printStackTrace(); } } } |
3.2.8.4、HTTP请求,PHP示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
<!--?php function reportItemsByCurl($url, $params = array()) { $options = array( CURLOPT_HTTP_VERSION => 'CURL_HTTP_VERSION_1_1',<br ?--> CURLOPT_CONNECTTIMEOUT => 60, CURLOPT_TIMEOUT => 60, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_HEADER => false, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER =>array('Expect:'), CURLOPT_POSTFIELDS => $params, ); $session = curl_init($url); curl_setopt_array($session, $options); $response = curl_exec($session); curl_close($session); return $response; } $jsondata = array( 'cmd'=>'add', 'fields'=>array( 'itemid'=>'1111', 'title'=>'title', 'cateid'=>'1' ) ); $content = array(); array_push($content, $jsondata); $YOUR_APP_ID = 237389; $data = array( 'appid'=>$YOUR_APP_ID, 'table_name'=>'item', 'table_content'=> json_encode($content) ); $returnDG = reportItemsByCurl('http://datareportapi.datagrand.com/data/YOUR_APP_NAME', $data); echo $returnDG; |
4、调用推荐服务
4.1、个性化推荐服务
4.1.1、 接口描述
根据传入的userid、imei和cid,结合item数据、user数据和用户行为数据进行深入的挖掘和分析,生成用户最可能感兴趣的item列表,并且按照用户感兴趣的程度从高到低排序。由于user数据和用户行为数据的差异,从而生成的结果也是因人而异的,达到“千人千面”的效果。不带cateid参数,返回的是全局的个性化推荐结果。带有cateid参数,返回的是此分类下的个性化推荐结果。
4.1.2、 URL
http://recapi.datagrand.com/personal/YOUR_APP_NAME
4.1.3、 Http Method
GET
4.1.4、 Http 返回格式
JSON
4.1.5、 Http 请求参数说明
参数 | 类型 | 是否必需 | 描述 |
---|---|---|---|
appid | string | 否 | 应用id |
userid | string | 有则带上,否则对推荐结果有负面影响 | 用户id,没有的话请用空字符串表示 |
imei | string | 有则带上,否则对推荐结果有负面影响 | 用户手机IMEI号,没有的话请用空字符串表示 |
cid | string | 有则带上,否则对推荐结果有负面影响 | 用户网站cookieid,没有的话请用空字符串表示(注意:userid、imei、cid至少包含一项,这里三者的数据必须要和user_action中上报的数据字段一致 ) |
scene_type | string | 否 | 场景类型,用于标识不同的场景 |
device_type | string | 否 | 设备类型,用于表示不同设备型号,常见的包括ios_13pro、huawei_mate40pro等 |
start | int | 否 | 开始项,用于翻页,默认为0并且关闭,返回结果会把用户历史推荐结果全部过滤。如需打开,请跟达观联系 |
cnt | int | 是 |
单次推荐请求返回的结果数量,最大为64,不能为负数 |
exclude | string | 否 | 需要过滤的itemid列表,这些itemid推荐结果不会返回。如果有多个itemid请以英文逗号分隔 |
cateid | string | 否 | 是否需要按照类别过滤itemid列表,有则推荐的item必须是这个类别的。如果有多个cateid请以英文逗号分隔 |
exclude_cateid | string | 否 | 需要过滤的cateid,这些cateid对应的item不会推荐出来。如果有多个,请以英文逗号分隔 |
province | string | 否 | 是否需要按照所属省级过滤itemid列表,有则推荐的item必须是所属这个省级。如果有多个province请以英文逗号分隔 |
city | string | 否 | 是否需要按照所属市级过滤itemid列表,有则推荐的item必须是所属这个市级的。如果有多个city请以英文逗号分隔 |
4.1.6、 注意事项
1)userid/imei/cid 必须至少有一个,用于唯一标识一个用户
,然后和用户历史行为数据进行关联,达到千人千面的个性化推荐效果。如果某一个没有值,请不要传NULL、null、-1,0等异常值
,可以不传此参数或者传空字符串。
2)scene_type 主要用于标示不同推荐位置的,便于跟进各个位置的推荐效果。建议只有一个个性化推荐位置可以不传此参数,有多个的话最好带上
。
3)start 一般应用于相关推荐。举个例子,假如结果序列为 item1,item2,item3,item4,item5,item6。不使用start的话,请求参数cnt为2,则每次返回都是 item1,item2。如果使用start的话,cnt还是2,start为0,则返回 item1,item2;start为1,则返回item2,item3;start为2,则返回item3,item4。如果您有明确的翻页需求,需要使用start参数,请跟达观联系以启用此参数。
4)exclude 本次推荐请求需要过滤掉的itemid列表,主要是为了方便客户灵活应用达观推荐结果和自身业务规则相融合。比如客户有一部分强推的itemid列表,然后和达观推荐结果向结合,为了避免重复,可以把强推的itemid列表放在exclude参数里。当然客户有一些不希望被推荐出来的itemid列表,也可以使用这个参数进行处理。
5)cateid 用于控制本次推荐请求只返回此cateid下的itemid列表,前向匹配,支持传入多个cateid(传入多个cateid的话,以英文逗号分隔,满足一个cateid即可)。
比如itemid_1的 cateid为1_2_3, itemid_2的cateid为1_2_5, 传入cateid为1或者1_2或者’1_2,1_3’,结果可返回 itemid_1和itemid_2;传入cateid为1_2_3的话,只返回itemid_1;传入cateid为2或者2_3,itemid_1和itemid_2都不会返回。不能传1_或者1_2_。
6)假如在调用推荐接口的时候同时传入了province和city参数,我们默认只限制city来进行推荐。
7)在产品上展示的item顺序必须要和达观推荐接口返回的item顺序一致,不要对推荐结果进行二次处理,否则对效果有很大的负作用。
8)使用curl测试接口的时候,如果有中文,需要进行url编码。
4.1.7、 Http 返回结果说明
字段 | 类型 | 描述 |
---|---|---|
status | string | 执行结果,OK为成功,FAIL为失败,WARN为有部分非重要字段异常,请根据返回错误信息进行排查 |
recdata | string | 推荐结果,为一个LIST,每一项为一个dict,包括推荐itemid |
request_id | string | 该条查询的记录id,主要用于排查问题使用 |
errors | string | 如果FAIL或WARN时返回错误码和错误信息 |
4.1.8、 接口调用示例
CURL调用示例:
1 2 |
curl 'http://recapi.datagrand.com/personal/YOUR_APP_NAME?start=0&cnt=2&imei=48390293849849&userid=1234345&exclude=192,2102,3444&scene_type=pc_home' |
成功返回示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{ "status":"OK", "request_id":"1523877252347360", "recdata":[ { "itemid":"34" }, { "itemid":"15" } ] } |
错误返回示例:
1 2 3 4 5 6 7 8 9 |
{ "status":"FAIL", "request_id":"1523877252347355", "errors":{ "code":2012, "message":"userid,cid,imei all null" } } |
警告返回示例:
1 2 3 4 5 6 7 8 9 |
{ "status":"WARN", "request_id":"1523877252367365", "errors":{ "code":2012, "message":"cnt value is incorrect" } } |
4.2、相关推荐服务
4.2.1、接口描述
根据传入的itemid,结合item数据和用户行为数据进行深入的挖掘和分析,生成与当前item最相关的item列表,并且按照“相关性”从高到低排序。不带cateid参数,返回的是全局相关推荐结果。带有cateid参数,返回的是此分类下的相关推荐结果。
4.2.2、URL
http://recapi.datagrand.com/relate/YOUR_APP_NAME
4.2.3、Http Method
GET
4.2.4、Http 返回格式
JSON
4.2.5、Http 请求参数说明
参数 | 类型 | 是否必需 | 描述 |
---|---|---|---|
appid | string | 否 | 应用id |
itemid | string | 是 |
当前物品id,请求和该itemid相关的推荐物品 |
userid | string | 有则带上,否则对推荐结果有负面影响 | 用户id,没有的话请用空字符串表示 |
imei | string | 有则带上,否则对推荐结果有负面影响 | 用户手机IMEI号,没有的话请用空字符串表示 |
cid | string | 有则带上,否则对推荐结果有负面影响 | 用户网站cookieid,没有的话请用空字符串表示(注意:userid、imei、cid至少包含一项,这里三者的数据必须要和user_action中上报的数据字段一致 ) |
scene_type | string | 否 | 场景类型,用于标识不同的场景,常用的包括pc_home(PC首页个性推荐),android_detail(安卓详情页个性化推荐)等。不在上述中的可以自行添加 |
device_type | string | 否 | 设备类型,用于表示不同设备型号,常见的包括ios_13pro、huawei_mate40pro等 |
start | int | 否 | 开始项,用于翻页,默认为0并且关闭状态,如需打开,请跟达观联系 |
cnt | int | 是 |
单次推荐请求返回的结果数量,最大为64 |
exclude | string | 否 | 需要过滤的itemid列表,这些itemid推荐结果不会返回。如果有多个itemid请以,分隔 |
cateid | string | 否 | 是否需要按照类别过滤itemid列表,有则推荐的item必须是这个类别的 |
4.2.6、注意事项
1)userid/imei/cid 必须至少有一个,用于唯一标识一个用户
,有利于优化推荐效果。如果某一个没有值,请不要传NULL、null、-1,0等异常值
,可以不传此参数或者传空字符串。
2)scene_type 主要用于标示不同推荐位置的,便于跟进各个位置的推荐效果。建议只有一个相关推荐位置可以不传此参数
,有多个的话最好带上。
3)start 默认不使用
。如果您有明确的翻页需求,请跟达观联系以启用此参数。
4)exclude 本次推荐请求需要过滤掉的itemid列表,主要是为了方便客户灵活应用达观推荐结果和自身业务规则相融合。比如客户有一部分强推的itemid列表,然后和达观推荐结果向结合,为了避免重复,可以把强推的itemid列表放在exclude参数里。当然客户有一些不希望被推荐出来的itemid列表,也可以使用这个参数进行处理。
5)cateid 用于控制本次推荐请求只返回此cateid下的itemid列表,前向匹配,支持传入多个(传入多个的话以英文逗号分隔,满足一个cateid即可)。
比如itemid_1的 cateid为1_2_3, itemid_2的cateid为1_2_5, 传入cateid为1或者1_2或者’1_2,1_5’,结果可返回 itemid_1和itemid_2;传入cateid为1_2_3的话,只返回itemid_1;传入cateid为2或者2_3,itemid_1和itemid_2都不会返回。不能传1_或者1_2_。
6)使用curl测试接口的时候,如果有中文,需要进行url编码。
4.2.7、Http 返回结果说明
字段 | 类型 | 描述 |
---|---|---|
status | string | 执行结果,OK为成功,FAIL为失败,,WARN为有部分非重要字段异常,请根据返回错误信息进行排查 |
recdata | string | 推荐结果,为一个LIST,每一项为一个dict,包括推荐itemid |
request_id | string | 该条查询的记录id,主要用于排查问题使用 |
errors | string | 如果FAIL或WARN时返回错误码和错误信息 |
4.2.8、接口调用示例
CURL调用示例
1 2 |
curl 'http://recapi.datagrand.com/relate/YOUR_APP_NAME?itemid=123&start=0&cnt=2&imei=abcdefg&userid=1234345&exclude=1,2,3&scene_type=pc_detail' |
成功返回示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{ "status":"OK", "request_id":"1523877252345665", "recdata":[ { "itemid":"34" }, { "itemid":"15" } ] } |
错误返回示例:
1 2 3 4 5 6 7 8 9 |
{ "status":"FAIL", "request_id":"1523877252347890" "errors":{ "code":2012, "message":"itemid is required" } } |
警告返回示例:
1 2 3 4 5 6 7 8 9 |
{ "status":"WARN", "request_id":"1523877252347388" "errors":{ "code":2013, "message":"cnt value is incorrect" } } |
4.3、热门推荐服务
4.3.1、 接口描述
根据item数据和用户行为数据进行深入的挖掘和分析,分别针对全部item和各个分类下的item按照热门程度进行排序,得到全局和各个分类的热门item列表,并且按照热门程度从高到低排序。不带cateid参数,返回的是全局热门推荐结果。带有cateid参数,返回的是此分类下的热门推荐结果。
4.3.2、URL
http://recapi.datagrand.com/hot/YOUR_APP_NAME
4.3.3、Http Method
GET
4.3.4、Http 返回格式
JSON
4.3.5、Http 请求参数说明
参数 | 类型 | 是否必需 | 描述 |
---|---|---|---|
appid | string | 否 | 应用id |
userid | string | 有则带上,否则对推荐结果有负面影响 | 用户id,没有的话请用空字符串表示 |
imei | string | 有则带上,否则对推荐结果有负面影响 | 用户手机IMEI号,没有的话请用空字符串表示 |
cid | string | 有则带上,否则对推荐结果有负面影响 | 用户网站cookieid,没有的话请用空字符串表示(注意:userid、imei、cid至少包含一项,这里三者的数据必须要和user_action中上报的数据字段一致 ) |
scene_type | string | 否 | 场景类型,用于标识不同的场景,常用的包括pc_home(PC首页个性推荐),android_detail(安卓详情页个性化推荐)等。不在上述中的可以自行添加 |
device_type | string | 否 | 设备类型,用于表示不同设备型号,常见的包括ios_13pro、huawei_mate40pro等 |
cateid | string | 否 | 如果该项为空,则为全局排行,如果不为空,则为相应分类排行 |
start | int | 否 | 开始项,用于翻页,默认为0 |
cnt | int | 是 |
单次推荐请求返回的结果数量,最大为64 |
4.3.6、注意事项
1)userid/imei/cid 必须至少有一个,用于唯一标识一个用户
,有利于优化推荐效果。如果某一个没有值,请不要传NULL、null、-1,0等异常值,可以不传此参数或者传空字符串。
2)scene_type 主要用于标示不同推荐位置的,便于跟进各个位置的推荐效果。建议只有一个热门推荐位置可以不传此参数
,有多个的话最好带上。
3)cateid 用于控制本次推荐请求只返回此cateid下的itemid列表,前向匹配,支持传入多个cateid(传入多个cateid的话,以英文逗号分隔,满足一个cateid即可)。
比如itemid_1的 cateid为1_2_3, itemid_2的cateid为1_2_5, 传入cateid为1或者1_2或者’1_2,1_3’,结果可返回 itemid_1和itemid_2;传入cateid为1_2_3的话,只返回itemid_1;传入cateid为2或者2_3,itemid_1和itemid_2都不会返回。不能传1_或者1_2_。
4)使用curl测试接口的时候,如果有中文,需要进行url编码。
Http 返回结果说明
字段 | 类型 | 描述 |
---|---|---|
status | string | 执行结果,OK为成功,FAIL为失败,,WARN为有部分非重要字段异常,请根据返回错误信息进行排查 |
recdata | string | 推荐结果,为一个LIST,每一项为一个dict,包括推荐itemid |
request_id | string | 该条查询的记录id,主要用于排查问题使用 |
errors | string | 如果FAIL或WARN时返回错误码和错误信息 |
4.3.7、示例
CURL调用示例:
1 2 |
curl 'http://recapi.datagrand.com/hot/YOUR_APP_NAME?cateid=1_2&start=0&cnt=2&imei=abcdefg&userid=1234345&scene_type=pc_home' |
成功返回示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{ "status":"OK", "request_id":"1523877252347200", "recdata":[ { "itemid":"34" }, { "itemid":"15" } ] } |
错误返回示例:
1 2 3 4 5 6 7 8 9 |
{ "status":"FAIL", "request_id":"1523877252347300" "errors":{ "code":2015, "message":"userid, imei, cid all null" } } |
警告返回示例:
1 2 3 4 5 6 7 8 9 |
{ "status":"WARN", "request_id":"1523877252347400" "errors":{ "code":2012, "message":"cnt value is incorrect" } } |
三、效果测试
上线达观推荐策略后,如果希望将达观推荐系统和应用方自身的推荐系统进行效果比对的话,那么在进行效果测试的过程中需要关注以下几点。
1.测试位置
对比双方使用相同的推荐位置,只是展示的推荐结果来自不同的推荐系统,其它的内容保持不变。
2.测试方法
采用业界普遍采用的AB测试方法。具体过程是:对用户进行分流,一部分用户展示“达观”的推荐结果,另外的用户展示应用方自身的推荐结果。流量比例由应用方这边指定,前期可以先小流量测试,用于磨合算法。效果提升了以后,再扩大流量观察。
3.测试指标
一般是推荐点击率,其它指标也可以双方进行协商。
4.其他
1)测试指标是透明的,也就是达观接收到的数据计算出的推荐效果指标和应用方自身的效果数据是一致的;
2)数据上报和推荐结果的分流都需要应用方相关的技术人员进行配合;
四、常见问题汇总
1、上报用户行为数据(user_action)时,需要注意的事项有哪些?
1)客户上报用户行为数据时,需要保证userid、 imei、cid三个用户id至少有一个不能为空,为了得到更好的推荐效果,强烈建议三者都上报。如果没有用空字符串表示,请勿传null、-1等异常数据
;
2)在点击、购买、点赞、收藏等行为场景下,itemid不能为空;
3)用户对来自达观推荐结果的点击行为,action_type请设置为“rec_click”,用于统计推荐点击率,可以更好的优化推荐效果;
2、为什么数据需要尽可能地实时上报?
数据上报的实时性会很大程度上影响推荐的准确性,物品实时上报,可以实时反映到推荐结果里;用户行为上报可以用于实时更新个性化推荐结果,响应用户实时兴趣的变化。
3、个性化推荐、相关推荐和热门推荐的应用场景是什么?
1)热门推荐一般适用于有明确热门榜单的场景,不要求个性化,和当前页面其它内容无明确关联;
2)相关推荐适合放在物品详情页面,可以满足用户兴趣的深度需求,推荐内容也比较聚焦;
3)个性化推荐适合放置于首页或其他独立的页面,可以满足用户兴趣的多样性,让用户有更多的选择;
4、调用达观推荐接口(个性化推荐接口、相关推荐接口、热门推荐接口)时,userid、imei、cid的设置有什么要求吗?
userid、imei、cid的设置要和user_action保持一致,用于和用户历史行为数据进行关联,有助于推荐效果的提升。不能上报null、-1等异常值。
5、如何对推荐结果进行干预,以满足自身特有的业务需求?
可以根据自身业务运营的需求逻辑,调整item表score字段的大小,值越大的被推荐出来的可能性越大。
6、我们的产品有资讯、视频、帖子,有的场景推荐内容仅限于一种,比如只推荐资讯,有的场景则三种都需要,这种多类别的推荐可以实现吗?
1)上报数据是到item表,使用cateid的第一层进行区分产品,后面再跟上该产品的实际类别,比如资讯体育、视频科技;
2)调用推荐接口时,使用cateid限制推荐结果列表的类别。比如,不传cateid或者传空字符串的话,推荐结果里可以出现资讯、视频、帖子中的一种或多种;如果只传cateid=资讯,则推荐结果里只有资讯,可以出现资讯下的所有类别;如果传cateid=资讯_体育,则推荐结果只有资讯且是体育类型的;