Hexo博客(28)自建访问量统计
自建访问量统计系统
访问量统计方案
前端页面每刷新一次就 ajax post 上报一次 pv 统计,后端同时写入 汇总表 page_view 和 流水表 page_view_transaction 表。
前端页面每刷新一次就 ajax get 查询一次 pv 统计,从 page_view 表查当前 页面的访问量 和 站点总访问量,从 page_view_transaction 表查今日和昨日站点 PV 和 UV。
pv 上报和查询合并为一个请求即可。
PV算法,每刷新一次页面就统计一次PV
UV算法,一个时间段内一个IP值只计算一次,比如统计当日UV,则在流水表 count group by ip
查询即可,即一个IP每天只计算一次UV
我的博客有些个性化需求,我有三个域名对应三个版本的博客,现在整合为一个了,但还是能通过三个域名访问,我需要统计每篇文章通过这三个域名的访问量分别是多少。
前端
每次页面加载完 ($(document).ready()
) 就上报一次 pv,上报完后查询一次,同时查询出当前页面 pv 和 站点总访问量,以及 当日/昨日 PV/UV。
页面 pv 写入 侧边栏。
站点总访问量,当日/昨日 PV/UV 写入 footer
后端
page_view 表统计每个 url 的访问量汇总
page_view_transaction 记录每次访问流水,每此 pv 上报就 insert 一条数据。
article 表记录 pathname 和 title 的映射关系, pathname是唯一key,每次pv上报请求中创建或更新 article 表
page_view 汇总表
-- PV统计表,保存每个pathname的访问量总和
-- 2020-01-05 19:34:45 上线
DROP TABLE IF EXISTS `page_view`;
CREATE TABLE `page_view` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'id,自增主键',
`pathname` VARCHAR(1024) NOT NULL DEFAULT '' COMMENT '页面pathname',
`host` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '域名:端口',
`views` BIGINT NOT NULL DEFAULT 0 COMMENT 'pathname在此host上的访问量',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
-- mysql最大索引 768 个字节, utf8 占 3 个字节,768/3=256
KEY `pathname` (`pathname`(255)),
KEY `host` (`host`)
) ENGINE = InnoDB
AUTO_INCREMENT = 1
DEFAULT CHARSET = utf8;
page_view_transaction 流水表
-- PV流水表,记录每次页面访问
-- 2020-01-08 18:37:07 上线
DROP TABLE IF EXISTS `page_view_transaction`;
CREATE TABLE `page_view_transaction` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'id,自增主键',
`pathname` VARCHAR(1024) NOT NULL DEFAULT '' COMMENT '页面pathname',
`title` VARCHAR(2048) CHARACTER SET utf8mb4 NOT NULL DEFAULT '' COMMENT '文章title或页面title',
`host` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '域名:端口',
`ip` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '用户的ip',
`platform` VARCHAR(128) NOT NULL DEFAULT '' COMMENT 'navigator.platform 操作系统',
`user_agent` VARCHAR(2048) NOT NULL DEFAULT '' COMMENT 'navigator.userAgent 用户代理(浏览器类型)',
`referrer` VARCHAR(2048) NOT NULL DEFAULT '' COMMENT 'document.referrer 上一个页面url',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
-- mysql最大索引 768 个字节, utf8 占 3 个字节,768/3=256
KEY `pathname` (`pathname`(255)),
KEY `host` (`host`),
KEY `create_time` (`create_time`)
) ENGINE = InnoDB
AUTO_INCREMENT = 1
DEFAULT CHARSET = utf8;
article 文章信息表
-- 文章表,文章表保存 pathname 和 title 的对应关系
-- 2020.1.10 上线
DROP TABLE IF EXISTS `article`;
CREATE TABLE `article` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'id,自增主键',
`pathname` VARCHAR(1024) NOT NULL DEFAULT '' COMMENT '页面pathname',
`title` VARCHAR(2048) CHARACTER SET utf8mb4 NOT NULL DEFAULT '' COMMENT '文章title或页面title',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
-- mysql最大索引 768 个字节, utf8 占 3 个字节,768/3=256
UNIQUE `pathname` (`pathname`(255))
) ENGINE = InnoDB
AUTO_INCREMENT = 1
DEFAULT CHARSET = utf8;
使用gif图片请求上报访问量
前端如何最方便的把统计量数据送到服务器?
目前公认成熟的方案就是通过请求服务器上的一张1x1大小的gif图片的方式将数据发给后端
比如 百度统计 就是请求服务器上的 hm.gif 图片
为什么要请求gif图片?
因为统计的需求就是单方面的将数据发送出去,不需要任何数据的回复,而且统计的sdk绝大部分都是放在第三方的客户的域下的,这就不得不需要解决跨域的问题,然而http对于image类型的文件是没有任何跨域问题的,所以请求一张image图片的方式简直完美适用于这种场景。
至于为什么用gif类型的,当然是因为几种类型的图片文件,(png,jpg,gif等)gif最小了。
至于如何区分是不是独立的访客,第一次请求gif文件的时候,会在客户端写入一份cookie,以后每次请求都会携带这个cookie的值,服务器在清洗数据的时候就可以区分具体访客了。
上一篇 LeetCode.053.Maximum Subarray 最大连续子序列和
下一篇 2020年运动记录
页面信息
location:
protocol
: host
: hostname
: origin
: pathname
: href
: document:
referrer
: navigator:
platform
: userAgent
: