本文目录导读:

- 方案一:Nginx 日志 + 一行 Shell 命令(最轻量)
- 方案二:Python 脚本(简单易用,可扩展)
- 方案三:Node.js 脚本(适合实时Web服务)
- 方案四:专业方式 - 嵌入代码(推荐用于生产环境)
- 如何选择?
- 注意事项
可以,统计URL访问量是Web开发中的常见需求,下面提供几种实用且能自动运行的脚本方案,从简单到复杂,你可以根据技术栈和场景选择。
Nginx 日志 + 一行 Shell 命令(最轻量)
如果你的网站使用 Nginx 作为反向代理,它的访问日志文件本身就记录了所有请求的URL,用下面的脚本可以自动统计实时或历史的访问量。
-
命令脚本:统计所有URL的访问次数,按从高到低排序。
# 统计 access.log 中,第7列(请求的URL路径,不含域名)的出现次数 awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20 -
自动刷新脚本:保存为
watch_url.sh,每5秒自动刷新一次。#!/bin/bash while true; do clear echo "===== 当前URL访问量 Top 10 (每5秒刷新) =====" awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10 sleep 5 done运行:
bash watch_url.sh
Python 脚本(简单易用,可扩展)
使用Python可以更灵活地处理数据,比如统计今天、过去1小时的数据,或者输出为JSON。
# url_stats.py
import re
from collections import Counter
from datetime import datetime, timedelta
LOG_FILE = "/var/log/nginx/access.log"
def count_urls(time_window_minutes=None):
"""
统计URL访问量
:param time_window_minutes: 可选,只统计最近N分钟内的访问
"""
urls = []
now = datetime.now()
with open(LOG_FILE, "r") as f:
for line in f:
# 解析日志行,提取时间戳和URL路径
# 常见Nginx日志格式:127.0.0.1 - - [10/Oct/2023:13:55:36 +0000] "GET /api/v1/users HTTP/1.1" 200 1234
match = re.search(r'\[(\d{2}/\w{3}/\d{4}:\d{2}:\d{2}:\d{2}).*?"(\w+)\s+(/\S*)', line)
if not match:
continue
log_time_str = match.group(1)
url = match.group(3)
if time_window_minutes:
log_time = datetime.strptime(log_time_str, "%d/%b/%Y:%H:%M:%S")
if (now - log_time) > timedelta(minutes=time_window_minutes):
continue
urls.append(url)
return Counter(urls)
if __name__ == "__main__":
# 统计最近30分钟的Top 10
stats = count_urls(time_window_minutes=30)
print("最近30分钟内 TOP 10 URL 访问量:")
for url, count in stats.most_common(10):
print(f"{count:>5} {url}")
运行方式: python url_stats.py
Node.js 脚本(适合实时Web服务)
如果你希望统计结果可被前端直接请求,可以用Node.js。
// url_stats_server.js
const express = require('express');
const fs = require('fs');
const readline = require('readline');
const app = express();
const LOG_FILE = '/var/log/nginx/access.log';
const PORT = 3000;
// 存储统计结果
let urlCounts = {};
function parseLog() {
console.log('更新统计...');
const counts = {};
const rl = readline.createInterface({
input: fs.createReadStream(LOG_FILE),
crlfDelay: Infinity
});
rl.on('line', (line) => {
// 简单正则提取URL
const match = line.match(/"(?:GET|POST|PUT|DELETE)\s+(\/\S*)/);
if (match) {
const url = match[1];
counts[url] = (counts[url] || 0) + 1;
}
});
rl.on('close', () => {
urlCounts = counts;
console.log(`统计完成,共 ${Object.keys(counts).length} 个URL`);
});
}
// 每30秒重新解析一次日志
setInterval(parseLog, 30000);
parseLog(); // 首次启动时立即统计
app.get('/api/url-stats', (req, res) => {
// 返回排序后的Top 20
const sorted = Object.entries(urlCounts)
.sort((a, b) => b[1] - a[1])
.slice(0, 20)
.map(([url, count]) => ({ url, count }));
res.json(sorted);
});
app.listen(PORT, () => {
console.log(`URL统计API运行在 http://localhost:${PORT}/api/url-stats`);
});
运行: node url_stats_server.js,然后访问 http://localhost:3000/api/url-stats 即可看到JSON格式的统计结果。
专业方式 - 嵌入代码(推荐用于生产环境)
生产环境几乎不使用解析日志的方式,而是在应用层直接埋点统计,因为:
- 日志解析有延迟
- 长连接(WebSocket)不写日志
- 静态资源CDN不会返回日志
JavaScript 前端埋点示例:
// 在每个页面或API调用时,发送统计请求
function trackPageView() {
fetch('/api/track?url=' + encodeURIComponent(window.location.pathname), {
method: 'GET',
// 使用1x1像素图片代替 fetch,避免跨域问题(更稳妥)
});
}
// 用 img 标签发送(最兼容,且不阻塞页面)
new Image().src = '/track.gif?url=' + encodeURIComponent(window.location.pathname);
后端接收(Node.js + Redis示例):
// 服务端接收埋点并计数(挂载在 /track 路由)
app.get('/track', (req, res) => {
const url = req.query.url || '/';
redisClient.incr(`url_count:${url}`); // 在Redis中递增计数
// 返回透明1x1像素图片
res.writeHead(200, { 'Content-Type': 'image/gif' });
res.end(Buffer.from('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7', 'base64'));
});
// 获取统计
app.get('/api/stats', (req, res) => {
redisClient.keys('url_count:*', (err, keys) => {
const pipeline = redisClient.pipeline();
keys.forEach(key => pipeline.get(key));
pipeline.exec((err, results) => {
const data = keys.map((key, i) => ({
url: key.replace('url_count:', ''),
count: parseInt(results[i][1] || 0)
}));
res.json(data.sort((a,b) => b.count - a.count).slice(0,20));
});
});
});
如何选择?
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 临时调试、快速查看 | 方案一(Shell) | 无需安装、秒级执行 |
| 需要对历史数据做复杂分析 | 方案二(Python) | 容易写条件过滤和时间窗口 |
| 需要实时Web接口供其他系统调用 | 方案三(Node.js) | 自带HTTP服务器 |
| 生产环境、高并发 | 方案四(埋点+Redis) | 延迟低、不占磁盘、可弹性扩展 |
注意事项
- 权限问题:读取
/var/log/nginx/access.log通常需要sudo或让用户加入adm组。 - 日志轮转:生产环境日志会按天切割,如果使用方案一/二,需要关注日志文件名(如
access.log.1)。 - 性能影响:解析100MB以上的日志文件时,Python/Node脚本会消耗一定CPU,建议用
tail -0f跟随最新日志(流式处理)代替重新读全量文件。 - 去重:如果统计UV(独立访客),需要在统计时加入IP或Cookie作为标识。
如果需要我针对某个方案(比如Python脚本的详细解读或Node.js的实时推送到WebSocket),可以告诉我。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播