track_info={
"cn":"精选",
"source_from":"home"
},
groupNum=1,
spm=a2h0c.8166622.xx_1.background
=====================================
=====================================
pid=64b6847e992c4c45,
track_info={
"cn":"精选",
"source_from":"home"
},
groupNum=1,
spm=a2h0c.8166622.xx_1.background
=====================================
=====================================
utparam={"yk_abtest":"943:2175"},
track_info={
"k":"乡村爱情",
"search_from":1,
"object_title":"搜索"
},
spm=a2h0c.8166619.xx.keyinput,
scm=20140669.search.xx.keyinput,
pid=64b6847e992c4c45
=====================================
=====================================
track_info={
"k":"乡村爱情",
"search_from":1,
"object_title":"搜索"
},
spm=a2h0c.8166619.xx.keyinput,
scm=20140669.search.xx.keyinput,
utparam={"yk_abtest":"943:2175"}
=====================================
=====================================
track_info={
"object_title":"搜索",
"utparam":"{\"yk_abtest\":\"943:2175\"}"
},
spm=a2h0c.8166619.xx.keyinput,
scm=20140669.search.xx.keyinput,
utparam={"yk_abtest":"943:2175"}
package com.alibaba.maidianRun.sdksearchClick.searchScene;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.odps.data.Record;
import java.util.List;
public class Arg1Analysis {
public static void parseLog(List<Record> list) {
//通用需求正则必须存在的key的校验
// public static String[] mustExistKeyOuter = {"spm", "scm"};
// public static String[] mustExistKeyInner = {"soku_test_ab", "engine", "item_log", "aaid", "k", "source_from", "search_from"};
for (int i = 0; i < list.size(); i++) {
// 获取单条SQL的查询字段内容
Record record = list.get(i);
// System.out.println("args为:" + args);
// 获取args里的track_info,解析,取第一个{}
// 打印读取SQL的日志信息,运行时可以注释,调试用
// System.out.println("======debug【original_log】======第" + i + "条原始埋点日志为:page为【" + record.getString("page") + "】,arg1为 " +
// record.getString("arg1") + ",【args】为 " + record.getString("args")); // i == count
String app_version = record.getString("app_version").trim();
String os = record.getString("os").trim();
String utdid = record.getString("utdid").trim();
String user_nick = record.getString("user_nick").trim();
String page = record.getString("page").trim();
String event_id = record.getString("event_id").trim();
String arg1 = record.getString("arg1").trim();
String args = record.getString("args").trim();
String ds = record.getString("ds").trim();
String hh = record.getString("hh").trim();
// System.out.println("======debug【original_log】=====" +
// "第" + i + "条埋点日志==app_version为:【" + app_version + "】," +
// "event_id为:【" + event_id + "】," +
// "page为:【" + page + "】," +
// "arg1为:【" + arg1 + "】," +
// "os为:【" + os + "】," +
// "utdid为:【" + utdid + "】," +
// "user_nick为:【" + user_nick + "】," +
// "args为:【" + args + "】," +
// "ds为:【" + ds + "】," +
// "hh为:【" + hh + "】");
if (page.matches("page_(searchhome|searchresults|_ai_search)|SearchActivity")) {
All_cards.ret_cardsAll(parseToJson(args, i), record, i);
} else {
System.err.println("非搜索默认页、结果页页面,请注意是否为其他业务线埋点");
}
}
System.out.println("==========共" + list.size() + "条日志==========");
// 打印读取SQL的日志信息,运行时可以注释,调试用
// System.out.println("第" + i + "条原始埋点日志为:page为【" + record.getString("page") + "】,arg1为 " +
// record.getString("arg1") + ",【args】为 " + record.getString("args")); // i == count
}
//
// private static void switchParse(int page, String args, int count, Record record) {
// switch (page) {
// case 0:
// JSONArray array1 = parseToJson(args, count);
// page_searchhome.voice(array1, record, count);
// break;
// case 1:
// JSONArray array2 = parseToJson(args, count);
// page_searchresults_鹤唳华亭.ogc(array2, record, count);
//
// break;
// default:
// System.out.println("没有此类型page");
// break;
// }
// }
// 点击埋点-2101
public static JSONArray parseToJson(String args, int count) {
JSONArray jsonArray = new JSONArray();
JSONObject innerJSON;
JSONObject outerJSON;
try {
int trackinfoIndex = args.indexOf("track_info");
// 以track_info开始的位置往后查找第一个{,从第11个字符开始查找以后的字符
int firstIndex = args.indexOf("{", trackinfoIndex);
// int firstIndex = args.lastIndexOf("{");
// 如果没有track_info 也就是没有内层json,只有外层的spm=xx,scm=xx; 则==1
if (firstIndex == -1) {
String[] outer = args.split(",");
outerJSON = new JSONObject();
for (int i = 0; i < outer.length; i++) {
if (outer[i].endsWith("==")) {
String outer2 = outer[i].trim().replace("==", "");
String[] array = outer2.split("=");
// 以=拆分之后,为key value
outerJSON.put(array[0].trim(), array[1].trim());
} else {
// 如果outer(spm scm)不包含== 则直接以=拆分key value,如"k":"乡村爱情","search_from":"1",
String[] array = outer[i].split("=");
outerJSON.put(array[0].trim(), array[1].trim());
}
}
innerJSON = new JSONObject();
jsonArray.add(innerJSON);
jsonArray.add(outerJSON);
return jsonArray;
}
// innerJson可能存在"object_title":"搜索","utparam":"{\"yk_abtest\":\"592:1381\"}"
int lastIndexOf = args.lastIndexOf("}");
// 截取inner字符串,json格式{}里所有内容,从{开始截取,直到}的位置
// substring原则左闭右开如[1,3),则截取结果为1,2 需要+1取到后面的开区间,则}+1截取为},不含有","
String innerStr = args.substring(firstIndex, lastIndexOf + 1);
// 如果日志包含utparam,则截取的innerStr是track_info={...},utparam={"yk_abtest":"943:2175"}
// 如果日志不包含utparam,则截取的innerStr是track_info={...}
// 需要截取第二次,找到innerStr重新从0开始截取,找到utparam-1就是",",左开右闭即截取到track_info={...}
// 这样可以做到从track_info开始截取,完美兼容前后出现utparam的情况
if (innerStr.contains("utparam")) {
innerStr = innerStr.substring(0, innerStr.indexOf("utparam") - 1);
}
innerJSON = JSON.parseObject(innerStr);
// 截取outer字符串,A=a,B=b,C=c格式日志,默认页点击埋点在track_info前面、后面均存在outer格式日志,结果页点击埋点仅在track_info后面存在outer格式日志
// 因此,分2部分解析日志,前面part==outerStr1(track_info=为11个字符) 后面part==outerStr2
// 以上2部分拼接outerStr1+outerStr2==outerStr
// 从0开始截取,以{为index,查找track_info=往前移11位,查找outerStr1
// String outerStr1 = args.substring(0, firstIndex - 11);
// 由于2020年3月18日发现日志格式变了,前面增加trackinfoIndex定义,以下代码代替前一种查找方式
String outerStr1 = args.substring(0, trackinfoIndex);
String outerStr2 = args.substring(lastIndexOf + 2);
// 先以,拆分 spm=xx,scm=yy,pid=zz
String outerStr = outerStr1 + outerStr2;
// System.out.println("======debug======outerStr为:" + outerStr);
// System.out.println("======debug======outerStr1为:" + outerStr1);
// System.out.println("======debug======outerStr2为:" + outerStr2);
String[] outer = outerStr.split(",");
// System.out.println("============================="+innerStr.toString());
outerJSON = new JSONObject();
for (int i = 0; i < outer.length; i++) {
// 如果track_info外层包含scm=20140669.search.rvideoset-algo.video_XNDQ5OTQ4NjgwNA==
// 或者spm=a2h0c.8166622.page.downloadbutton,vid=XNDQyODk3OTMyOA==
// 则需要把==替换为空,不影响以,拆分的判断
if (outer[i].endsWith("==")) {
String outer2 = outer[i].trim().replace("==", "");
String[] array = outer2.split("=");
// 以=拆分之后,为key value
outerJSON.put(array[0].trim(), array[1].trim());
} else {
// 如果outer(spm scm)不包含== 则直接以=拆分key value
String[] array = outer[i].split("=");
outerJSON.put(array[0].trim(), array[1].trim());
}
}
// 以下为调试日志,运行代码时注释!!!
// System.err.println("第" + count + "条埋点日志,innerJSON为======" + innerJSON.toJSONString());
// System.err.println("第" + count + "条埋点日志,outerJSON为======" + outerJSON.toJSONString());
jsonArray.add(innerJSON);
jsonArray.add(outerJSON);
} catch (Exception e) {
e.printStackTrace();
}
return jsonArray;
}
// 曝光埋点-2201
public static JSONArray parseToJsonExp(String args, int count) {
System.out.println("parseToJsonExp====parseToJsonExpargs:" + args);
JSONArray jsonArray = new JSONArray();
JSONArray innerJSONArray = new JSONArray();
JSONObject outerJSON;
try {
int firstIndex = args.indexOf("{");
// 如果没有track_info 也就是没有内层json,只有外层的spm=xx,scm=xx;
if (firstIndex == -1) {
String[] outer = args.split(",");
outerJSON = new JSONObject();
for (int i = 0; i < outer.length; i++) {
if (outer[i].endsWith("==")) {
String outer2 = outer[i].trim().replace("==", "");
String[] array = outer2.split("=");
// 以=拆分之后,为key value
outerJSON.put(array[0].trim(), array[1].trim());
} else {
// 如果outer(spm scm)不包含== 则直接以=拆分key value
String[] array = outer[i].split("=");
outerJSON.put(array[0].trim(), array[1].trim());
}
// 以=拆分之后,为key value
}
jsonArray.add(innerJSONArray);
jsonArray.add(outerJSON);
return jsonArray;
}
// innerJson可能存在"object_title":"搜索","utparam":"{\"yk_abtest\":\"592:1381\"}"
int lastIndexOf = args.lastIndexOf("}");
//截取inner字符串,json格式{}里所有内容,从{开始截取,直到}的位置
String innerStr = args.substring(firstIndex, lastIndexOf + 1);
// 截取outer字符串,A=a,B=b,C=c格式日志,默认页点击埋点在track_info前面、后面均存在outer格式日志,结果页点击埋点仅在track_info后面存在outer格式日志
// 因此,分2部分解析日志,前面part==outerStr1(track_info=为11个字符) 后面part==outerStr2,2部分拼接==outerStr
// String outerStr1 = args.substring(0, firstIndex - 11);
String outerStr2 = args.substring(lastIndexOf + 2);
// 先以,拆分 spm=xx,scm=yy,pid=zz
String outerStr = outerStr2;
String[] innerArray = innerStr.split(";");
for (int i = 0; i < innerArray.length; i++) {
if (innerArray[i].trim().length() != 0) {
//{} {} {}
JSONObject innerJSON = JSON.parseObject(innerArray[i]);
innerJSONArray.add(innerJSON);
}
}
String[] outer = outerStr.split(",");
outerJSON = new JSONObject();
for (int i = 0; i < outer.length; i++) {
// 如果track_info外层包含scm=20140669.search.rvideoset-algo.video_XNDQ5OTQ4NjgwNA==
// 或者spm=a2h0c.8166622.page.downloadbutton,vid=XNDQyODk3OTMyOA==
// 则需要把==替换为空,不影响以,拆分的判断
if (outer[i].endsWith("==")) {
String outer2 = outer[i].trim().replace("==", "");
String[] array = outer2.split("=");
// 以=拆分之后,为key value
outerJSON.put(array[0].trim(), array[1].trim());
} else {
// 如果outer(spm scm)不包含== 则直接以=拆分key value
String[] array = outer[i].split("=");
outerJSON.put(array[0].trim(), array[1].trim());
}
}
// 以下为调试日志,运行代码时注释!!!
// System.err.println("第" + count + "条埋点日志,innerJSON为======" + innerJSON.toJSONString());
// System.err.println("第" + count + "条埋点日志,outerJSON为======" + outerJSON.toJSONString());
jsonArray.add(innerJSONArray);
jsonArray.add(outerJSON);
} catch (Exception e) {
e.printStackTrace();
}
return jsonArray;
}
}