百度统计为用户提供了 API 接入的方式,使得用户可以自定义 UI 而无须进入百度统计网站。百度统计存在两种账号体系:百度商业账号和百度账号,前者就是统计早期的用户账号,本文基于百度商业账号,说明如何接入统计 API。
接口的请求需要向相应 API 通过 POST 的方式发送 JSON 格式的数据,注意 JSON 数据放在请求的 RawBody 中,而不是一般的键对值得 POST 结构。该请求数据的结构分为两个部分,header 部分是用户信息,body 部分 : 对于不同的 API,body 部分有所不同。
String json = "{\"header\": "
+ "{"
+ "\"username\": \"xxxxx\", "
+ "\"password\": \"xxxxx\","
+ "\"token\": \"xxxx\","
+ "\"account_type\": 1"
+ "}"
+ "}";
String html = HttpBasicRequest.post("https://api.baidu.com/json/tongji/v1/ReportService/getSiteList", json, conn -> {
conn.addRequestProperty("Content-type", "application/json");
});
请求必须指定 Content-type 为 application/json
,否则不能请求。
实现中我们把 header 用 map 定义,然后转换为 JSON 字符串,如下方法所示。
/**
* 获取请求头
*
* @return
*/
private static String getHeader() {
Map header = new HashMap() {
private static final long serialVersionUID = 1L;
{
put("username", ConfigService.get("baidu_tongji.api_username"));
put("password", ConfigService.get("baidu_tongji.api_password"));
put("token", ConfigService.get("baidu_tongji.api_token"));
put("account_type", 1);
}
};
return JsonHelper.stringifyMap(header);
}
接着可以传入不同业务需求的 body,body 也是 Map。
private static final String JSON = "{\"header\": %s, \"body\": %s}";
/**
* 请求 API
*
* @param body
* @return
*/
private static String getData(Map body) {
String req = String.format(JSON, getHeader(), JsonHelper.stringifyMap(body));
String json = HttpBasicRequest.post("https://api.baidu.com/json/tongji/v1/ReportService/getData", req, conn -> {
conn.addRequestProperty("Content-type", "application/json");
});
return "json::" + json;
}
然后进行请求,返回结果 JSON。
一个百度统计账号下面可以有多个站点。接口 https://api.baidu.com/json/tongji/v1/ReportService/getSiteList 。关键的字段是 siteId,如果已知 siteId 则可不必请求该接口。
这是核心的 API,接口是 https://api.baidu.com/json/tongji/v1/ReportService/getData 。在这个接口中根据不同的参数来获取各项的报告数据。具体是 body 的 method 字段。
@GET
@Path("getTimeTrendRpt")
@Produces(MediaType.APPLICATION_JSON)
public String getTimeTrendRpt() {
Date now = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTime(now);
calendar.add(Calendar.DAY_OF_MONTH, -1);// 昨天
String today = formater.format(now), yesterday = formater.format(calendar.getTime());
Map body = new HashMap() {
private static final long serialVersionUID = 1L;
{
put("site_id", ConfigService.get("baidu_tongji.siteId"));
put("start_date", yesterday);
put("end_date", today);
put("method", "overview/getTimeTrendRpt");
put("metrics", "pv_count,visitor_count,ip_count,bounce_ratio,avg_visit_time");
}
};
return getData(body);
}
生成界面如下(部分)。
默认是昨天、今天的数据。
@GET
@Path("getCommonTrackRpt")
@Produces(MediaType.APPLICATION_JSON)
public String getCommonTrackRpt() {
Date now = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTime(now);
calendar.add(Calendar.DAY_OF_MONTH, -1);// 昨天
String today = formater.format(now), yesterday = formater.format(calendar.getTime());
Map body = new HashMap() {
private static final long serialVersionUID = 1L;
{
put("site_id", ConfigService.get("baidu_tongji.siteId"));
put("start_date", yesterday);
put("end_date", today);
put("method", "overview/getCommonTrackRpt");
}
};
return getData(body);
}
获取趋势分析报告中 PV 和 UV 数据,按天粒度。
@GET
@Path("getTrend")
@Produces(MediaType.APPLICATION_JSON)
public String getTrend(@QueryParam("start_date") @NotNull String start_date, @QueryParam("end_date") @NotNull String end_date) {
Map body = new HashMap() {
private static final long serialVersionUID = 1L;
{
put("site_id", ConfigService.get("baidu_tongji.siteId"));
put("start_date", start_date);
put("end_date", end_date);
put("method", "trend/time/a");
put("metrics", "pv_count,visit_count");
put("max_results", "0");
put("gran", "day");
}
};
return getData(body);
}
本系统基于 vue 的前端。这里需要一个图表组件展示用,我最开始使用 vue2-frappe,但不知为何,可能是样式冲突,加入我的样式就不显示了,DOM 是存在的,我不折腾这组件,于是改为另外一款轻量级的图表组件,更轻量级,而且是国人作品,是为 Laue(https://laue.js.org 、https://github.com/qingwei-li/laue) 。
当前并没有完全整合百度统计的所有 API,而是使用了其最重要的三个接口,在给用户一个初步的展示已经足够了。