Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
平常的樣式排版中,我們經(jīng)常遇到將某個(gè)模塊隱藏,下面我整理了一下隱藏元素的多種方法以及對(duì)比(有的占據(jù)空間,有的不占據(jù)空間。有的可以點(diǎn)擊,有的不能點(diǎn)擊。):
( 一 ) display: none;
特點(diǎn):元素不可見(jiàn),不占據(jù)空間,無(wú)法響應(yīng)點(diǎn)擊事件。
.hide{ display: none; }
( 二 ) opacity: 0; ( IE8以下版本:filter:Alpha(opacity=50) )
特點(diǎn):改變?cè)赝该鞫龋夭豢梢?jiàn),占據(jù)頁(yè)面空間,可以響應(yīng)點(diǎn)擊事件。
.hide{ opacity: 0; filter:Alpha(opacity=0); }
( 三 ) visibility: hidden;
特點(diǎn):元素不可見(jiàn),占據(jù)頁(yè)面空間,無(wú)法響應(yīng)點(diǎn)擊事件。
.hide{ visibility: hidden; }
( 四 ) transform: scale(0);
( 1 ) zoom: 0.1; transform: scale(0);
特點(diǎn):元素不可見(jiàn),IE 6 7 9 不占據(jù)頁(yè)面空間,IE8 谷歌 火狐 歐朋 等瀏覽器占據(jù)空間,無(wú)法響應(yīng)點(diǎn)擊事件。
.hide{ zoom: 0.1; transform: scale(0); -webkit-transform: scale(0); -moz-transform: scale(0); -ms-transform: scale(0); -o-transform: scale(0); }
( 2 ) position: absolute; zoom: 0.1; transform: scale(0);
特點(diǎn):元素不可見(jiàn),不占據(jù)頁(yè)面空間,無(wú)法響應(yīng)點(diǎn)擊事件。
.hide{ position: absolute; zoom: 0.1; transform: scale(0); -webkit-transform: scale(0); -moz-transform: scale(0); -ms-transform: scale(0); -o-transform: scale(0); }
( 五 ) width: 0; height: 0; 配合overflow: hidden;
特點(diǎn):元素不可見(jiàn),不占據(jù)頁(yè)面空間,無(wú)法響應(yīng)點(diǎn)擊事件。但 padding值 和 margin值 依然存在,需要將內(nèi)外邊距都調(diào)整為0。
.hide{ display: inline-block; width: 0; height: 0; padding: 0; margin: 0; overflow: hidden; }
( 六 ) position: absolute; left: -200%; 或者 top: -200%;等,父級(jí)需要相對(duì)定位,這種left top值可以根據(jù)具體的實(shí)際情況去定義
特點(diǎn):元素不可見(jiàn),不占據(jù)頁(yè)面空間,無(wú)法響應(yīng)點(diǎn)擊事件。
. father{ position: relative; overflow: hidden; } .hide{ position: absolute; left: -200%;//或top: -200%; }
( 七 ) clip-path: polygon(0px 0px,0px 0px,0px 0px,0px 0px)
特點(diǎn):元素不可見(jiàn),占據(jù)頁(yè)面空間,無(wú)法響應(yīng)點(diǎn)擊事件。
.hide{ float: left; width: 150px; margin: 20px; clip-path: polygon(0px 0px, 0px 0px, 0px 0px, 0px 0px); }
( 八 ) margin: top | right | bottom | left ;父級(jí)添加overflow: hidden; (margin的值 一定要小于(子級(jí)的寬度加上邊距的總和的負(fù)數(shù)))
特點(diǎn):元素不可見(jiàn),不占據(jù)頁(yè)面空間,無(wú)法響應(yīng)點(diǎn)擊事件。
.father{ width: 400px; height: 400px; overflow: hidden; } .hide{ display: inline-block; width: 200px; height: 200px; margin-left: -200px; }
以上就是幾種隱藏元素的方法,我在以前的面試中,也碰到了面試官提出的一些關(guān)于隱藏元素css的對(duì)比,查閱了一些資料,做了以下整理:
( 一 ) display: none 和 visibility: hidden 的區(qū)別
1. 占據(jù)頁(yè)面空間( display: none 將元素隱藏后,在頁(yè)面是是不占有空間位置的,而visibility: hidden 將元素隱藏后,還保留著元素大小的空間位置 ) ;
2. display: none 影響了 reflow和repaint(回流與重繪),而visibility: hidden并沒(méi)有影響
3. 某個(gè)模塊添加了display: none; 它下面的任何子級(jí)都會(huì)被隱藏,而添加了visibility: hidden,子級(jí)一旦有添加visibility: visible的css,該子級(jí)將不會(huì)被隱藏。
( 二 ) display: none 和 opacity: 0的區(qū)別
1. 占據(jù)頁(yè)面空間( display: none 將元素隱藏后,在頁(yè)面是是不占有空間位置的,而opacity: 0 只是改變了元素的透明度將其隱藏,還保留著元素大小的空間位置 ) ;
2. display: none 不會(huì)被子類(lèi)繼承,但是子類(lèi)一樣不會(huì)顯示。 opacity: 0 會(huì)被子類(lèi)繼承,但不能像visibility的屬性一樣,給子類(lèi)添加opacity:1,并不能將子類(lèi)顯示。
3. css3 transition 屬性對(duì)display:none 并無(wú)效果,但對(duì)opacity 則有效果。(附加一句,對(duì)visibility: hidden也無(wú)效果)
avaScript奇技淫巧:隱形字符
本文,分享一種奇特的JS編程技巧,功能是:可以使字符串“隱形”、不可見(jiàn)!
如下圖所示,一個(gè)字符串經(jīng)物別的操作之后,其長(zhǎng)度有621字節(jié),但內(nèi)容卻是“隱形”不可見(jiàn)的!
這個(gè)技術(shù)可以應(yīng)用到很多領(lǐng)域,非常具有實(shí)用性。
比如:代碼加密、數(shù)據(jù)加密、文字隱藏、內(nèi)容保密、隱形水印,等等。
實(shí)現(xiàn)字符串隱形,技術(shù)原理是“零寬字符”。
什么是“零寬字符”呢?
在Unicode編碼中,有一類(lèi)奇怪的字符格式,它們不可見(jiàn)、不可打印,主要用于調(diào)整字符的顯示格式。
常見(jiàn)零寬字符類(lèi)型:
空格符:格式為U+200B,用于較長(zhǎng)字符的換行分隔;
非斷空格符:格式為U+FEFF,用于阻止特定位置的換行分隔;
連字符:格式為U+200D,用于阿拉伯文與印度語(yǔ)系等文字中,使不會(huì)發(fā)生連字的字符間產(chǎn)生連字效果;
斷字符:格式為U+200C,用于阿拉伯文、德文、印度語(yǔ)系等文字中,阻止會(huì)發(fā)生連字的字符間的連字效果;
左至右符:格式為U+200E,用于在混合文字方向的多種語(yǔ)言文本中,規(guī)定排版文字書(shū)寫(xiě)方向?yàn)樽笾劣遥?/p>
右至左符:格式為U+200F : 用于在混合文字方向的多種語(yǔ)言文本中,規(guī)定排版文字書(shū)寫(xiě)方向?yàn)橛抑磷螅?/p>
在編程實(shí)現(xiàn)隱形字符功能時(shí),先將字符串轉(zhuǎn)為二進(jìn)制,再將二進(jìn)制中的1轉(zhuǎn)換為\u200b;0轉(zhuǎn)換為\u200c;空格轉(zhuǎn)換為\u200d,最后使用\ufeff 零寬度非斷空格符作分隔符。這幾種unicode字符都是不可見(jiàn)的,因此最終轉(zhuǎn)化完成并組合后,就會(huì)形成一個(gè)全不可見(jiàn)的“隱形”字符串。
function text_2_binary(text){
return text.split('').map(function(char){ return char.charCodeAt(0).toString(2)}).join(' ');
}
function binary_2_hidden_text(binary){
return binary.split('').map(function (binary_num){
var num = parseInt(binary_num, 10);
if (num === 1) {
return '\u200b';
} else if(num===0) {
return '\u200c';
}
return '\u200d';
}).join('\ufeff')
}
var text = "jshaman是專(zhuān)業(yè)且強(qiáng)大的JS代碼混淆加密工具";
var binary_text = text_2_binary(text);
var hidden_text = binary_2_hidden_text(binary_text);
console.log("原始字符串:",text);
console.log("二進(jìn)制:",binary_text);
console.log("隱藏字符:",hidden_text,"隱藏字符長(zhǎng)度:",hidden_text.length);
接下來(lái)介紹“隱形”后的內(nèi)容如何還原。
在了解上文內(nèi)容之后,知道了字符隱形的原理,再結(jié)合源代碼可知:還原隱形內(nèi)容,即進(jìn)行逆操作:將隱形的unicode編碼轉(zhuǎn)化成二進(jìn)制,再將二進(jìn)制轉(zhuǎn)成原本字符。
直接給出源碼:
function hidden_text_2_binary(string){
return string.split('\ufeff').map(function(char){
if (char === '\u200b') {
return '1';
} else if(char === '\u200c') {
return '0';
}
return ' ';
}).join('')
}
function binary_2_Text(binaryStr){
var text = ""
binaryStr.split(' ').map(function(num){
text += String.fromCharCode(parseInt(num, 2));
}).join('');
return text.toString();
}
console.log("隱形字符轉(zhuǎn)二進(jìn)制:",hidden_text_2_binary(hidden_text));
console.log("二進(jìn)制轉(zhuǎn)原始字符:",binary_2_Text(hidden_text_2_binary(hidden_text)));
運(yùn)行效果:
如果在代碼中直接提供“隱形”字符內(nèi)容,比如ajax通信時(shí),將“隱形”字符由后端傳給前端,并用以上解密方法還原,那么這種方式傳遞的內(nèi)容會(huì)是非常隱秘的。
但還是存在一個(gè)安全問(wèn)題:他人查看JS源碼,能看到解密函數(shù),這可能引起加密方法泄露、被人推導(dǎo)出加密、解密方法。
對(duì)此問(wèn)題,可以采用JS代碼混淆加密,進(jìn)一步提升整體JS代碼安全性。
用JShaman對(duì)上面兩個(gè)解密函數(shù)進(jìn)行代碼混淆加密。
如下圖,來(lái)到JShaman網(wǎng)站,貼入要加密的JS代碼:
使用如下配置:
得到加密的JS代碼:
將代碼粘貼回源文件中:
加密的JS代碼,運(yùn)行起來(lái)跟之前完全一樣。
但此時(shí),已不再是裸露的透明JS代碼,從這混亂復(fù)雜的代碼中很難看出功能邏輯。
注:“隱形字符”技術(shù),可用于前后端JS執(zhí)行環(huán)境,即可在Node.JS中執(zhí)行,也可在瀏覽器中使用。
這篇文章我翻譯自:https://github.com/JonasCz/How-To-Prevent-Scraping,因?yàn)樽罱诳匆恍┓磁赖馁Y料,無(wú)意間在 Github 發(fā)現(xiàn)這篇文章,我覺(jué)得寫(xiě)的很全面,所以想要翻譯一下,順便進(jìn)行吸收。另外讓我覺(jué)得非常贊的是這個(gè)文章從服務(wù)端和前端的角度都做了分析,我們應(yīng)該從哪些點(diǎn)去做優(yōu)化,而且每個(gè)點(diǎn)都舉了例子,有些還給出了注意點(diǎn)。雖然文中有些提到的一些點(diǎn)很基礎(chǔ),也有很多我們目前在業(yè)務(wù)中也在使用,但是我還是從中吸收到了一些新東西,里面文中外部鏈接有很多,但是公眾號(hào)這里不允許外鏈,所以大家可以點(diǎn)擊文末最后的"閱讀原文"到 Github 去查看,Github Markdown 的排版可能也比這里更好 : )。
(最后,有些倉(cāng)促,可能有些注意不到的措別字,還請(qǐng)多多包涵)
提示:這篇文章是我 Stack Overflow 這個(gè)問(wèn)題回答的擴(kuò)展,我把它整理在 Github 因?yàn)樗鼘?shí)在是太長(zhǎng)了,超過(guò)了 Stack Overflow 的字?jǐn)?shù)限制(最多 3 萬(wàn)個(gè)字,這文章已經(jīng)超過(guò) 4 萬(wàn)字)
歡迎大家修改、完善還有分享,本文使用 CC-BY-SA 3.0 許可。
不幸的是這挺難的,你需要在防抓和降低真實(shí)用戶(hù)以及搜索引擎的可訪(fǎng)問(wèn)性之間做一下權(quán)衡。
為了防爬(也稱(chēng)為網(wǎng)頁(yè)抓取、屏幕抓取、網(wǎng)站數(shù)據(jù)挖掘、網(wǎng)站收割或者網(wǎng)站數(shù)據(jù)獲取),了解他們的工作原理很重要,這能防止他們能高效爬取,這個(gè)就是這篇文章的主要內(nèi)容。
通常情況下,抓取程序的目的是為了獲取你網(wǎng)站特定的信息,比如文章內(nèi)容、搜索結(jié)果、產(chǎn)品詳情還有網(wǎng)站上藝術(shù)家或者相冊(cè)信息。他們爬取這些內(nèi)容用于維護(hù)他們自己的網(wǎng)站(甚至通過(guò)你的內(nèi)容賺錢(qián)!),或者制作和你網(wǎng)站不一樣的前端界面(比如去做移動(dòng) APP),還有一些可能作為個(gè)人研究或分析使用。
實(shí)際上,有特別多的爬蟲(chóng)類(lèi)型,而且他們的爬取方式都不太相同:
以上不同的爬蟲(chóng)類(lèi)型有很多相同點(diǎn),很多爬蟲(chóng)的行為也很相似,即使他們使用了不同的技術(shù)或者方案去爬取你的內(nèi)容。
這些大多數(shù)都是我自己的想法,我在寫(xiě)爬蟲(chóng)時(shí)也遇到許多困難,還有一些是來(lái)源于網(wǎng)絡(luò)。
一些常見(jiàn)的檢測(cè)和防止爬蟲(chóng)的方法:
周期性的檢查你的日志,如果發(fā)現(xiàn)有異常活動(dòng)表明是自動(dòng)爬取(爬蟲(chóng)),類(lèi)似某一個(gè)相同的 IP 很多相同的行為,那你就可以阻止或限制訪(fǎng)問(wèn)。
一些常用的方法:
舉個(gè)例子,如果某個(gè) IP 請(qǐng)求了你網(wǎng)站很多次,所有的訪(fǎng)問(wèn)都有相同的 UserAgent 、屏幕尺寸(JavaScript 檢測(cè)),還有全都使用同樣的方式和固定的時(shí)間間隔點(diǎn)擊同一個(gè)按鈕,那它大概是一個(gè)屏幕爬蟲(chóng);你可以臨時(shí)限制相似的請(qǐng)求(比如 只限制來(lái)自那個(gè) IP 特定 User-Agent 和 屏幕尺寸的請(qǐng)求),這樣你不會(huì)誤傷同樣使用這個(gè) IP 的真實(shí)用戶(hù),比如共享網(wǎng)絡(luò)鏈接的用戶(hù)。
更進(jìn)一步,當(dāng)你發(fā)現(xiàn)相似的請(qǐng)求,但是來(lái)自不同的 IP 地址,表明是分布式爬蟲(chóng)(使用僵尸網(wǎng)絡(luò)或網(wǎng)絡(luò)代理的爬蟲(chóng))。如果你收到類(lèi)似大量的請(qǐng)求,但是他們來(lái)自不同的 IP 地址,你可以拒絕訪(fǎng)問(wèn)。再?gòu)?qiáng)調(diào)一下,小心不經(jīng)意限制了真實(shí)用戶(hù)。
這種方法對(duì)那種運(yùn)行 JavaScript 的屏幕爬蟲(chóng)比較有效,因?yàn)槟憧梢垣@得他們大量的信息。
Stack Exchange 上關(guān)于 Secruity 的相關(guān)問(wèn)題:
How to uniquely identify users with the same external IP address?
Why do people use IP address bans when IP addresses often change? 關(guān)于僅使用 IP 的其他限制
如果可行,要求創(chuàng)建用戶(hù)才可以查看你的內(nèi)容。這個(gè)可以很好的遏制爬蟲(chóng),但很容易遏制真實(shí)用戶(hù):
為了防止爬蟲(chóng)創(chuàng)建大量的用戶(hù),你應(yīng)該:
要求注冊(cè)用戶(hù)對(duì)用戶(hù)和搜索引擎來(lái)說(shuō)不友好;如果你要求必須注冊(cè)才可以看文章,那用戶(hù)也可能直接離開(kāi)。
有時(shí)爬蟲(chóng)會(huì)被運(yùn)行在云服務(wù)商,比如 Amazon Web Services 或 Google App Engine,或者其他 VPS。限制這些來(lái)自云服務(wù)商的 IP 地址訪(fǎng)問(wèn)你的網(wǎng)站(或出驗(yàn)證碼)。你可以可以直接對(duì)來(lái)自爬取服務(wù)的 IP 地址限制訪(fǎng)問(wèn)。
類(lèi)似的,你也可以限制來(lái)自代理或 VPN 的 IP 地址,因?yàn)楹芏嗯老x(chóng)會(huì)使用它們來(lái)防止被檢測(cè)到。
但是要知道限制來(lái)自代理服務(wù)器或 VPN 的 IP,也很容易影響到真實(shí)用戶(hù)。
如果你要封禁或限制訪(fǎng)問(wèn),你應(yīng)該確保不要把導(dǎo)致封禁的原因告訴爬蟲(chóng),他們會(huì)根據(jù)提示修改自己的爬蟲(chóng)程序。所以下面的這些錯(cuò)誤最好不要出現(xiàn):
想法的,展示一些不包含原因的友好信息會(huì)更好,比如下面的信息會(huì)更好:
如果真實(shí)用戶(hù)看到這個(gè)錯(cuò)誤頁(yè)面,這個(gè)對(duì)真實(shí)用戶(hù)來(lái)說(shuō)也十分友好。在后續(xù)訪(fǎng)問(wèn)中,你也可以考慮展示驗(yàn)證碼而不是直接封禁,如果真實(shí)用戶(hù)看到這個(gè)錯(cuò)誤信息,對(duì)于合法用戶(hù)也會(huì)聯(lián)系你。
驗(yàn)證碼(Captcha,“Completely Automated Test to Tell Computers and Humans Apart”)對(duì)于防爬十分有效。不幸的是,它也很容易惹惱用戶(hù)。
因此,如果你發(fā)現(xiàn)疑似爬蟲(chóng),而且想要阻止它的爬取行為,而不是封禁它以免它是真實(shí)用戶(hù)。你可以考慮顯示驗(yàn)證碼在你再次允許訪(fǎng)問(wèn)之前。
使用驗(yàn)證碼的注意事項(xiàng):
你可以在服務(wù)端將文字渲染成圖片顯示,他將防止簡(jiǎn)單的爬蟲(chóng)去獲取文字內(nèi)容。
然而,這個(gè)對(duì)于屏幕閱讀器、搜索引擎、性能還有一些其他一些事情都不太好。這個(gè)在某些方面也是不違法的(源于訪(fǎng)問(wèn)性問(wèn)題,eg. the Americans with Disabilities Act),而且對(duì)于一些 OCR 爬蟲(chóng)也能非常簡(jiǎn)單的規(guī)避,所以不要采用這種方式。
你也可以用 CSS sprites 做類(lèi)似的事情,但是也有相同的問(wèn)題。
如果可以的話(huà),不要讓腳本/爬蟲(chóng)能獲取你所有的數(shù)據(jù)。舉個(gè)例子:你有一個(gè)新聞?wù)荆写罅康膫€(gè)人文章。你應(yīng)該確保文章只能通過(guò)你自己網(wǎng)站的搜索到,如果你網(wǎng)站不是到處都有你的文章還有鏈接,那么確保它們只能被搜索功能訪(fǎng)問(wèn)到。這意味著如果一個(gè)腳本想要獲取你網(wǎng)站的所有文章,就必須通過(guò)你站點(diǎn)文章中所有可能的短語(yǔ)去進(jìn)行搜索,從而獲取所有的文章列表,但是這個(gè)會(huì)非常耗時(shí),而且低效,從而讓爬蟲(chóng)放棄。
以下操作會(huì)讓你完全暴露:
確保你不會(huì)暴露你的任何 API,很多時(shí)候都是無(wú)意間暴露。舉個(gè)例子,如果你正在使用 AJAX 或 Adobe Flash 的網(wǎng)絡(luò)請(qǐng)求 或 Java Applet(千萬(wàn)不要用!)來(lái)加載你的數(shù)據(jù),從這些網(wǎng)絡(luò)請(qǐng)求中找到要請(qǐng)求的 API 十分簡(jiǎn)單,比如可以進(jìn)行反編譯然后在爬蟲(chóng)程序中使用這些接口。確保你混淆了你的 API 并且其他人要用它會(huì)非常難破解。
由于 HTML 解析器是通過(guò)分析頁(yè)面特定結(jié)構(gòu)去獲取內(nèi)容,我們可以故意修改這些結(jié)構(gòu)來(lái)阻止這類(lèi)爬蟲(chóng),甚至從根本上他們獲取內(nèi)容。下面大多數(shù)做法對(duì)其他類(lèi)型爬蟲(chóng)如搜索引擎蜘蛛、屏幕爬蟲(chóng)也有效。
處理 HTML 的爬蟲(chóng)通過(guò)分析特定可識(shí)別的部分來(lái)處理 HTML。舉個(gè)例子:如果你所有的頁(yè)面都有 id 為 article-content 的 div 結(jié)構(gòu),然后里面有你的文章內(nèi)容,那要獲取你站點(diǎn)所有文章內(nèi)容是十分簡(jiǎn)單的,只要解析那個(gè) article-content 那個(gè) div 就可以了,然后有這個(gè)結(jié)構(gòu)的爬蟲(chóng)就可以把你的文章隨便用在什么地方。
如果你常常修改 HTML 還有你頁(yè)面的結(jié)構(gòu), 那這類(lèi)爬蟲(chóng)就不能一直使用。
本質(zhì)上來(lái)說(shuō),就是確保爬蟲(chóng)從相似頁(yè)面獲取想要的內(nèi)容變得不那么容易。
可以參考這個(gè) PHP 的實(shí)現(xiàn):How to prevent crawlers depending on XPath from getting page contents
這個(gè)和前一個(gè)類(lèi)似。如果你根據(jù)不同用戶(hù)的位置/國(guó)家(根據(jù) IP 獲取)來(lái)提供不同的 HTML,這個(gè)可能會(huì)破壞將站點(diǎn) HTML 給用戶(hù)的爬蟲(chóng)。比如,如果有人寫(xiě)了一個(gè)移動(dòng) APP 來(lái)抓取你的站點(diǎn),一開(kāi)始可以用,但是對(duì)于不同地區(qū)的用戶(hù)就不起作用了,因?yàn)樗麄儠?huì)獲取到不同的 HTML 結(jié)構(gòu),嵌入式的 HTML 將不不能正常使用。
舉個(gè)例子:你有一個(gè)包含搜索功能的網(wǎng)站, example.com/search?query=somesearchquery 的搜索結(jié)果是下面的 HTML 結(jié)構(gòu):
<div class="search-result">
<h3 class="search-result-title">Stack Overflow has become the world's most popular programming Q & A website</h3>
<p class="search-result-excerpt">The website Stack Overflow has now become the most popular programming Q & A website, with 10 million questions and many users, which...</p>
<a class"search-result-link" href="/stories/stack-overflow-has-become-the-most-popular">Read more</a>
</div>
(And so on, lots more identically structured divs with search results)
你可以猜到這個(gè)非常容易爬取:一個(gè)爬蟲(chóng)需要做的就只是訪(fǎng)問(wèn)搜索鏈接,然后從返回的 HTML 分析想要的數(shù)據(jù)。除了定期修改上面 HTML 的內(nèi)容,你也可以 保留舊結(jié)構(gòu)的 id 和 class,然后使用 CSS 進(jìn)行隱藏,并使用假數(shù)據(jù)進(jìn)行填充,從而給爬蟲(chóng)投毒 。比如像下面這樣:
<div class="the-real-search-result">
<h3 class="the-real-search-result-title">Stack Overflow has become the world's most popular programming Q & A website</h3>
<p class="the-real-search-result-excerpt">The website Stack Overflow has now become the most popular programming Q & A website, with 10 million questions and many users, which...</p>
<a class"the-real-search-result-link" href="/stories/stack-overflow-has-become-the-most-popular">Read more</a>
</div>
<div class="search-result" style="display:none">
<h3 class="search-result-title">Visit example.com now, for all the latest Stack Overflow related news !</h3>
<p class="search-result-excerpt">EXAMPLE.COM IS SO AWESOME, VISIT NOW! (Real users of your site will never see this, only the scrapers will.)</p>
<a class"search-result-link" href="http://example.com/">Visit Now !</a>
</div>
(More real search results follow)
這意味著基于 id 或 class 獲取特定數(shù)據(jù)的爬蟲(chóng)仍然能繼續(xù)工作,但是他們將會(huì)獲取假數(shù)據(jù)甚至廣告,而這些數(shù)據(jù)真實(shí)用戶(hù)是看不到的,因?yàn)樗麄儽?CSS 隱藏了。
對(duì)上個(gè)例子進(jìn)行補(bǔ)充,你可以在你的 HTML 里面增加不可見(jiàn)的蜜罐數(shù)據(jù)來(lái)抓住爬蟲(chóng)。下面的例子來(lái)補(bǔ)充之前說(shuō)的搜索結(jié)果:
<div class="search-result" style="display:none">
<h3 class="search-result-title">This search result is here to prevent scraping</h3>
<p class="search-result-excerpt">If you're a human and see this, please ignore it. If you're a scraper, please click the link below :-)
Note that clicking the link below will block access to this site for 24 hours.</p>
<a class"search-result-link" href="/scrapertrap/scrapertrap.php">I'm a scraper !</a>
</div>
(The actual, real, search results follow.)
一個(gè)來(lái)獲取所有內(nèi)容的爬蟲(chóng)將會(huì)被找到,就像獲取其他結(jié)果一樣,訪(fǎng)問(wèn)鏈接,查找想要的內(nèi)容。一個(gè)真人將不會(huì)看到(因?yàn)槭褂?CSS 隱藏),而且更不會(huì)訪(fǎng)問(wèn)這個(gè)鏈接。而正規(guī)或者期望的蜘蛛比如谷歌的蜘蛛將不會(huì)訪(fǎng)問(wèn)這個(gè)鏈接,因?yàn)槟憧梢詫?/scrapertrap/ 加入你的 robots.txt 中(不要忘記增加)
你可以讓你的 scrapertrap.php 做一些比如限制這個(gè) IP 訪(fǎng)問(wèn)的事情,或者強(qiáng)制這個(gè) IP 之后的請(qǐng)求出驗(yàn)證碼。
如果你確定某個(gè)訪(fǎng)問(wèn)是爬蟲(chóng),你可以提供假的或者無(wú)用的數(shù)據(jù);這將破壞爬蟲(chóng)從你網(wǎng)站獲取的數(shù)據(jù)。你還應(yīng)該把它和真實(shí)數(shù)據(jù)進(jìn)行混淆,這樣爬蟲(chóng)就不知道他們獲取的到底是真的還是假的數(shù)據(jù)。
舉個(gè)例子:如果你有一個(gè)新聞?wù)荆銠z測(cè)到了一個(gè)爬蟲(chóng),不要去直接封禁它,而是提供假的或者隨機(jī)生成的文章,那爬蟲(chóng)獲取的數(shù)據(jù)將會(huì)被破壞。如果你將假數(shù)據(jù)和真實(shí)的數(shù)據(jù)進(jìn)行混淆,那爬蟲(chóng)很難獲取到他們想要的真實(shí)文章。
很多懶惰的程序員不會(huì)在他們的爬蟲(chóng)發(fā)請(qǐng)求時(shí)帶上 UserAgent,而所有的瀏覽器包括搜索引擎蜘蛛都會(huì)攜帶。
如果請(qǐng)求你時(shí)沒(méi)有攜帶 UserAgent header 頭,你可以展示驗(yàn)證碼,或者直接封禁或者限制訪(fǎng)問(wèn)(或者像上面說(shuō)的提供假數(shù)據(jù)或者其他的)
這個(gè)非常簡(jiǎn)單去避免,但是作為一種針對(duì)書(shū)寫(xiě)不當(dāng)?shù)呐老x(chóng),是值得去做的。
很多情況下,爬蟲(chóng)將會(huì)使用真實(shí)瀏覽器或搜索引擎爬蟲(chóng)絕對(duì)不會(huì)使用的 UserAgent,比如:
如果你發(fā)現(xiàn)一些爬蟲(chóng)使用真實(shí)瀏覽器或合法蜘蛛絕對(duì)不會(huì)使用的 UserAgent,你可以將其添加到你的黑名單中。
對(duì)上一章節(jié)的補(bǔ)充,你也可以檢查 [Referer] (https://en.wikipedia.org/wiki/HTTP_referer header) (是的,它是 Referer,而不是 Referrer),一些懶惰的爬蟲(chóng)可能不會(huì)攜帶的這個(gè),或者只是每次都攜帶一樣的(有時(shí)候是 “google.com”)。舉個(gè)例子,如果用戶(hù)是從站內(nèi)搜索結(jié)果頁(yè)點(diǎn)擊進(jìn)入文章詳情的,那要檢查 Referer 這個(gè) header 頭是否存在還要看搜索結(jié)果頁(yè)的打點(diǎn)。
注意:
還是,作為一種防止簡(jiǎn)單爬蟲(chóng)的方法,也值得去實(shí)現(xiàn)。
一個(gè)真實(shí)瀏覽器(通常)會(huì)請(qǐng)求和下載資源比如 CSS 和 圖片。HTML 解析器和爬取器可能只關(guān)心特定的頁(yè)面和內(nèi)容。
你可以基于訪(fǎng)問(wèn)你資源的日志,如果你看到很多請(qǐng)求只請(qǐng)求 HTML,那它可能就是爬蟲(chóng)。
注意搜索引擎蜘蛛、舊的移動(dòng)設(shè)備、屏幕閱讀器和設(shè)置錯(cuò)誤的設(shè)備可能也不會(huì)請(qǐng)求資源。
訪(fǎng)問(wèn)你網(wǎng)站時(shí),你可以要求 cookie 必須開(kāi)啟。這個(gè)能識(shí)別沒(méi)有經(jīng)驗(yàn)和爬蟲(chóng)新手,然而爬蟲(chóng)要攜帶 Cookie 也十分簡(jiǎn)單。如果你要求開(kāi)啟 Cookie,你能使用它們來(lái)追蹤用戶(hù)和爬蟲(chóng)的行為,然后基于此來(lái)實(shí)現(xiàn)頻率限制、封禁、或者顯示驗(yàn)證碼而不僅僅依賴(lài) IP 地址。
舉個(gè)例子:當(dāng)用戶(hù)進(jìn)行搜索時(shí),設(shè)置一個(gè)唯一的 Cookie。當(dāng)搜索結(jié)果加載出來(lái)之后,驗(yàn)證這個(gè) Cookie。如果一個(gè)用戶(hù)打開(kāi)了所有的搜索結(jié)果(可以從 Cookie 中得知),那很可能就是爬蟲(chóng)
使用 Cookie 可能是低效的,因?yàn)榕老x(chóng)也可以攜帶 Cookie 發(fā)送請(qǐng)求,也可以根據(jù)需要丟棄。如果你的網(wǎng)站只能在開(kāi)啟 Cookie 時(shí)使用,你也不能給關(guān)閉 Cookie 的用戶(hù)提供服務(wù)。
要注意如果你使用 JavaScript 去設(shè)置和檢測(cè) Cookie,你能封禁那些沒(méi)有運(yùn)行 JavaScript 的爬蟲(chóng),因?yàn)樗鼈儧](méi)辦法獲取和發(fā)送 Cookie。
你可以在頁(yè)面加載完成之后,使用 JavaScript + AJAX 來(lái)加載你的內(nèi)容。這個(gè)對(duì)于那些沒(méi)有運(yùn)行 JavaScript 的 HTML 分析器來(lái)說(shuō)將無(wú)法取得數(shù)據(jù)。這個(gè)對(duì)于沒(méi)有經(jīng)驗(yàn)或者新手程序員寫(xiě)的爬蟲(chóng)非常有效。
注意:
如果你用 Ajax 和 JavaScript 加載你的數(shù)據(jù),在傳輸?shù)臅r(shí)候要混淆一下。比如,你可以在服務(wù)器端 encode 你的數(shù)據(jù)(比如簡(jiǎn)單的使用 base64 或 負(fù)載一些的多次混淆、位偏移或者是進(jìn)行加密),然后在客戶(hù)端在 Ajax 獲取數(shù)據(jù)之后再進(jìn)行 decode。這意味著如果有人要抓包獲取你的請(qǐng)求就不能直接看到你頁(yè)面如何加載數(shù)據(jù),而且那些人也不能直接通過(guò) API 獲得你的數(shù)據(jù),如果想要獲取數(shù)據(jù),就必須要去解密你的算法。
下面是一些這個(gè)方式的缺點(diǎn):
比如,CloudFlare 提供反蜘蛛和反爬蟲(chóng)的防御,你只需要直接啟用它就可以了,另外 AWS 也提供類(lèi)似服務(wù)。而且 Apache 的 mod_evasive 模塊也能讓你很輕松地實(shí)現(xiàn)頻率限制。
你應(yīng)該直接告訴人們不要抓取你的網(wǎng)站,比如,在你的服務(wù)條款中表明。有些人確實(shí)會(huì)尊重它,而且不在你允許的情況下不會(huì)再去抓取數(shù)據(jù)。
律師們知道如何處理侵犯版權(quán)的事情,而且他們可以發(fā)送律師函。DMCA(譯者注:Digital Millennium Copyright Act,數(shù)字千年版權(quán)法案,是一個(gè)美國(guó)版權(quán)法律) 也能提供援助。
這看起來(lái)適得其反,但是你可以要求標(biāo)明來(lái)源并包含返回你站點(diǎn)的鏈接。甚至也可以售賣(mài)你的 API 而賺取費(fèi)用。
還有就是,Stack Exchange 提供了 API,但是必須要標(biāo)明來(lái)源。
以我自己寫(xiě)和幫忙別人寫(xiě)爬蟲(chóng)的經(jīng)驗(yàn),我認(rèn)為最有效的方法是:
擴(kuò)展閱讀:
作者:h1z3y3
來(lái)源:微信公眾號(hào): 360搜索技術(shù)團(tuán)隊(duì)
出處:https://mp.weixin.qq.com/s?__biz=MzA5ODIxODE2Ng==&mid=2651137205&idx=1&sn=664a46d66f132c96780750d4e9b206eb
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。