最近查看一个自己写的网站的时候,发现用来存放session文件的目录里面有超多的文件,居然rm ./*
的时候还报错说文件太多了 -_-|||
仔细想想应该是爬虫导致的,因为这个网站虽然并没有太多的访客,来的爬虫倒是不少。每个爬虫访问一次,就会产生一个session file。单纯靠php的gc
是不够了。只好想想怎么区分真正的访客和爬虫了。
一般访客访问的时候,应该是有页面的滚动动作,或者鼠标键盘的动作,所以可以靠这个来区分。
在页面上加上一段javascript
代码
<script>
function notRobot() {
document.cookie = "_notRobot_=1;path=/";
window.removeEventListener("scroll", notRobot);
window.removeEventListener("mousemove", notRobot);
window.removeEventListener("keypress", notRobot);
}
window.addEventListener("scroll", notRobot);
window.addEventListener("mousemove", notRobot);
window.addEventListener("keypress", notRobot);
</script>
所以当访客翻页/移动动鼠标/按下键盘的时候,就会设置一个cookie
,以便和爬虫区分开。
再修改服务器端的php代码,根据这个cookie来判断是否需要session_destroy()
if (session_status() === PHP_SESSION_ACTIVE && (!isset($_SESSION['robot']) || $_SESSION['robot'] !== 0)) {
if (isset($_COOKIE['_notRobot_']) && $_COOKIE['_notRobot_'] == 1)
$_SESSION['robot'] = 0;
else {
session_destroy();
}
}
当然这么做也有缺点。
首先是当一个访客第一次访问时,他在页面上做的所有动作都不会被记录,因为会被session_destroy()
。
第二个缺点是session文件会被建立再删除。当然也可以先判断$_COOKIE['_notRobot_']
,通过了才session_start()
。
然而第二个缺点也同时是优点,因为这样做可以把session_destroy()
放在末尾执行,对主体代码的影响比较小,所以如果主体代码依赖$_SESSION
变量的话会不需要进行任何改动。
此外这样做可以在第一次访问确认访客不是爬虫后,在第二次访问时把信息写入$_SESSION
,之后就不再需要通过_notRobot_
的cookie判断,于是可以让_notRobot_
的cookie过期,从而节省之后访问时的http头部开销。当然,服务器需要在判断访客不是爬虫时不再输出之前的javascript,以避免再次设置_notRobot_
的cookie。