Nim 清理 Nginx access log,删除不需的行
现在人工智能兴起,网站的爬虫多起来了,并且有的爬虫如 Claude 不讲“武德”,不断更换访问网站的 IP 地址
海云青飞 官方网站 https://www.tuenhai.com 用功能简单但速度很快的 visitors 统计网站访问数据,它不能很好地把爬虫的访问识别出来,因此它报告的访客数据就会不准确
以前,我用 vi 删除网站 Nginx access.log 中的某些行,操作如下:
首先 ssh 登录服务器,然后执行命令:
sudo vi /home/tuenhai.com/logs/tuenhai_access.log
:g/Bot\|pider\|rawler\|bot\/\|bot\"\|bot\-\|\.php\| 404 /d
ZZ
再用 visitors
统计网站访问数据
目前 海云青飞 在学习 Nim 编程语言,我提倡在实践中学习,能用 Nim 做的事情尽量让 Nim 去做。今天我写了个清理 web log 的 Nim 程序。在写这个程序中,我注重以下几点:
-
指明使用的符号从哪个库导入
Nim 的标准库丰富、强大,只是我以前很少写 Nim 程序,因此对标准库并不怎么熟悉。我在程序开头导入符号的做法有助于我熟悉 Nim 标准库 API
-
符号的命名尽量做到自解释。就是人或机器人看到这个名字就能大概猜到它是干什么的
-
还得写上简洁的明文注释
现在,我只要在服务器上执行命令:
sudo clean_web_log
就能依据 clean_web_log.json
中的配置迅速把网站访问记录 Nginx access_log 清理一遍,比以前我用 vi 手动删除行要快速、方便 N 倍
clean_web_log.nim
#[
# 海云青飞 https://www.tuenhai.com
# 2024-09-21
Nim 编程语言 2.0
批量删除网站存取日志中不需要的行
用法:
- 在可执行文件同目录创建 .json 配置文件,文件名同可执行文件。示例:
json:
{
"logEnds": "access.log",
"webLogDir": "/home/tuenhai.com/log",
"spamMarking" : ["Bot", "bot/", "bot\"", "bot-", ".php", " 404 ", "pider", "rawler"]
}
- 运行程序
]#
import json
from os import splitFile, walkDir, getAppFilename, dirExists, `/`
from std/syncio import writeFile
from sequtils import mapIt
from strutils import endsWith, splitLines, contains, join
# "import doAssert" is unnecessary?
from std/assertions import doAssert
let
json_key_logEnds = "logEnds"
json_key_webLogDir = "webLogDir"
json_key_spamMarking = "spamMarking"
# .json 格式配置文件与可执行文件同目录且同名,只是后缀不同
proc configFilePath(): string =
let (dir, name, _) = splitFile(getAppFilename())
dir / name & ".json"
# 得到指定目录下符合条件的 log 文件绝对路径
proc listDirFiles(path: string, fileEnds: string): seq[string] =
for _, filePath in walkDir(path, relative=false):
if filePath.endsWith(fileEnds):
result.add(filePath)
# 用 .json 配置文件中 json_key_spamMarking 列出的标记检测某行 web log, 如符合就返回 true
proc isSpam(line: string, marks: seq[string]): bool =
for mark in marks:
if line.contains(mark):
return true
false
# main proc
proc cleanLogs() =
let
jsonNode = configFilePath().readFile().parseJson()
# .json 配置文件中,json_key_logEnds 指定要处理的 web log 文件的结尾字符串
logEnds = jsonNode[json_key_logEnds].getStr()
# .json 配置文件中,json_key_webLogDir 指定 web log 目录的绝对路径
webLogDir = jsonNode[json_key_webLogDir].getStr()
# .json 配置文件中,json_key_spamMarking 指定要删除的 web log lines 的标记
spamMarking = jsonNode[json_key_spamMarking].getElems().mapIt(it.getStr())
doAssert(webLogDir.dirExists(), "Not exists: " & webLogDir)
doAssert(spamMarking.len > 0, "Please set spamMarking")
let logFiles = listDirFiles(webLogDir, logEnds)
doAssert(logfiles.len > 0, "There are no log files to clean, please check your settings")
for i, log in logFiles:
let logContent = readFile(log)
# 要保留的 web log lines, 将覆盖原 log 文件
var cleanedContent: seq[string] = @[]
var spamLines = 0
for line in splitLines(logContent):
if not isSpam(line, spamMarking):
cleanedContent.add(line)
else:
spamLines += 1
if spamLines > 0:
writeFile(log, join(cleanedContent, "\n"))
echo i + 1, " - ", log
echo "Removed ", $spamLines, " lines\n"
cleanLogs()
2024-09-21
独立思考最难得,赞赏支持是美德!(微信扫描下图)