通过user-agent来源判断阻止爬虫访问网站,并防止生成[ error ] NULL日志
一、TP5.0通过行为(Behavior)拦截爬虫并避免生成 [ error ] NULL 错误日志
1. 创建行为类(拦截爬虫)
在 application/common/behavior 目录下新建BlockBot.php ,用于识别并拦截爬虫请求:
<?php
namespace app\common\behavior;use think\Response;class BlockBot
{// 爬虫User-Agent特征列表protected $botPatterns = ['/bot/i', '/spider/i', '/curl/i', '/wget/i', '/python/i', '/scrapy/i', '/crawl/i', '/httpclient/i',// 下面是自己添加的爬虫'/toutiao/i','/zhanzhang.toutiao.com/i','/dataforseo/i','/dataforseo.com/i','/dataforseo-bot/i','/semrush/i','/www.semrush.com/i','/YisouSpider/i',];// 白名单(搜索引擎合法爬虫)protected $allowPatterns = ['/googlebot/i', '/bingbot/i', '/baiduspider/i', '/Sogou web spider/i'];public function run(){$request = request();$userAgent = $request->header('user-agent', '');$path = $request->path();// 白名单放行foreach ($this->allowPatterns as $pattern) {if (preg_match($pattern, $userAgent)) {trace("放行{$pattern}爬虫: UA={$userAgent}, Path={$path}", 'info');return;}}// 黑名单拦截foreach ($this->botPatterns as $pattern) {if (preg_match($pattern, $userAgent)) {// 静默记录日志(不触发错误)trace("Blocked Bot: UA={$userAgent}, Path={$path}", 'info');// 静默拦截(不记录错误日志)$this->silentBlock();}}}/*** 静默拦截逻辑*/private function silentBlock(){// 返回404页面(或自定义响应)$response = Response::create()->code(404)->data('Access Denied')->header(['Content-Type' => 'text/plain']);// 终止后续执行throw new \think\exception\HttpResponseException($response);}}
2. 注册行为到请求事件
在 application/tags.php 中绑定行为到 app_init事件(应用初始化):
return [// 应用初始化'app_init' => ['app\\common\\behavior\\BlockBot', //爬虫拦截],
];
3. 自定义异常处理(防止错误日志)
(1) 创建异常处理类
在 application/common/exception 下新建 ExceptionHandler.php,覆盖默认错误处理:
<?php
namespace app\common\exception;use think\exception\Handle;
use think\exception\RouteNotFoundException;
use think\exception\ValidateException;
use think\Response;class ExceptionHandler extends Handle
{public function render(\Exception $e){// 拦截路由不存在错误(常见于爬虫探测)if ($e instanceof RouteNotFoundException) {return $this->silentResponse(404);}// 拦截参数验证错误(如分页参数过大)if ($e instanceof ValidateException) {return $this->silentResponse(400);}// 其他错误静默记录(可选)trace("Silent Error: " . $e->getMessage(), 'error');return parent::render($e);}/*** 静默响应(不记录日志)*/private function silentResponse($code){return Response::create()->code($code)->data('')->header(['Content-Type' => 'text/plain']);}
}
(2) 配置异常处理
在 application/config.php 中指定自定义异常处理器:
// 异常处理配置
'exception_handle' => 'app\common\exception\ExceptionHandler',
4. Nginx层优化(可选)
在服务器配置中拦截部分爬虫并静默处理:
server {listen 80;server_name yourdomain.com;# 拦截爬虫User-Agent并静默处理if ($http_user_agent ~* (bot|spider|python|curl|wget)) {access_log off; # 不记录访问日志return 444; # 静默关闭连接}# 不记录404错误日志error_page 404 = /404;location = /404 {internal;access_log off;}# ThinkPHP伪静态规则location / {if (!-e $request_filename) {rewrite ^(.*)$ /index.php?s=$1 last;break;}}
}
二、TP5.1或TP6.0通过中间件(middleware)拦截爬虫并避免生成 [ error ] NULL 错误日志
以TP5.1演示:
1. 创建拦截中间件(核心逻辑)
在 application/common/middleware 下新建 BlockBot.php,实现 双重防护:
<?php
namespace app\common\middleware;use think\Response;class BlockBot
{// 爬虫User-Agent特征列表protected $botPatterns = ['/bot/i', '/spider/i', '/curl/i', '/wget/i', '/python/i', '/scrapy/i', '/crawl/i', '/httpclient/i'];// 白名单(搜索引擎合法爬虫)protected $allowPatterns = ['/googlebot/i', '/bingbot/i', '/baiduspider/i'];public function handle($request, \Closure $next){$userAgent = $request->header('user-agent', '');$path = $request->pathinfo();// 放行白名单爬虫foreach ($this->allowPatterns as $pattern) {if (preg_match($pattern, $userAgent)) {return $next($request);}}// 拦截黑名单爬虫foreach ($this->botPatterns as $pattern) {if (preg_match($pattern, $userAgent)) {// 静默记录日志(不触发错误)trace("Blocked Bot: UA={$userAgent}, Path={$path}", 'info');// 直接返回404或403,避免后续逻辑执行return response('', 404)->header(['Content-Type' => 'text/html; charset=utf-8']);}}return $next($request);}
}
2. 注册中间件(全局生效)
修改 application/config.php 配置,确保中间件在最优先执行:
// 中间件配置
'middleware' => ['app\common\middleware\BlockBot', // 添加此行到最前面// ...其他中间件
],
3. 防止生成 [ error ] NULL 日志
(1) 自定义错误处理(覆盖ThinkPHP5默认行为)
在 application/config.php 中配置:
// 错误处理配置
'exception_handle' => 'app\common\exception\ExceptionHandler',
创建 application/common/exception/ExceptionHandler.php:
<?php
namespace app\common\exception;use think\exception\Handle;
use think\exception\RouteNotFoundException;
use think\exception\ValidateException;
use think\Response;class ExceptionHandler extends Handle
{public function render(\Exception $e){// 拦截路由不存在错误(常见于爬虫探测)if ($e instanceof RouteNotFoundException) {return $this->silentResponse(404);}// 拦截参数验证错误(如分页过大)if ($e instanceof ValidateException) {return $this->silentResponse(400);}// 其他错误按需处理(此处静默记录)trace("Silent Error: " . $e->getMessage(), 'error');return parent::render($e);}/*** 静默响应(不记录日志)*/private function silentResponse($code){return Response::create()->code($code)->data('')->header(['Content-Type' => 'text/plain']);}
}
(2) 配置日志过滤
修改 application/config.php 忽略部分错误类型:
// 日志配置
'log' => ['type' => 'File','level' => ['error', 'sql'],'apart_level' => ['error', 'sql'],'ignore_error' => [// 忽略路由不存在错误(避免生成 [ error ] NULL 日志)'think\exception\RouteNotFoundException',],
],
4. Nginx层优化(双重防护)
server {listen 80;server_name yourdomain.com;# 拦截爬虫User-Agent并静默处理if ($http_user_agent ~* (bot|spider|python|curl|wget)) {access_log off; # 不记录访问日志return 444; # 静默关闭连接}# FastAdmin伪静态规则location / {if (!-e $request_filename) {rewrite ^(.*)$ /index.php?s=$1 last;break;}}# 不记录404错误日志error_page 404 = /404.html;location = /404.html {internal;access_log off;}
}
注意:经查,网站一直写入[ error ] NULL日志,是因为框架文件thinkphp\library\think\App.php文件代码被恶意篡改

通过user-agent来源判断阻止爬虫访问网站,并防止生成[ error ] NULL日志
一、TP5.0通过行为(Behavior)拦截爬虫并避免生成 [ error ] NULL 错误日志 1. 创建行为类(拦截爬虫) 在 application/common/behavior 目录下新建BlockBot.php ,用于识别并拦截爬虫请求: <?php name…...
动态规划法:爬楼梯
假如你现在爬楼梯,需要n阶才能到达楼顶,每次可以爬1或2 台阶,你有多少中不同的方法可以爬到楼顶。 例如: 输入:n2 输出:2 //有两种方法可以到达楼顶,1阶1阶,2阶。 输入&…...

IBM BAW(原BPM升级版)使用教程第七讲
续前篇! 一、团队 在 IBM Business Automation Workflow (BAW) 中,团队(Team) 是流程管理的关键部分,用于定义参与某个流程的用户、角色、组以及服务等。在团队配置中,有许多重要概念,特别是 …...

【论文阅读】Efficient and secure federated learning against backdoor attacks
Efficient and secure federated learning against backdoor attacks -- 高效且安全的可抵御后门攻击的联邦学习 论文来源问题背景TLDR系统及威胁模型实体威胁模型 方法展开服务器初始化本地更新本地压缩高斯噪声与自适应扰动聚合与解压缩总体算法 总结优点缺点 论文来源 名称…...

Java中的代理机制
目录 什么叫代理 静态代理 优缺点 优点: 缺点: 动态代理 JDK动态代理 核心类 JDK动态代理的实现 步骤 示例 特点 CGLIB动态代理 代理机制对比 总结 什么叫代理 代理模式是一种比较好理解的设计模式。简单来说就是我们使用代理对象来代替…...
Kotlin扩展函数提升Android开发效率
在Android开发中,Kotlin的扩展函数(Extension Functions)犹如一把神奇的瑞士军刀,它能显著提升代码简洁性和开发效率。以下是通过实战案例展示的扩展函数魔法手册: 一、扩展函数基础原理 // 给View添加渐显动画扩展 f…...

Jenkins linux安装
jenkins启动 service jenkins start 重启 service jenkins restart 停止 service jenkins stop jenkins安装 命令切换到自己的下载目录 直接用命令下载 wget http://pkg.jenkins-ci.org/redhat-stable/jenkins-2.190.3-1.1.noarch.rpm 下载直接安装 rpm -ivh jenkins-2.190.3-…...
加速pip下载:永久解决网络慢问题
一文教你解决 pip 下载太慢了的问题 || 下载时因为网络不好中断下载的问题 一、找到 pip 配置文件路径 1.配置文件位置: Windows 系统的 pip 配置文件默认不存在,需要手动创建,路径为: C:\Users\你的用户名\pip\pip.ini 用户目…...
WPF 触发器 Trigger
触发器 Trigger 触发器(Trigger)是 WPF 中的一种机制: 当某个条件满足时,自动改变控件的某些属性,比如颜色、大小、透明度等。 换句话说,就是"如果……那么就……" 的一种规则。 常见触发器类…...

Webug4.0靶场通关笔记-靶场搭建方法(3种方法)
目录 一、虚拟机绿色版本 1. 开启phpstudy 2. 访问靶场 二、Docker版本 1.拉取镜像 2.启动镜像 三、源码安装版本 1. 搭建环境 (1)安装PHPStudy (2)WeBug4.0靶场源码 (3)安装Navicat ÿ…...
Python核心编程深度解析:作用域、递归与匿名函数的工程实践
引言 Python作为现代编程语言的代表,其作用域管理、递归算法和匿名函数机制是构建高质量代码的核心要素。本文基于Python 3.11环境,结合工业级开发实践,深入探讨变量作用域的内在逻辑、递归算法的优化策略以及匿名函数的高效应用,…...

【Web】LACTF 2025 wp
目录 arclbroth lucky-flag whack-a-mole arclbroth 看到username为admin能拿到flag 但不能重复注册存在的用户 这题是secure-sqlite这个库的问题,底层用的是C,没处理好\0字符截断的问题 (在 Node.js 中,由于其字符串表示方式…...

【日撸 Java 三百行】综合任务 1
目录 Day 10:综合任务 1 一、题目分析 1. 数据结构 2. 相关函数基本知识 二、模块介绍 1. 初始化与成绩矩阵的构建 2. 创建总成绩数组 3. 寻找成绩极值 三、代码与测试 小结 拓展:关于求极值的相关算法 Day 10:综合任务 1 Task&…...
yocto的每个recipe都是在工作路径中完成
Yocto项目中每个Recipe的编译过程都会将源文件解压或搬运到tmp/work/下的特定工作目录,并在此完成所有构建任务。具体流程可分为以下关键步骤: 一、源码处理阶段 源码获取(do_fetch) Recipe通过SRC_URI变量指定源码来源(如Git仓库、HTTP下载或本地文件)。这些文件会被下载…...
玩转Docker | 使用Docker部署DailyTxT日记工具
玩转Docker | 使用Docker部署DailyTxT日记工具 一、DailyTxT介绍DailyTxT简介DailyTxT 特点二、系统要求环境要求环境检查Docker版本检查检查操作系统版本三、部署DailyTxT服务下载DailyTxT镜像编辑部署文件创建容器检查容器状态检查服务端口安全设置四、访问DailyTxT服务访问D…...
初等数论--欧拉定理及证明
0. 证明前置知识 同余类(剩余类) r n ‾ { x ∣ x m n r , m ∈ Z } \overline{r_n} \{ x| xmnr,m \in Z\} rn{x∣xmnr,m∈Z} r n ‾ \overline{r_n} rn表示模 n n n后余 r r r的同余类(剩余类) 比如 2 5 ‾ { ⋯…...
Oracle非归档模式遇到文件损坏怎么办?
昨天夜里基地夜班的兄弟,打电话说有个报表库连不上了,赶紧起来连上VPN查看一下,看到实例宕机了,先赶紧startup起来。 1.查看报错信息 环境介绍:Redhat 6.9 Oracle 11.2.0.4 No Archive Mode 查看alert log 关键报…...
机器人领域和心理学领域 恐怖谷 是什么
机器人领域和心理学领域 恐怖谷 是什么 恐怖谷是一个在机器人领域和心理学领域备受关注的概念,由日本机器人专家森政弘于1970年提出。 含义 当机器人与人类的相似度达到一定程度时,人类对它们的情感反应会突然从积极变为消极,产生一种毛骨悚然、厌恶恐惧的感觉。这种情感…...
树莓派4的v4l2摄像头(csi)no cameras available,完美解决
根据2025年最新技术文档和树莓派官方支持建议,no cameras available错误通常由驱动配置冲突或硬件连接问题导致。以下是系统化解决方案: 一、核心修复步骤 强制禁用传统驱动 sudo nano /boot/firmware/config.txt确保包含以下配置(2025年新版…...
每日一题:两个仓库的最低配送费用问题
文章目录 两个仓库的最低配送费用问题一、问题描述二、解题思路(一)初始假设(二)差值定义(三)选择最优(四)计算答案 三、代码实现四、代码分析(一)输入处理&a…...

华为私有协议Hybrid
实验top图 理论环节 1. 基本概念 Hybrid接口: 支持同时处理多个VLAN流量,且能针对不同VLAN配置是否携带标签(Tagged/Untagged)。 核心特性: 灵活控制数据帧的标签处理方式,适用于复杂网络场景。 2. 工作…...
Redis 基本数据类型解析
Redis 是一个高效的内存数据存储系统,广泛应用于缓存、消息队列、排行榜、实时数据处理等场景。其高性能的特点部分源自其丰富的数据结构,Redis 提供了多种数据类型,能够支持不同的使用需求。本文将详细介绍 Redis 的八种基本数据类型。 1. …...

数据库实验10
设计性实验 1.实验要求 1.编写函数FsumXXX,1~n(参数)求和; GO CREATE FUNCTION Fsum065 (n INT) RETURNS INT AS BEGIN DECLARE sum INT 0 WHILE n > 0 BEGIN SET sum sum n SET n n - 1 END RETURN sum END …...
Yocto是如何使用$D目录来构建文件系统的?
Yocto最终会将所有Recipe的${D}(部署目录)下的文件整合到根文件系统中,但这一过程并非简单收集所有内容,而是通过分阶段打包、依赖管理和定制化配置实现的。以下是核心机制的解析: 一、${D}目录的作用与文件收集原理 ${D}的定位 ${D}是模拟目标系统根文件结构的临时目录(…...

jflash下载时出现 Could not read unit serial number! 的解决方法
出现的原因是由于Jlink原厂固件SN码是-1 我用的版本是v6.40 解决方法:添加序列号 1.打开:J-Link commander 之后在命令栏输入:exec setsnxxxxxxxx 2.添加序列号到license,打开J-Link License Manager V6.40 jlink-v640下载软件…...

Linux 信号终篇(总结)
前文:本文是对信号从产生到被处理的过程中的概念和原理的总结,如果想了解具体实现,请查看前两篇博客:Linux 信号-CSDN博客、Linux 信号(下篇)-CSDN博客 一、信号的产生 1.1 信号产生的五种条件 ①键盘组…...
使用Kotlin Flow实现Android应用的响应式编程
在Android应用中使用Kotlin Flow实现响应式编程可以分为以下步骤,结合最佳实践和生命周期管理: 1. 添加依赖 在build.gradle中确保包含协程和生命周期相关依赖: dependencies {implementation("org.jetbrains.kotlinx:kotlinx-corouti…...
react中的用法——setDisabled dva dispatch effects
setDisabled 在react中,setDisabled通常是指通过状态管理来控制某个组件(如按钮、输入框等)的禁用状态。虽然react本身没有内置的setDisabled方法,但你可以使用useState钩子来实现类似的功能。以下是一个简单的示例,展…...
(九)Java Object类的使用全面解析
一、Object类概述 1.1 Object类在Java中的地位 在Java语言中,Object类是所有类的超类,位于类继承树的顶端。它是Java类层次结构中的根类,每个类都直接或间接继承自Object类。当我们定义一个类时,如果没有明确使用extends关键字指…...

LVGL对象(Objects)
文章目录 🧱 一、LVGL 中的对象(lv\_obj)🔹 lv\_obj\_t 的作用 🧩 二、对象的分类结构(类比继承)🧰 三、对象的创建与销毁✅ 创建对象示例:创建一个按钮❌ 删除对象 &…...