当前位置:首页>python>《Python 从入门到精通》109|日志处理实战:从一堆文本中提取有用信息

《Python 从入门到精通》109|日志处理实战:从一堆文本中提取有用信息

  • 2026-08-18 23:10:30
《Python 从入门到精通》109|日志处理实战:从一堆文本中提取有用信息

前面几章,我们已经把一条很重要的线慢慢串起来了。

会读 JSON 了。 会用正则提取关键信息了。 会处理时间了。 会排序、去重、统计了。 还会把脏数据清洗得更整洁了。

到这里,你会发现,很多真实问题已经不再是学不会语法,而是拿到一堆原始文本之后,不知道怎么下手。

而日志,恰好就是这种问题里最典型的一种。

你做网站,会有访问日志。 你写后端,会有运行日志。 你做自动化脚本,会有执行日志。 你处理服务器问题,会看到报错日志。 你做数据清洗,也可能会给自己留一份处理日志。

日志表面上看,就是一行一行普通文本。 可真正做项目的人都知道,日志里藏着大量有价值的信息。

哪一刻出了错。 哪种错误出现最多。 哪个接口最慢。 哪个用户操作异常。 某个任务到底有没有执行成功。 程序卡住之前,最后一步做了什么。

所以这一章很重要。

它教的不是单纯读文本文件。 而是更贴近真实工作的能力:

怎么从杂乱日志里,把真正有用的信息提取出来。


一、什么是日志,为什么程序离不开它

先别把日志想得特别玄。

你可以把日志理解成: 程序在运行过程中留下的文字记录。

就像一个人做事会写工作记录一样,程序也需要记录自己做了什么、什么时候做的、结果怎么样。

例如下面这种内容,就是很常见的日志风格:

2026-03-2909:00:01 INFO 用户登录成功 user_id=10012026-03-2909:01:15 WARNING 请求耗时过长 api=/order/list2026-03-2909:02:30 ERROR 数据库连接失败 db=mysql2026-03-2909:03:20 INFO 定时任务执行完成 task=backup

你一眼就能看出,这里面至少有这些信息:

时间 日志级别 事件描述 补充字段

这就是日志的价值。

它不是写给用户看的。 它主要是写给开发者、运维人员、排查问题的人看的。

程序平时运行得好好的,你可能不觉得它有多重要。 可一旦系统出问题,日志往往是第一现场。

所以很多时候,日志不是可有可无的附加品。 它是程序排查问题、分析行为、定位异常的重要依据。


二、为什么日志处理会成为一种实战能力

很多新手第一次接触日志,会觉得这不就是读文件吗。

其实远不止。

因为日志最大的特点就是:

量大 杂乱 重复 信息藏在文本里 并且不一定完全规整

比如你可能拿到一个几万行的日志文件。 如果靠肉眼去找错误,很快就会看花。

再比如,你想知道昨天一共报了多少次错,哪类错误最多,最早的一次错误出现在几点,哪些请求超时最严重。 这些事情用肉眼几乎没法高效完成。

所以日志处理真正考验的,不是会不会打开文件。 而是你能不能把文本里的信息批量提取、筛选、统计、整理出来。

说白了,日志处理就是数据处理能力的一次综合实战。

前面学的字符串、正则、时间、统计、清洗,在这里会同时派上用场。


三、先看一个最常见的日志长什么样

虽然不同项目日志格式会不一样,但很多日志大致都有类似结构:

时间 日志级别 具体内容

比如:

2026-03-2910:15:23 INFO 用户登录成功2026-03-2910:16:01 ERROR 支付接口调用失败2026-03-2910:16:45 WARNING 订单查询耗时过长

你可以先把它粗略拆成三部分来看:

前面是时间 中间是级别 后面是描述

其中最常见的日志级别通常有:

INFO 表示普通信息WARNING 表示警告,但未必致命ERROR 表示错误 有些项目里还会有 DEBUGCRITICAL 等级别

所以日志处理的第一步,往往不是马上写代码。 而是先观察格式。

你得先看明白,一行日志大概由哪些部分组成,哪些部分是你关心的,哪些只是背景信息。

