今天想对一个问题进行分析和讨论,就是关于爬虫对网站页面爬取的问题,有些网站通过爬虫去采集其它的网站页面信息作为己用,大量的爬取行为会对web服务器有比较性能有影响,主要的表现就是会变得很慢。
对于如何防止网站被爬取,我想从以下几种方法去分析:
1.基于程序本身去防止爬取:作为爬虫程序,爬取行为是对页面的源文件爬取,如爬取静态页面的html代码,可以用jquery去模仿写html,这种方法伪装的页面就很难被爬取了,不过这种方法对程序员的要求很高。

2.基于iptables和shell脚本:可以对nginx的access.log进行策略定义,例如定义在1分钟内并发连接数超过30个ip为非法,如ip不在白名单内,则加入iptables策略封掉,当然这种的缺点是会有“误伤”,策略细粒度越小就会有更多的“误伤”,细粒度大就会使效果变差,另外还有类似的第三方工具fail2ban,利用做filter和actor对一些有危害的操作记录或是封ip。但是对于某个特定的爬虫地址(例如网易、有道)的爬取行为拒绝也很难准确做到,因为你无法准确知道这些特定的爬虫ip地址(例如网易、有道),以下是我的定位方式,不过发现由于ip库不准确造成错误的屏蔽。注意:建议不要用封ip条目的方式,iptables列表长度是65535时就会封满,服务器也就会死机。
111812892.jpg
脚本如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

! /bin/bash

LOGFILE=/var/log/nginx/access.log
PREFIX=/etc/spiders

日志中大部分蜘蛛都有spider的关键字,但是百度的不能封,所以过滤掉百度

grep ‘spider’ LOGFILE|grep−v′Baidu′|awk′print$1′>PREFIX/ip1.txt

封掉网易的有道

grep ‘YoudaoBot’ LOGFILE|awk′print$1′>>PREFIX/ip1.txt

封掉雅虎

grep ‘Yahoo!’ LOGFILE|awk′print$1′>>PREFIX/ip1.txt

过滤掉信任IP

sort -n PREFIX/ip1.txt|uniq|sort|grep−v′192.168.0.′|grep−v′127.0.0.1′>PREFIX/ip2.txt

如果一小时内,发包不超过30个就要解封

/sbin/iptables -nvL |awk ‘1<=30print$8′>PREFIX/ip3.txt
for ip in cat $PREFIX/ip3.txt; do /sbin/iptables -D INPUT -s $ip -j DROP ; done
/sbin/iptables -Z // 将iptables计数器置为0
for ip in cat $PREFIX/ip2.txt; do /sbin/iptables -I INPUT -s $ip -j DROP ; done

3.使用robots.txt文件:例如阻止所有的爬虫爬取,但是这种效果不是很明显。
1
2
User-agent: *
Disallow: /

4.使用nginx的自带功能:通过对httpuseragent阻塞来实现,包括GET/POST方式的请求,以nginx为例,具体步骤如下:
编辑nginx.conf
1

vim /usr/local/nginx/conf/nginx.conf

拒绝以wget方式的httpuseragent,增加如下内容
1
2
3
4
5
6
7
8

Block http user agent - wget

if ($http_user_agent ~* (Wget) ) {
return 403;
}

Block Software download user agents

if ($http_user_agent ~* LWP::Simple|BBBike|wget) {
return 403;
}
平滑启动
1

/usr/local/nginx/sbin/nginx -s reload

如何拒绝多种http user agent,内容如下:
1
2
3
if ($http_user_agent ~ (agent1|agent2|Foo|Wget|Catall Spider|AcoiRobot) ) {
return 403;
}

大小写敏感匹配
1
2
3
4
5
6
7
8

大小写敏感http user agent拒绝

if ($http_user_agent ~ (Catall Spider|AcoiRobot) ) {
return 403;
}

大小写不敏感http user agent拒绝

if ($http_user_agent ~* (foo|bar) ) {
return 403;
}
注意语法:~*表示是大小写不敏感,~表示是大小写敏感