WordPress保卫战:用Python分析日志并封禁恶意爬虫

你是否遇到过这种情况:

  • 现象:你的WordPress博客突然变慢,甚至出现 502 Bad Gateway 错误。
  • 排查 :登录服务器查看 ​top​,发现 CPU 占用率飙升到 100%,PHP-FPM 进程多得吓人。
  • 真相:查看 Nginx 或 Apache 的访问日志,发现并没有多少真实人类在看文章,反而是大量的机器人在疯狂抓取。

为什么资源会紧张? WordPress 是动态网站,每一次页面访问都需要 PHP 解析和 MySQL 查询。如果一个爬虫每秒发起 10 个请求,对于一台配置较低(如 1核2G)的 VPS 来说,这就足以让数据库崩溃。

除了 Google、Bing 这种带来流量的"好爬虫",互联网上充斥着大量无用爬虫

  1. SEO工具爬虫(Ahrefs, Semrush, MJ12bot):对你没流量贡献,却疯狂消耗资源。
  2. 内容采集器:想把你的原创文章搬运走。
  3. bug扫描器 :疯狂探测 ​wp-login.php​​xmlrpc.php​

今天,我们不装臃肿的防火墙插件,而是用 Python 这种轻量级武器,从日志中揪出这些"资源吸血鬼",并在服务器层面直接封杀。


🛠️ 第一步:获取作案证据(访问日志)

首先,你需要找到 Web 服务器的访问日志(Access Log)。 通常在 Linux 服务器上,路径如下:

  • Nginx : ​/var/log/nginx/access.log​
  • Apache : ​/var/log/apache2/access.log​​/var/log/httpd/access_log​

把这个文件下载到本地,或者直接在服务器上用 Python 处理。


🐍 第二步:Python 编写"爬虫侦探"脚本

我们将编写一个 Python 脚本,完成以下任务:

  1. 解析日志文件。
  2. 统计 IP 的访问频率。
  3. 统计 User-Agent(用户代理)的分布。
  4. 自动生成封禁名单。

核心代码:​​analyze_bot.py​

python 复制代码
import re
from collections import Counter
import csv

# --- 配置区域 ---
LOG_FILE = 'access.log'  # 你的日志文件路径
THRESHOLD = 500          # 阈值:如果一个IP在日志中出现超过500次,视为可疑
OUTPUT_BAN_FILE = 'nginx_deny_list.conf' # 输出的封禁配置文件

# Nginx日志正则匹配模式 (根据你的日志格式调整,这是默认格式)
# 格式示例: 192.168.1.1 - - [23/Nov/2025:10:00:00 +0000] "GET / HTTP/1.1" 200 ...
LOG_PATTERN = re.compile(r'(?P<ip>\d+.\d+.\d+.\d+).*?"(?P<method>\w+) (?P<path>.*?) HTTP.*?" (?P<status>\d+) .*?"(?P<agent>.*?)"')

def analyze_logs():
    ip_counter = Counter()
    ua_counter = Counter()
    suspicious_ips = {} # 存储 {ip: user_agent}

    print(f"🔄 正在分析日志: {LOG_FILE} ...")
    
    with open(LOG_FILE, 'r', encoding='utf-8', errors='ignore') as f:
        for line in f:
            match = LOG_PATTERN.search(line)
            if match:
                data = match.groupdict()
                ip = data['ip']
                ua = data['agent']
                
                # 统计IP和UA
                ip_counter[ip] += 1
                ua_counter[ua] += 1
                
                # 记录最后一次该IP使用的UA,方便人工复核
                suspicious_ips[ip] = ua

    return ip_counter, ua_counter, suspicious_ips

def generate_report(ip_counts, ua_counts, suspicious_data):
    print("\n--- 📊 访问量 Top 10 IP ---")
    top_ips = ip_counts.most_common(10)
    for ip, count in top_ips:
        print(f"IP: {ip} | 次数: {count} | UA摘要: {suspicious_data[ip][:30]}...")

    print("\n--- 🤖 访问量 Top 10 User-Agents ---")
    for ua, count in ua_counts.most_common(10):
        print(f"次数: {count} | UA: {ua}")

    # 生成 Nginx 封禁列表
    print(f"\n--- 🚫 生成封禁建议 (超过 {THRESHOLD} 次访问) ---")
    banned_count = 0
    with open(OUTPUT_BAN_FILE, 'w') as f:
        f.write("# Auto-generated block list\n")
        for ip, count in ip_counts.items():
            if count > THRESHOLD:
                # 排除本地回环
                if ip.startswith('127.0.0'): continue 
                
                # 写入 Nginx 格式: deny 1.2.3.4;
                f.write(f"deny {ip};\n")
                banned_count += 1
    
    print(f"✅ 已生成配置文件: {OUTPUT_BAN_FILE}")
    print(f"🔨 建议封禁的 IP 数量: {banned_count}")

if __name__ == '__main__':
    try:
        ip_counts, ua_counts, suspicious_data = analyze_logs()
        generate_report(ip_counts, ua_counts, suspicious_data)
    except FileNotFoundError:
        print("❌ 错误:找不到日志文件,请检查路径。")