这一步特别重要。

很多人拿到日志就急着上正则,结果写了半天规则,发现连日志结构都没看明白。 所以越是文本处理,越要先观察,再动手。


四、处理日志之前,第一件事是先把文件读进来

这一点你已经很熟悉了。

假设我们有一个日志文件 app.log,内容如下:

2026-03-2910:15:23 INFO 用户登录成功 user_id=10012026-03-2910:16:01 ERROR 支付接口调用失败 order_id=50012026-03-2910:16:45 WARNING 订单查询耗时过长 api=/order/list2026-03-2910:17:10 INFO 用户退出登录 user_id=1001

最基础的读取方式就是:

with open("app.log""r", encoding="utf-8"as f:    content = f.read()print(content)

如果你是想一行一行处理,更常见的方式是:

with open("app.log""r", encoding="utf-8"as f:    lines = f.readlines()for line in lines:    print(line.strip())

或者写得更直接一点:

with open("app.log""r", encoding="utf-8"as f:for line in f:        print(line.strip())

对于日志这种“一行就是一条记录”的文本,按行处理通常比整段处理更自然。

因为很多分析动作,本来就是围绕“每一条日志”展开的。


五、为什么日志特别适合按行处理

这个习惯非常值得养成。

日志不像一篇文章,它通常是天然分行的。 每一行基本就是一条独立记录。

例如:

2026-03-2910:15:23 INFO 用户登录成功 user_id=10012026-03-2910:16:01 ERROR 支付接口调用失败 order_id=50012026-03-2910:16:45 WARNING 订单查询耗时过长 api=/order/list

如果你把整段文本混在一起看,处理起来反而容易乱。 而按行处理时,你的思路会很清晰:

读到一行 判断是不是我要的 提取关键信息 放进结果集 继续下一行

这就像流水线一样。

所以日志处理里,一个非常重要的默认思维就是:

先把日志当成一条条记录,而不是一整坨文本。

这个习惯会让你后面写筛选、提取、统计都顺手很多。


六、日志处理最常见的第一个需求:先把错误日志筛出来

现实里,很多人第一次处理日志,不是想分析全部内容。 而是最简单也最急迫的需求:

把出错的那部分先找出来。

比如你有一份上万行日志,现在最关心的是所有 ERROR 级别的记录。 这时可以直接写:

with open("app.log""r", encoding="utf-8"as f:for line in f:if"ERROR"in line:            print(line.strip())

这段代码非常朴素,但特别实用。

它体现了一个很重要的原则:

日志分析不一定一上来就要复杂规则。 很多时候,先筛出重点内容,已经能解决大半问题。

比如:

先找所有 ERROR先找所有 WARNING先找某个接口名 先找某个用户 ID 先找某个关键词

这些其实都是日志处理中最常见的第一步。

不要小看这种基础筛选。 很多真实工作里,第一轮排查问题,真就是这么开始的。


七、进一步一点:把错误日志保存下来

很多时候,我们不只是想打印出来,而是想把筛选结果单独保存成一个文件,方便后续分析。

例如把所有错误日志保存到 error.log

with open("app.log""r", encoding="utf-8"as f, open("error.log""w", encoding="utf-8"as out:for line in f:if"ERROR"in line:            out.write(line)

这样,你就得到了一份只包含错误记录的新日志文件。

这个做法特别常见。

比如原始日志太大,不方便发给别人。 比如你只想拿错误部分给同事排查。 比如你后面要针对错误日志继续统计。

这一步虽然简单,但已经很接近真实日志处理工作了:

先过滤 再抽取 再单独保存

这其实就是一种非常典型的数据预处理流程。


八、只会关键词筛选还不够,因为我们还想提取结构化信息

前面我们做的是“筛出来”。 但很多时候,光筛出来还不够。

比如下面这条日志:

2026-03-2910:16:01 ERROR 支付接口调用失败 order_id=5001

如果你只是打印这一整行,当然能看。 但如果你真正想做分析,你更希望拿到的是:

时间:2026-03-29 10:16:01 级别:ERROR 消息:支付接口调用失败 订单号:5001

一旦这些信息被拆出来,你后面就能做更多事:

统计某天错误次数 按时间排序 统计每种错误类型 找出涉及哪些订单 把结果存进表格或数据库

所以日志处理真正有价值的地方,往往在于:

把文本日志,逐步转成结构化数据。


九、最简单的日志拆分方式:先用 split 处理规则明显的日志

如果日志格式比较规整,其实不一定非要一上来就用正则。

比如日志格式始终像这样:

2026-03-2910:16:01 ERROR 支付接口调用失败

你先试着按空格拆分,就能得到不少信息。

line = "2026-03-29 10:16:01 ERROR 支付接口调用失败"parts = line.split()print(parts)

输出会是:

['2026-03-29''10:16:01''ERROR''支付接口调用失败']

这时你就能很直接地拿到:

date = parts[0]time = parts[1]level = parts[2]message = " ".join(parts[3:])

这种写法非常适合日志格式简单、字段位置稳定的场景。

所以你要记住:

文本处理不是逢日志必正则。 能用简单方法解决时,先用简单方法。

这是很重要的实战思维。


十、但很多日志并没那么规矩,这时候正则就派上用场了

真实项目里,日志格式经常更复杂一些。

例如:

2026-03-2910:16:01 ERROR 支付接口调用失败 order_id=50012026-03-2910:16:45 WARNING 订单查询耗时过长 api=/order/list2026-03-2910:17:20 INFO 用户登录成功 user_id=1001

这类日志里,前半部分相对稳定,后半部分字段不一定完全固定。 这时候正则会非常适合。

比如先把时间和级别提出来:

import reline = "2026-03-29 10:16:01 ERROR 支付接口调用失败 order_id=5001"match = re.match(r"(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\s+(INFO|WARNING|ERROR)\s+(.*)", line)if match:    print("时间:", match.group(1))    print("级别:", match.group(2))    print("内容:", match.group(3))

输出大致是:

时间: 2026-03-2910:16:01级别: ERROR内容: 支付接口调用失败 order_id=5001

这一步非常关键。

因为它说明一件事:

日志虽然原本是文本,但你完全可以通过规则,把它逐步拆成更容易处理的部分。

这就是日志分析的核心起点。


十一、进一步提取日志里的具体字段

刚才我们已经把整行拆成了时间、级别、内容。 那如果我们还想从内容里继续提取字段怎么办

比如这条:

支付接口调用失败 order_id=5001

我们还想拿到订单号 5001

这时可以继续用正则:

import remessage = "支付接口调用失败 order_id=5001"match = re.search(r"order_id=(\d+)", message)if match:    print(match.group(1))

输出:

5001

同理,你也可以提取:

user_id=1001api=/order/listcost=2.35sip=192.168.1.10

你会发现,日志处理非常像“多层提取”:

先按行读 再拆整行 再从局部字段里挖出更细的信息

这和前面学的正则提取手机号、日期、邮箱,其实是一个思路。


十二、先做一个小案例:统计错误日志一共有多少条

假设日志文件内容如下:

2026-03-2910:15:23 INFO 用户登录成功2026-03-2910:16:01 ERROR 支付接口调用失败2026-03-2910:16:45 WARNING 订单查询耗时过长2026-03-2910:17:10 ERROR 数据库连接失败2026-03-2910:18:00 INFO 用户退出登录

你想统计一共有多少条错误日志。

代码其实很直接:

count = 0with open("app.log""r", encoding="utf-8"as f:for line in f:if"ERROR"in line:            count += 1print("错误日志数量:", count)

输出:

错误日志数量: 2

这个例子虽然简单,但它已经体现了日志处理最朴素的实用价值:

从一堆肉眼难以快速统计的文本里,提炼出明确结论。

很多自动化脚本,最开始就是从这种小需求长出来的。


十三、再进一步:统计每种日志级别分别出现多少次

这就比单纯统计错误数更完整一些了。

我们想知道:

INFO 出现多少次WARNING 出现多少次ERROR 出现多少次

这时候很适合用前一章学过的 Counter

from collections import Counterlevels = []with open("app.log""r", encoding="utf-8"as f:for line in f:        parts = line.split()if len(parts) >= 3:            level = parts[2]            levels.append(level)result = Counter(levels)print(result)

输出大致会是:

Counter({'INFO'2'ERROR'2'WARNING'1})

你看,前面学过的统计能力,在这里马上就接上了。

这也是为什么我前面一直强调: 不要把知识点孤立看。

字符串处理、列表、字典、正则、Counter,这些东西单独看可能都不算复杂。 但一旦组合起来,就能开始解决真实问题。


十四、日志处理里最常见的需求之一:找出出现最多的错误类型

这比统计 ERROR 总数更进一步。

很多时候,大家关心的不只是“有多少错”,而是:

到底哪种错最常见

比如错误日志可能有这些:

2026-03-2910:16:01 ERROR 支付接口调用失败2026-03-2910:17:10 ERROR 数据库连接失败2026-03-2910:18:05 ERROR 支付接口调用失败2026-03-2910:19:20 ERROR 支付接口调用失败

你想知道哪个错误最频繁,就可以先把错误消息提取出来,再计数。

from collections import Countererrors = []with open("app.log""r", encoding="utf-8"as f:for line in f:if"ERROR"in line:            parts = line.split()            message = " ".join(parts[3:])            errors.append(message)result = Counter(errors)print(result)print("最常见错误:", result.most_common(1))

输出可能是:

Counter({'支付接口调用失败'3'数据库连接失败'1})最常见错误: [('支付接口调用失败'3)]

这就已经很像一个小型日志分析报告了。


十五、很多日志分析问题,真正难点不在统计,而在清洗

比如你想统计错误类型,但日志内容可能是:

支付接口调用失败 order_id=5001支付接口调用失败 order_id=5002支付接口调用失败 order_id=5003

如果你直接整行计数,那它们会被当成三种不同错误。 但从业务角度看,它们其实是同一类问题。

所以你要做的,不只是统计。 而是先把可变部分去掉。

这时候正则清洗就很有用了:

import refrom collections import Countererrors = []with open("app.log""r", encoding="utf-8"as f:for line in f:if"ERROR"in line:            parts = line.split()            message = " ".join(parts[3:])            message = re.sub(r"order_id=\d+""", message).strip()            errors.append(message)result = Counter(errors)print(result)

这样,即使订单号不同,也会被归到同一个错误类别里。

你会发现,这一章和前面的“函数式清洗数据”也接上了。

日志分析不是只会读和数。 很多时候,得先把日志内容标准化,统计才有意义。


十六、日志里最重要的字段之一,往往是时间

因为很多分析都和时间有关。

比如:

某种错误是几点开始出现的 某个时间段错误暴涨 某个任务多久执行一次 某一天的错误量是不是比前一天更多 一条请求从开始到结束耗时多久

所以日志处理里,时间字段通常非常关键。

例如从日志里提取时间:

import reline = "2026-03-29 10:16:01 ERROR 支付接口调用失败"match = re.match(r"(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})", line)if match:    print(match.group(1))

拿到时间字符串后,你还可以继续转成 datetime 对象:

from datetime import datetimetime_text = "2026-03-29 10:16:01"dt = datetime.strptime(time_text, "%Y-%m-%d %H:%M:%S")print(dt)

一旦变成时间对象,你后面就能做真正的时间比较和统计了。


十七、一个很实用的场景:筛选某个时间段的日志

假设你只想看上午 10 点到 11 点之间的错误日志。

这时候,时间解析就非常有用了。

from datetime import datetimeimport restart = datetime.strptime("2026-03-29 10:00:00""%Y-%m-%d %H:%M:%S")end = datetime.strptime("2026-03-29 11:00:00""%Y-%m-%d %H:%M:%S")with open("app.log""r", encoding="utf-8"as f:for line in f:        match = re.match(r"(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})", line)if match:            log_time = datetime.strptime(match.group(1), "%Y-%m-%d %H:%M:%S")if start <= log_time <= end and"ERROR"in line:                print(line.strip())

这类需求在排查线上问题时特别常见。

因为很多问题往往不是全天都发生,而是某一小段时间突然暴增。 所以时间筛选,是日志处理中非常高频的一类操作。


十八、日志里经常还藏着请求耗时、接口名、用户 ID 这类信息

比如一条日志:

2026-03-2910:16:45 WARNING 请求耗时过长 api=/order/list cost=2.35s

如果你只把它当普通文本看,就很浪费。 因为里面至少还有两个很有分析价值的字段:

接口:/order/list耗时:2.35s

我们可以用正则把它提出来:

import reline = "2026-03-29 10:16:45 WARNING 请求耗时过长 api=/order/list cost=2.35s"api_match = re.search(r"api=([^\s]+)", line)cost_match = re.search(r"cost=([\d.]+)s", line)if api_match:    print("接口:", api_match.group(1))if cost_match:    print("耗时:", cost_match.group(1))

输出:

接口: /order/list耗时: 2.35

一旦这些字段被提取出来,你就可以进一步做:

统计哪个接口最慢 筛选耗时超过 2 秒的请求 按接口分类统计平均耗时

这时候日志文本就已经开始往“可分析的数据”转变了。


十九、做一个更真实一点的小案例:找出所有耗时超过 2 秒的请求

这是非常典型的日志分析需求。

假设日志里有这些内容:

2026-03-2910:16:45 WARNING 请求耗时过长 api=/order/list cost=2.35s2026-03-2910:17:10 INFO 请求正常 api=/user/info cost=0.35s2026-03-2910:17:50 WARNING 请求耗时过长 api=/pay/create cost=3.20s

现在我们要把耗时超过 2 秒的接口筛出来。

import rewith open("app.log""r", encoding="utf-8"as f:for line in f:        api_match = re.search(r"api=([^\s]+)", line)        cost_match = re.search(r"cost=([\d.]+)s", line)if api_match and cost_match:            api = api_match.group(1)            cost = float(cost_match.group(1))if cost > 2:                print(f"慢请求:{api},耗时 {cost} 秒")

这段代码已经很像实际排查性能问题的脚本了。

你会发现,它背后其实只是在做几件事:

读日志 提字段 转类型 做判断 输出结果

说到底,还是数据处理。


二十、日志处理里,函数式思维同样非常有用

前一章我们讲过,把清洗动作拆成函数。 这一章同样适用。

例如你可以把“解析一行日志”单独封装成函数:

import redefparse_log_line(line):    match = re.match(r"(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\s+(INFO|WARNING|ERROR)\s+(.*)", line.strip())ifnot match:returnNonereturn {"time": match.group(1),"level": match.group(2),"message": match.group(3)    }

测试一下:

line = "2026-03-29 10:16:01 ERROR 支付接口调用失败 order_id=5001"print(parse_log_line(line))

输出:

{'time''2026-03-29 10:16:01','level''ERROR','message''支付接口调用失败 order_id=5001'}

这样一来,后面整份日志处理就会清楚很多。

你不再每次都在主循环里重复写正则。 而是把“如何解析一行日志”这件事,交给一个单独函数。

这就是结构化思维的价值。


二十一、再进一步:把日志中更细的字段也封装出来

例如我们希望一条日志最终被整理成这样:

{"time""2026-03-29 10:16:01","level""ERROR","message""支付接口调用失败","order_id""5001"}

可以进一步写解析函数:

import redefparse_log_line(line):    match = re.match(r"(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\s+(INFO|WARNING|ERROR)\s+(.*)", line.strip())ifnot match:returnNone    time_text = match.group(1)    level = match.group(2)    raw_message = match.group(3)    order_match = re.search(r"order_id=(\d+)", raw_message)    order_id = order_match.group(1if order_match elseNone    message = re.sub(r"order_id=\d+""", raw_message).strip()return {"time": time_text,"level": level,"message": message,"order_id": order_id    }

这就更像项目代码了。

因为日志原来只是普通字符串。 现在它已经变成了一个结构化字典。 后面你再统计、筛选、排序,就会容易很多。


二十二、把整份日志转成列表后,后面事情就顺了

例如我们先把每一行都解析成字典,放进一个列表里:

logs = []with open("app.log""r", encoding="utf-8"as f:for line in f:        parsed = parse_log_line(line)if parsed:            logs.append(parsed)print(logs)

这时候,logs 可能会变成这样:

[    {"time""2026-03-29 10:15:23""level""INFO""message""用户登录成功""order_id"None},    {"time""2026-03-29 10:16:01""level""ERROR""message""支付接口调用失败""order_id""5001"}]

看到这里你应该会有一个明显感受:

日志原本难处理,是因为它只是文本。 一旦转成列表加字典,整个世界都清楚了。

你可以按级别筛选,可以按时间排序,可以统计错误类型,可以导出表格。 这就是“把文本变成结构化数据”的力量。


二十三、做一个完整一点的小案例:统计错误类型、错误次数、最早时间

我们来写一个更像实战的小脚本。

假设日志格式如下:

2026-03-2910:16:01 ERROR 支付接口调用失败 order_id=50012026-03-2910:17:10 ERROR 数据库连接失败 db=mysql2026-03-2910:18:05 ERROR 支付接口调用失败 order_id=50022026-03-2910:19:20 ERROR 支付接口调用失败 order_id=50032026-03-2910:20:00 INFO 用户登录成功 user_id=1001

我们想要得到这些结果:

错误总数 每种错误分别出现几次 第一条错误发生在什么时候

代码可以这样写:

import refrom collections import Counterfrom datetime import datetimedefparse_error_message(message):    message = re.sub(r"order_id=\d+""", message)    message = re.sub(r"db=\w+""", message)return message.strip()error_messages = []error_times = []with open("app.log""r", encoding="utf-8"as f:for line in f:        match = re.match(r"(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\s+(INFO|WARNING|ERROR)\s+(.*)", line.strip())ifnot match:continue        time_text = match.group(1)        level = match.group(2)        message = match.group(3)if level == "ERROR":            clean_message = parse_error_message(message)            error_messages.append(clean_message)            dt = datetime.strptime(time_text, "%Y-%m-%d %H:%M:%S")            error_times.append(dt)print("错误总数:", len(error_messages))print("错误统计:", Counter(error_messages))if error_times:    print("第一条错误时间:", min(error_times))

这段代码已经非常接近日常日志分析脚本的样子了。


二十四、日志处理里还有一种很常见的需求:找某个用户做了什么

比如有些日志里会记录 user_id=1001。 这时候你可能想查:

这个用户今天都干了哪些操作 他在报错前做了什么 他是不是频繁请求某个接口

例如筛出某个用户的日志:

target_user = "1001"with open("app.log""r", encoding="utf-8"as f:for line in f:iff"user_id={target_user}"in line:            print(line.strip())

如果你愿意再往前走一步,也可以先提取所有用户 ID,再统计最活跃的用户。

你会发现,日志文本虽然表面普通,但实际上已经很像数据库里的记录了。 只不过它还没被正式整理出来而已。

而日志处理的过程,本质上就是在做这件事: 把文本里的行为记录,整理成可分析的数据。


二十五、日志处理特别适合和前面学过的知识联动

这一章其实就是前面很多知识点的一次综合应用。

字符串方法,用来做基础切分和清洗。 正则表达式,用来提取时间、级别、订单号、接口名、耗时。 时间处理,用来筛选某个时间段、计算先后顺序。 排序、去重、统计,用来总结日志规律。 函数式清洗思路,用来把解析逻辑写得更清晰。

所以如果你发现这一章有点像“综合题”,那是正常的。 因为真实工作里,本来就很少只考一个孤立知识点。

很多有价值的脚本,都是几种基础能力组合出来的。

而日志处理,恰好就是非常典型的组合型场景。


二十六、真实日志和练习日志最大的区别是什么

练习题里的日志通常都很干净。 格式统一,字段整齐,没有异常行。

但真实日志未必。

你可能会遇到:

空行 格式不完整的行 级别缺失 某些字段有时有,有时没有 时间格式偶尔不一致 消息内容里带额外空格或符号

所以写日志处理脚本时,一个特别重要的习惯就是:

不要默认每一行都完美。 要给异常情况留余地。

比如解析失败时直接跳过:

parsed = parse_log_line(line)if parsed isNone:continue

比如提取某个字段时,先判断匹配是否存在:

match = re.search(r"user_id=(\d+)", line)if match:    user_id = match.group(1)else:    user_id = None

这种“写得稳一点”的意识,和单纯会语法,是两回事。


二十七、给初学者一个非常实用的日志处理套路

以后你只要拿到一份日志,基本都可以按这个顺序想:

先观察格式。 看每一行大概由哪些部分组成。

再做基础筛选。 比如先找 ERROR,先找某个关键词。

然后提取结构。 把时间、级别、内容、附加字段拆出来。

接着清洗标准化。 去掉不重要的可变字段,让同类日志归到一起。

最后再统计和分析。 看数量、频次、时间分布、异常模式。

你按这个套路去处理,思路通常不会太乱。

最怕的是一上来就想一步到位,结果规则还没看清,代码已经写乱了。


二十八、这一章真正重要的,不只是会处理日志,而是会从文本里挖信息

你可以把日志看成一种特别典型的文本数据。 它比普通文章更规整,但又没有表格那么整洁。

所以学日志处理,本质上是在训练一种非常实用的能力:

面对一堆文本,能不能把里面有价值的信息提出来,并整理成可分析的结果。

这不只对日志有用。

以后你处理聊天记录、爬虫原始文本、服务器输出、命令行结果、系统导出文件,很多时候都在做类似的事。

所以这一章表面讲的是日志。 更深一层,讲的是文本信息提取和结构化分析能力。

这是非常有实战价值的一步。


本章小结

日志本质上是程序运行过程留下的文本记录。 它通常包含时间、级别、事件描述,以及各种补充字段。

日志处理的核心,不是把文件读出来就结束。 而是要把日志从一堆原始文本,逐步变成可筛选、可统计、可分析的结构化信息。

这一章你要重点掌握这些思路:

先按行处理日志。 先做关键词筛选,比如先找 ERROR。 能用 split() 解决的场景,不必一上来就用正则。 格式复杂时,用正则提取时间、级别、接口、用户 ID、耗时等字段。 把可变部分清洗掉,再做统计,结果会更可靠。 尽量把解析逻辑封装成函数,让代码更清楚、更像正式项目。

当你真正理解这一点,日志对你来说就不再只是“程序吐出来的一堆字”。 它会慢慢变成一份可以被提炼、被分析、被利用的数据来源。


课后练习

第一,准备一份简单日志文件,统计其中 ERROR 一共出现多少次。

第二,把日志中的 INFOWARNINGERROR 级别分别统计出来。

第三,写一个正则,把每行日志里的时间、级别、内容拆出来。

第四,从日志中提取所有 user_id 或 order_id,整理成列表。

第五,把错误日志的可变字段去掉后,再统计哪种错误最常见。

第六,筛选某个时间段内的日志,看看这段时间里到底发生了什么。

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-08-22 01:20:38 HTTP/2.0 GET : https://f.mffb.com.cn/a/504495.html
  2. 运行时间 : 0.278603s [ 吞吐率:3.59req/s ] 内存消耗:4,781.26kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=2aad8c8db5c3b06ac17c72000b339267
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.001145s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001521s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000850s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000715s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.001685s ]
  6. SELECT * FROM `set` [ RunTime:0.000632s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.001926s ]
  8. SELECT * FROM `article` WHERE `id` = 504495 LIMIT 1 [ RunTime:0.006179s ]
  9. UPDATE `article` SET `lasttime` = 1787332838 WHERE `id` = 504495 [ RunTime:0.057174s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.000641s ]
  11. SELECT * FROM `article` WHERE `id` < 504495 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.001121s ]
  12. SELECT * FROM `article` WHERE `id` > 504495 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.008553s ]
  13. SELECT * FROM `article` WHERE `id` < 504495 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.008695s ]
  14. SELECT * FROM `article` WHERE `id` < 504495 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.016064s ]
  15. SELECT * FROM `article` WHERE `id` < 504495 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.005252s ]
0.280229s