尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Wipi 访问量统计是怎么做到的?IP 定位与 UA 解析的访问统计系统实战

Wipi 访问量统计是怎么做到的?IP 定位与 UA 解析的访问统计系统实战 Wipi 访问量统计是怎么做到的IP 定位与 UA 解析的访问统计系统实战【免费下载链接】wipiA blog system written by next.js, nest.js and MySQL.项目地址: https://gitcode.com/gh_mirrors/wi/wipiWipi 是一个用 Next.js、NestJS 和 MySQL 构建的博客系统内置了一套轻量但完整的访问量统计方案访客每打开一个页面系统自动完成访问上报、IP 定位和UAUser-Agent解析最终在管理后台呈现访客来自哪里、用什么浏览器和系统、每天访问趋势如何。本文带你用最短的路径看懂这套访问统计系统的完整实现思路 先想清楚一个访问统计系统要解决什么问题很多新手以为统计访问量就是页面加载 1但真正的难点在于三个问题谁访问了—— 需要拿到访客的真实 IP即使站点挂在 Nginx 反向代理后面访客是谁—— 需要解析 IP 得到地区IP 定位解析 UA 字符串得到浏览器、内核、操作系统、设备型号怎么算次数—— 同一访客反复刷新页面不能把 PV 刷爆需要合理的去重与累加策略。Wipi 对这三个问题的回答分别落在前端上报组件、两个工具函数和一张数据库表上。整体架构数据从浏览器到图表的完整链路整个访问统计的数据流非常清晰浏览器页面加载 → ViewStatistics 组件上报 URL → 后端 /view 接口从请求头取 IP、UA → node-ip2region 离线定位 IP → ua-parser-js 解析 UA → 落库 MySQL自动去重累加 count → 管理后台记录表格 ECharts 趋势图涉及的核心文件都在服务端packages/server/src下实体定义packages/server/src/modules/view/view.entity.ts控制器packages/server/src/modules/view/view.controller.ts业务逻辑packages/server/src/modules/view/view.service.tsIP 工具packages/server/src/utils/ip.util.tsUA 工具packages/server/src/utils/ua.util.ts前端上报一个零感知的统计组件统计的第一步发生在前端。Wipi 用了一个名为ViewStatistics的 React 组件见packages/client/src/components/ViewStatistics.tsx全局挂载在客户端应用的入口处任何页面渲染时都会自动触发上报业务代码完全无感。它只有三行核心逻辑却做对了两个关键细节同页去重用模块级变量lastUrl记住上次上报的 URL相同 URL 不重复上报避免 SPA 路由切换时重复计数过滤本地调试用正则匹配localhost和127.0.0.1开发环境自己的调试流量不会污染线上数据。确认无误后组件调用ViewProvider.addView({ url })packages/client/src/providers/view.ts向接口POST /view发送请求请求体里只有 URL——IP 和 UA 都不需要前端传因为它们天然存在于 HTTP 请求头中由后端自行提取更安全也更简单。后端取 IP在反向代理下依然准确拿到请求后控制器view.controller.ts会调用工具函数getClientIP获取访客 IP。很多项目的通病是直接取remoteAddress结果在 Nginx 后面拿到的全是代理 IP。Wipi 的取 IP 逻辑是一条优先级兜底链ip.util.tsx-real-ip—— Nginx 配置proxy_set_header后最常用的真实 IP 头x-forwarded-for—— 多级代理时的转发 IP 链req.connection.remoteAddress—— 直连时的远程地址req.socket.remoteAddress—— 最后兜底。取到的值再做一次split(:).pop()处理兼容 IPv6 的::1:port这类写法。这个小函数虽然只有几行却是IP 定位准确的前提。IP 定位怎么做离线库 node-ip2region不发任何网络请求把203.0.113.10这样的 IP 变成中国 浙江 杭州是 IP 定位要解决的核心问题。Wipi 选择的是node-ip2region的 BTree 算法库ip.util.ts中create()btreeSearchSync(ip)。它的优点非常适合自建博客完全离线IP 库随依赖本地加载查询是纯内存操作不依赖第三方接口没有配额限制、没有隐私泄露风险速度极快返回结构化地区结果按|分隔出国家、省份、城市、运营商等字段代码里再过滤掉值为0未知的项拼成如中国 江苏 南京的干净文本存入数据库。查询失败时优雅降级为空字符串不会让整个统计流程报错——统计系统不能拖垮主站这是很值得学习的设计。UA 解析怎么做把指纹字符串变成结构化画像每个请求头里都有一段 User-Agent例如Mozilla/5.0 (iPhone; CPU iPhone OS 17_0...)对人类是天书但ua-parser-js库可以把它解析得非常彻底。Wipi 在ua.util.ts中把解析结果组织成四个维度维度字段来源示例浏览器 browserbrowser.name versionChrome 126.0内核 engineengine.name versionChromium 126.0操作系统 osos.name versionWindows 11设备 devicevendor model typeiPhone四个维度会分别写入数据库对应列。这样做的好处是管理后台可以按任意维度模糊搜索比如想看所有 iPhone 用户的访问一条 LIKE 查询就够了。智能去重count 字段让统计更可信最巧妙的设计在落库环节view.service.ts的create方法每次访问先按ip userAgent url三元组查库查到了不新增记录直接把该条记录的count加 1没查到才新建一条记录写入解析好的地区、浏览器等画像字段count初始为 1。这意味着数据库里存的是访客 × 页面维度的聚合访问而不是流水账。同一访客一天刷 50 次首页只占一行数据count显示 50——既防刷量又让表体积可控还能通过updateAt字段天然按天聚合出趋势数据。对应的表结构见view.entity.ts主键使用 UUID还包含createAt/updateAt两个自动维护的时间戳列为后续按时间查询打好了基础。管理后台一张表格 一张趋势图看全访问统计数据的消费端在管理端packages/admin1. 访问记录管理页packages/admin/pages/view/index.tsx以表格展示每条访客聚合记录URL、IP、浏览器、内核、操作系统、设备、地址、访问量Badge 徽标、访问时间并提供按 IP、UA、URL、地址、浏览器等8 个维度的组合搜索支持单条和批量删除删除接口需要 admin 角色 JWT 双重校验防止恶意刷量者自删记录。2. 访问量趋势图packages/admin/src/components/ViewChart/index.tsx基于 ECharts 的折线图调用/view/url?urlxxx接口拿到某页面的全部聚合记录按updateAt的日期分组并累加count即可画出该页面每日访问量曲线支持滚轮缩放dataZoom。文章管理页也复用了这个组件作者发布文章后能直观看到流量变化 快速上手跑起来试试如果你也想在自己的项目里复用这套思路可以先把 Wipi 跑起来克隆仓库git clone https://gitcode.com/gh_mirrors/wi/wipi进入项目执行pnpm install配置 MySQL 连接与packages/config下的环境变量启动packages/serverNestJS 后端与packages/client前台、packages/admin管理端访问任意文章页面然后进入管理端的访问量页面就能看到刚才自己这条带地区、浏览器画像的记录了。小结Wipi 的访问量统计没有引入任何重型组件却五脏俱全前端全局挂载的上报组件自动去重、过滤本地流量取 IP多级请求头兜底反向代理下依然准确IP 定位node-ip2region 离线库快且隐私安全UA 解析ua-parser-js 四维度结构化画像支持任意维度检索去重策略ip UA url聚合 count累加防刷量又省空间可视化表格 ECharts 趋势图数据可查可删可看趋势。这套上报 → 解析 → 聚合 → 展示的思路非常通用几乎可以平移到任何需要访问统计的场景中。【免费下载链接】wipiA blog system written by next.js, nest.js and MySQL.项目地址: https://gitcode.com/gh_mirrors/wi/wipi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表