🕵️ 第三步:案例分析与实战操作

假设你运行了上面的代码,得到以下输出结果,我们来分析几个典型场景。

场景 A:暴力的 IP 采集者

脚本输出:

yaml 复制代码
IP: 45.132.xx.xx | 次数: 5000 | UA摘要: Python-urllib/3.8...

分析 :一个 IP 访问了 5000 次,User-Agent 竟然是 ​​Python-urllib​​。这意味着有人在写简陋的脚本暴力抓取你的站,完全没有伪装。 对策直接封杀 IP

场景 B:伪装成正常的 SEO 工具

脚本输出:

yaml 复制代码
次数: 2000 | UA: Mozilla/5.0 (compatible; MJ12bot/v1.4.8; ...)
次数: 1500 | UA: Mozilla/5.0 (compatible; SemrushBot/7~bl; ...)

分析 :MJ12bot 和 SemrushBot 是著名的 SEO 分析工具。它们不是恶意ddos,但它们抓取频率极高,而且对普通博客来说,这类商业 SEO 数据的价值远低于它们消耗的服务器资源。 对策通过 User-Agent 屏蔽

场景 C:恶意扫描

日志特征 : 脚本发现某个 IP 的 ​​path​​ 全是 ​​/wp-login.php​​, ​​.env​​, ​​sql.bak​​ 等。 分析 :这是在扫描bug,试图爆破后台。 对策立刻封杀,并安装 Fail2Ban 自动处理。


🛡️ 第四步:实施封锁

Python 帮我们找出了敌人,现在要在服务器层面进行拦截。

1. 基于 IP 的封禁 (Nginx)

Python 脚本已经生成了 ​​nginx_deny_list.conf​​,内容大致如下:

ini 复制代码
deny 45.132.11.22;
deny 103.21.33.44;

部署方法:

  1. 将该文件上传到 Nginx 配置目录(如 ​/etc/nginx/conf.d/​)。
  2. 在你的网站配置文件(​server​ 块内)引入它:
ini 复制代码
server {
    listen 80;
    server_name example.com;
    
    # 引入封禁列表
    include /etc/nginx/conf.d/nginx_deny_list.conf;
    
    location / {
        ...
    }
}
  1. 重载 Nginx:​sudo nginx -s reload​效果:这些 IP 访问时直接返回 403 Forbidden,甚至不消耗 PHP 资源。

2. 基于 User-Agent 的封禁 (Nginx)

针对那些换 IP 很勤快,但 UA 固定的爬虫(如 MJ12bot, AhrefsBot),直接在 Nginx 配置文件中添加判断:

bash 复制代码
server {
    # ... 其他配置
    
    # 禁止特定的 User-Agent
    if ($http_user_agent ~* (MJ12bot|AhrefsBot|SemrushBot|DotBot|PetalBot|Bytespider)) {
        return 403;
    }
}

注意:​Bytespider​​ 是字节跳动的爬虫,非常凶猛,如果是中文站且不需要今日头条的流量,建议限制或封禁。


🚀 进阶技巧:自动化防御 (Fail2Ban)

虽然 Python 脚本分析很有用,但手动跑太累。对于 WordPress,建议结合 Fail2Ban 实现自动化。

虽然 Fail2Ban 不是 Python 写的(虽然它现在也有 Python 绑定),但它的逻辑和我们上面的脚本一样:读日志 -> 正则匹配 -> 调用防火墙(iptables)封IP

简单的 WordPress 防爆破配置思路:

  1. 安装 Fail2Ban。
  2. 配置 Jail 监控 ​/var/log/auth.log​ 或 Nginx 日志。
  3. 规则:如果在 5 分钟内访问 ​wp-login.php​ 返回非 200 状态码超过 5 次,封禁 IP 1小时。

对于资源紧张的 WordPress 博客:

  1. 定期分析:使用提供的 Python 脚本定期(如每周)"体检",看看到底是谁在消耗你的 CPU。
  2. 狠心做减法:对于不带来直接流量的国外 SEO 爬虫(Ahrefs, MJ12等),建议直接在 Nginx 层屏蔽 User-Agent。
  3. 精确打击:对于异常高频的单个 IP,利用 Python 生成的黑名单直接 Deny。

通过这套组合拳,你会发现服务器负载会瞬间下降,博客又能秒开了!

相关推荐
nvd112 小时前
Gidgethub 使用指南
开发语言·python
___波子 Pro Max.2 小时前
Python模块导入详解与最佳实践
python
CNRio3 小时前
ZUC国密算法深度研究:原理、实现与应用(Python、Rust)
python·算法·rust
Python大数据分析@4 小时前
数据分析为什么常用Jupyter而不是直接使用Python脚本或Excel?
python·jupyter·数据分析
一株菌子4 小时前
10.9总结
开发语言·python
o***Z4484 小时前
Python包管理工具
开发语言·python
虹科网络安全5 小时前
艾体宝干货 | Redis Python 开发系列#4 保证原子性与性能
redis·python·junit
G***T6915 小时前
Python混合现实案例
python·pygame·mr
FreeCode5 小时前
LangGraph1.0智能体开发:选择API
python·langchain·agent