apache access_log是web服务器核心日志,记录http请求详情;清洗需识别无效请求、过滤爬虫、标准化格式、提取状态码、响应时间、ua、来源页等关键维度。

Apache的access_log是Web服务器最核心的日志文件,记录每次HTTP请求的详细信息。理解各字段含义是做流量分析、安全审计或数据清洗的前提;而清洗的关键在于识别无效请求、过滤爬虫、标准化格式、提取关键维度(如状态码、响应时间、UA、来源页)。
access_log常见字段含义(默认combined格式)
典型日志行示例如下:
192.168.1.100 - - [10/Jan/2024:14:23:56 +0800] "GET /api/user?id=123 HTTP/1.1" 200 1872 "https://example.com/home" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" 246对应字段(按空格/引号分隔,共11列)含义如下:
- 1st(客户端IP):发起请求的真实IP,若经代理需结合X-Forwarded-For解析
- 2nd & 3rd(ident & auth-user):通常为“-”,表示未启用Ident协议和HTTP Basic Auth
-
4th([timestamp]):服务端接收请求的时间,含时区,格式固定为
[dd/MMM/yyyy:HH:mm:ss Z] - 5th(request line):引号内完整请求行,含方法、路径(含查询参数)、协议版本;需拆解提取method、uri、query、http_version
- 6th(status code):HTTP响应状态码,如200、404、502等,是判断请求成败的核心指标
- 7th(response size):响应体字节数(不含响应头),- 表示无响应体(如304)
- 8th(referer):来源页面URL,为空或“-”表示直接访问或书签打开;常用于分析流量入口
- 9th(user-agent):客户端标识字符串,可解析出设备类型、浏览器、OS,也用于识别爬虫(如curl、python-requests、Baiduspider)
-
10th(response time):非标准字段,需在LogFormat中显式添加
%D(微秒)或%T(秒),表示服务器处理耗时
Java中常用日志清洗策略与实现要点
使用Java(如Log4j、SLF4J配合自定义Parser)处理access_log时,重点不是逐行正则硬匹配,而是构建可扩展的字段解析器。推荐方式:
- 用
Pattern.compile预编译正则(如^([^\s]+) \S+ \S+ \[([^[\]]+)\] "([^"]+)" (\d+) (\d+|-) "([^"]*)" "([^"]*)" (\d+|\-)$),捕获核心10字段 - 对
request line二次解析:用split(" ", 3)分离method、path+query、protocol;再用new URI(path).getQuery()安全提取参数 - 对
user-agent调用轻量库(如UADetector或UAParser)识别bot、mobile、browser family,避免手动字符串匹配 - 将
timestamp转为Instant或ZonedDateTime,统一为UTC便于聚合;注意SimpleDateFormat非线程安全,应使用DateTimeFormatter(Java 8+) - 过滤明显无效请求:status为400/414/413(客户端错误)、response size为0且非HEAD/304、URI含敏感路径(如
/phpmyadmin/、/wp-admin/)或异常长query
典型清洗后结构化字段建议
清洗目标不是保留原始文本,而是产出可用于分析的结构化事件。建议至少保留以下字段(Java对象或Map形式):
- clientIp:清洗后的IP(去代理头、IPv6标准化)
- timestamp:纳秒级Instant,精确到毫秒即可
- method:UPPERCASE字符串(GET/POST/PUT等)
-
path:无query、无编码的规范路径(如
/api/user) - status:int型状态码
- bytesSent:long型响应字节数,-1表示未知
-
refererHost:referer URL的host部分(如
example.com),便于归类来源域 - isBot:boolean,基于UA识别
- responseTimeMs:long型,单位毫秒(若原始为微秒需除1000)
- userAgentFamily:如Chrome、Safari、Baiduspider、Other
注意事项与避坑点
实际工程中容易忽略但影响清洗质量的细节:
- 日志中存在换行符或双引号未转义内容(尤其在UA或referer中),正则匹配会错位;建议先用
line.replaceAll(" | | ", " ")预清理 - 多个空格或制表符会导致
String.split(" ")产生空字段;优先用StringTokenizer或按正则"\s+"分割并过滤空串 - 中文路径或参数多为UTF-8编码,但日志文件本身可能被误读为ISO-8859-1(尤其Linux系统默认);Java读取时必须显式指定
StandardCharsets.UTF_8 - 高并发写入日志时,单行可能被截断(尤其大响应体+长UA),需校验字段数是否达标(如combined格式正常为11段),不足则丢弃或打标为corrupted
- 不要依赖日志中的IP做用户唯一标识——CDN、NAT、代理会使大量用户共享同一clientIp;需结合cookie或token字段(若日志已记录)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










