反爬蟲策略,表面上看彷佛跟WEB系統優化沒有關係,通過分析,發現該策略是能夠歸到WEB性能優化的系列之中。javascript
經過分析apache日誌發現,某系統40%的帶寬和服務器資源都消耗在爬蟲上,若是除去10%-15%搜索引擎的爬蟲,作好反爬蟲策略,能節省20%-25%的資源,實際上是變向優化了web系統。java
1、爬蟲請求與正經常使用戶請求的區別web
爬蟲請求是相似httpClient的機制或curl,wget的命令,用戶請求通常走瀏覽器。shell
區別:爬蟲請求通常不會執行頁面裏的異步JavaScript操做,而用戶請求則執行Jquery提供的異步JavaScript操做,具體以下:apache
<script type="text/javascript">
$(document).ready(function(){
alertFunTest();
}
function alertFunTest() {
alert(「異步」);
}
</script >
代碼alert(「異步」)通常不會被爬蟲請求執行。網頁爬蟲
2、分析系統有多少爬蟲行爲後端
某系統某天的日誌分析以下:瀏覽器
cat access20110421.log | wc -l
2156293
cat page_access20110421.log | sort | uniq -c | sort -nr | head -n20
441421 /讀帖頁 20.4%
374274 /彈出框 17.3%
266984 /帖子點擊數 12.3%
213522 /讀取支持數和反支持數 9.9%
207269 /其它 9.6%
203567 /帖子列表頁 9.4%
185138 /刷新功能 8.5%
164884 /帖子列表點擊 7.6%
如上所示,帖子點擊數請求是不會被爬蟲執行的。緩存
(讀帖頁數-帖子點擊數)/ 讀帖頁數=爬蟲執行讀帖頁次數的比例性能優化
(441421 - 266984 )/ 441421=39.6%
結論:近40% 帖子的讀取操做是爬蟲行爲,讀帖佔系統85%以上的操做,也就是說近1/3以上的網絡和服務器資源在爲爬蟲服務。
3、請求在不一樣層面對應的反抓策略
(一)防火牆層面
經過netstat80端口的tcp鏈接量判斷IP是否非法。
WEB系統都是走http協議跟WEB容器連通的,每次請求至少會產生一次客戶端與服務器的tcp鏈接。經過netstat命令,就能夠查看到當前同時鏈接服務器所對應的IP以及鏈接量。
命令 /bin/netstat -nat -n | grep 80 通常都幾百或幾千個。
同一個IP對應的鏈接數超過咱們觀察到的一個閥值時,就可判斷爲非正常的用戶請求。閥值設定相當重要,大型網吧或同一個學校、公司出來的IP也可能會被誤判爲非法請求。
此策略我寫了兩個定時腳本去,一個定時封IP( tcpForbidCmd.sh ),一個定時釋放IP ( tcpReleaseCmd.sh ),分別是每隔5分鐘和40分鐘各執行一次
tcpForbidCmd.sh參考代碼以下:
#!/bin/sh
file=/home/songlin.lu/shell/log/forbid-ips-tmp.log
myIps=/home/songlin.lu/shell/log/noforbid_ips.log
today=`date +'%Y%m%d'`
logForbidIp=/home/songlin.lu/shell/log/forbid-iptables-logs-$today.log
netstatFile=/home/songlin.lu/shell/log/forbid-netstat-nat-tmp.log
/bin/netstat -nat -n > $netstatFile
nowDate=`date +'%Y-%m-%d %H:%M'`
/bin/awk -F: '/tcp/{a[$(NF-1)]++}END{for(i in a)if(a[i]>90)print i}' $netstatFile > $file
drop_ip=`cat $file |awk '{print $2}'`
for iptables_ip in $drop_ip
do
if [ $iptables_ip != $0 ] && [ -z "` iptables -L -n | grep DROP | awk '{print$4}'|grep $iptables_ip`" ] && [ -z "` cat $myIps |grep $iptables_ip`"];then
/sbin/iptables -A INPUT -s $iptables_ip -p tcp --dport 80 -j DROP
echo $iptables_ip >> /home/songlin.lu/shell/log/release-forbid-logs-tmp.log
echo '--------------------'$nowDate'----'$iptables_ip >> $logForbidIp
fi
done
文件/home/songlin.lu/shell/log/noforbid_ips.log爲白名單列表
tcpReleaseCmd.sh參考代碼以下:
#!/bin/sh
today=`date +'%Y%m%d'`
logReleaseIpLog=/home/songlin.lu/shell/log/release-iptables-log-$today.log
iptables=/home/songlin.lu/shell/log/release-iptables-save-tmp.log
tmpFile=/home/songlin.lu/shell/log/release-forbid-logs-tmp.log
/sbin/iptables-save > $iptables
drop_ips=`cat $tmpFile`
nowDate=`date +'%Y-%m-%d %H:%M'`
for iptables_ip1 in $drop_ips
do
if [ ! -z "`cat $iptables |awk /DROP/'{print $4}' | grep $iptables_ip1`" ]
then
/sbin/iptables -D INPUT -s $iptables_ip1 -p tcp --dport 80 -j DROP
echo '--------------------'$nowDate'----'$iptables_ip1 >> $logReleaseIpLog
fi
done
> $tmpFile
此策略至關於給咱們的系統設定了門檻,相似公路交通系統內,某馬路設定限高4米欄杆,高於4米的車不能在此通行。該策略能預防惡意的或新手寫的請求頻率不規則的爬蟲。
(二)WEB服務器容器層面
a.User-Agent判斷 b. connlimit模塊判斷
每一個爬蟲會聲明本身的User-Agent信息,咱們能夠經過判斷爬蟲的User-Agent信息來識別,具體查看相關文檔
Apache做connlimit須要mod_limitipconn來實現,通常須要手動編譯。
編輯httpd.conf文件,添加以下配置
ExtendedStatus On
LoadModule limitipconn_module modules/mod_limitipconn.so
< IfModule mod_limitipconn.c >
< Location / > # 全部虛擬主機的/目錄
MaxConnPerIP 20 # 每IP只容許20個併發鏈接
NoIPLimit image/* # 對圖片不作IP限制
< /Location>
< /IfModule>
Nginx做connlimit,限制ip併發數,比較簡單
添加limit_conn 這個變量能夠在http, server, location使用 如:limit_conn one 10;
(三)日誌層面
經過日誌和網站流量分析識別爬蟲
用awstats分析服務器日誌,用流量統計工具,如Google Analytics來統計IP對應的流量記錄,流量統計在網頁裏面嵌入一段js代碼。把統計結果和流量統計系統記錄的IP地址進行對比,排除真實用戶訪問IP,再排除咱們但願放行的網頁爬蟲,好比Google,百度,youdao爬蟲等。最後的分析結果就獲得爬蟲的IP地址。
(四)程序層面
時時反爬蟲過濾機制
實現起來也比較簡單,咱們能夠用memcached或本地內存來作訪問計數器,在緩存過時以前的時間段內(如3分鐘),每一個IP訪問一次,計數器加1,緩存的KEY包括IP,經過計數器獲得的值,判斷超過一個閥值,這個IP極可能有問題,那麼就能夠返回一個驗證碼頁面,要求用戶填寫驗證碼。若是是爬蟲的話,固然不可能填寫驗證碼,就被拒掉了,保護了後端的資源。
閥值的設定也是很重要的,不一樣的系統不同。
咱們將這個過濾機制改進一下,將更加準確。 即咱們在網頁的最下面添加一個JS的異步請求,此異步請求用來減計數器的值,進頁面時對IP進行加值,出頁面時減值,生成一個差值。 根據咱們以前的分析,爬蟲不會執行異步JS減值請求。 這樣能夠從生成的值的大小上判斷這個IP是否爲爬蟲。
程序邏輯以下圖所示:
[文章做者:狂奔的鹿(陸松林)本文版本:v1.0 轉載請註明原文連接:http://www.cnblogs.com/dynamiclu/]