整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          5 種用 CSS 隱藏頁面元素的方法

          CSS 隱藏頁面元素有許多種方法。你可以將 opacity 設為 0、將 visibility 設為 hidden、將 display 設為 none 或者將 position 設為 absolute 然后將位置設到不可見區域。

          你有沒有想過,為什么我們要有這么多技術來隱藏元素,而它們看起來都實現的是同樣的效果?每一種方法實際上與其他方法之間都有一些細微的不同,這些 不同決定了在一個特定的場合下使用哪一個方法。這篇教程將覆蓋到那些你需要記住的細小不同點,讓你根據不同情況選擇上面這些方法中適合的方法來隱藏元素。

          opacity

          opacity 屬性的意思是設置一個元素的透明度。它不是為改變元素的邊界框(bounding box)而設計的。這意味著將 opacity 設為 0 只能從視覺上隱藏元素。而元素本身依然占據它自己的位置并對網頁的布局起作用。它也將響應用戶交互。

          .hide {
           opacity: 0;}

          如果你打算使用 opacity 屬性在讀屏軟件中隱藏元素,很不幸,你并不能如愿。元素和它所有的內容會被讀屏軟件閱讀,就像網頁上的其他元素那樣。換句話說,元素的行為就和它們不透明時一致。

          我還要提醒一句,opacity 屬性可以用來實現一些效果很棒的動畫。任何 opacity 屬性值小于 1 的元素也會創建一個新的堆疊上下文(stacking context)。

          看下面的例子:

          看 @SitePoint 提供的例子“用 opacity 隱藏元素”

          當你的鼠標移到被隱藏的第 2 個的區塊上,元素狀態平滑地從完全透明過渡到完全不透明。區塊也將 cursor 屬性設置為了 pointer,這說明了用戶可以與它交互。

          我自己是一名從事了多年開發的web前端老程序員,目前辭職在做自己的web前端私人定制課程,今年年初我花了一個月整理了一份最適合2019年學習的web前端學習干貨,各種框架都有整理,送給每一位前端小伙伴,想要獲取的可以關注我的頭條號并在后臺私信我:前端,即可免費獲取。

          visibility

          第二個要說的屬性是 visibility。將它的值設為 hidden 將隱藏我們的元素。如同 opacity 屬性,被隱藏的元素依然會對我們的網頁布局起作用。與 opacity 唯一不同的是它不會響應任何用戶交互。此外,元素在讀屏軟件中也會被隱藏。

          這個屬性也能夠實現動畫效果,只要它的初始和結束狀態不一樣。這確保了 visibility 狀態切換之間的過渡動畫可以是時間平滑的(事實上可以用這一點來用 hidden 實現元素的延遲顯示和隱藏——譯者注)。

          .hide {
           visibility: hidden;}

          下面的例子演示了 visibility 與 opacity 有怎樣的不同:

          看 @SitePoint 提供的例子“用 visibility 隱藏元素”

          注意,如果一個元素的 visibility 被設置為 hidden,同時想要顯示它的某個子孫元素,只要將那個元素的 visibility 顯式設置為 visible 即可(就如例子里面的 .o-hide p——譯者注)。嘗試只 hover 在隱藏元素上,不要 hover 在 p 標簽里的數字上,你會發現你的鼠標光標沒有變成手指頭的樣子。此時,你點擊鼠標,你的 click 事件也不會被觸發。

          而在 <div> 標簽里面的 <p> 標簽則依然可以捕獲所有的鼠標事件。一旦你的鼠標移動到文字上,<div> 本身變得可見并且事件注冊也隨之生效。

          display

          display 屬性依照詞義真正隱藏元素。將 display 屬性設為 none 確保元素不可見并且連盒模型也不生成。使用這個屬性,被隱藏的元素不占據任何空間。不僅如此,一旦 display 設為 none 任何對該元素直接打用戶交互操作都不可能生效。此外,讀屏軟件也不會讀到元素的內容。這種方式產生的效果就像元素完全不存在。

          任何這個元素的子孫元素也會被同時隱藏。為這個屬性添加過渡動畫是無效的,它的任何不同狀態值之間的切換總是會立即生效。

          不過請注意,通過 DOM 依然可以訪問到這個元素。因此你可以通過 DOM 來操作它,就像操作其他的元素。

          .hide {
           display: none;}

          看下面的例子:

          @SitePoint 提供的例子“用 display 隱藏元素”

          你將看到第二個塊元素內有一個 <p> 元素,它自己的 display 屬性被設置成 block,但是它依然不可見。這是 visibility:hidden 和 display:none 的另一個不同之處。在前一個例子里,將任何子孫元素 visibility 顯式設置成 visible 可以讓它變得可見,但是 display 不吃這一套,不管自身的 display值是什么,只要祖先元素的 display 是 none,它們就都不可見。

          現在,將鼠標移到第一個塊元素上面幾次,然后點擊它。這個操作將讓第二個塊元素顯現出來,它其中的數字將是一個大于 0 的數。這是因為,元素即使被這樣設置成對用戶隱藏,還是可以通過 JavaScript 來進行操作。

          position

          假設有一個元素你想要與它交互,但是你又不想讓它影響你的網頁布局,沒有合適的屬性可以處理這種情況(opacity 和 visibility 影響布局, display 不影響布局但又無法直接交互——譯者注)。在這種情況下,你只能考慮將元素移出可視區域。這個辦法既不會影響布局,有能讓元素保持可以操作。下面是采用這 種辦法的 CSS:

          .hide {
           position: absolute;
           top: -9999px;
           left: -9999px;}

          下面的例子闡明了怎樣通過絕對定位的方式隱藏元素,并讓它和前面的那個例子效果一樣:

          看 @SitePoint 提供的例子“用 position 屬性隱藏元素”

          這種方法的主要原理是通過將元素的 top 和 left 設置成足夠大的負數,使它在屏幕上不可見。采用這個技術的一個好處(或者潛在的缺點)是用它隱藏的元素的內容可以被讀屏軟件讀取。這完全可以理解,是因為你只是將元素移到可視區域外面讓用戶無法看到它。

          你得避免使用這個方法去隱藏任何可以獲得焦點的元素,因為如果那么做,當用戶讓那個元素獲得焦點時,會導致一個不可預料的焦點切換。這個方法在創建 自定義復選框和單選按鈕時經常被使用。(用 DOM 模擬復選框和單選按鈕,但用這個方法隱藏真正的 checkbox 和 radio 元素來“接收”焦點切換——譯者注)

          clip-path

          隱藏元素的另一種方法是通過剪裁它們來實現。在以前,這可以通過 clip 屬性來實現,但是這個屬性被廢棄了,換成一個更好的屬性叫做 clip-path。Nitish Kumar 最近在 SitePoint 發表了“介紹 clicp-path 屬性”這篇文章,通過閱讀它可以了解這個屬性的更多高級用法。

          記住,clip-path 屬性還沒有在 IE 或者 Edge 下被完全支持。如果要在你的 clip-path 中使用外部的 SVG 文件,瀏覽器支持度還要更低。使用 clip-path 屬性來隱藏元素的代碼看起來如下:

          .hide {
           clip-path: polygon(0px 0px,0px 0px,0px 0px,0px 0px);}

          下面是一個實際使用它的例子:

          看 @SitePoint 提供的例子“用 clip-path 屬性隱藏元素”

          如果你把鼠標懸停在第一個元素上,它依然可以影響第二個元素,盡管第二個元素已經通過 clip-path 隱藏了。如果你點擊它,它會移除用來隱藏的 class,讓我們的元素從那個位置顯現出來。被隱藏元素中的文字仍然能夠通過讀屏軟件讀取,許多 WordPress 站點使用 clip-path 或者之前的 clip來實現專門為讀屏軟件提供的文字。

          雖然我們的元素自身不再顯示,它也依然占據本該占據的矩形大小,它周圍的元素的行為就如同它可見時一樣。記住用戶交互例如鼠標懸停或者點擊在剪裁區 域之外也不可能生效。在我們的例子里,剪裁區大小為零,這意味著用戶將不能與隱藏的元素直接交互。此外,這個屬性能夠使用各種過渡動畫來實現不同的效果。

          結論

          在這篇教程里,我們看了 5 種不同的通過 CSS 隱藏元素的方法。每一種方法都與其他幾種有一點區別。知道你想要實現什么有助于你決定采用哪一個屬性,隨著時間推移,你就能根據實際需求本能地選擇最佳方式了。

          在CSS中很多隱藏元素的方法,但這些方法的可訪問性、布局、動畫、性能和事件處理的方式有所不同。

          • 「動畫:」 一些CSS隱藏元素的方法一般是全有或者全無,元素要么是完全可見,要么是完全不可見,并且沒有中間狀態。其他的,比如透明度,可以是一個范圍的值,所以在這中間過程插入動畫成為可能;
          • 「可訪問性:」 下面的每一種方法都會在視覺上隱藏一個元素,但不一樣會真正的去除DOM元素。有一些方式隱藏元素后,屏幕閱讀器仍然能讀取到元素內容;
          • 「事件處理:」 隱藏元素之后,有些方式元素上的事件仍然能被觸發,而有些方式就會導致元素上的事件觸發無效;
          • 「表現:」 瀏覽器加載并解析 HTML DOM 和 CSS 對象模型后,頁面將分三個階段呈現:布局(生成每個元素的幾何位置)、繪制(繪制每個元素的像素)、組合(以適當的順序放置元素層)。僅導致構圖變化的效果明顯比影響布局的效果更好。在某些情況下,瀏覽器還可以使用硬件加速。

          實現方式

          通過css實現隱藏元素方法有如下:

          1.display: none: 渲染樹不會渲染對象

          2.visibility: hidden: 元素在頁面中仍占據空間,但是不會響應綁定的監聽事件。

          3.opacity: 0: 元素在頁面中仍然占據空間,并且能夠響應元素綁定的監聽事件。

          4.position: absolute: 通過使用絕對定位將元素移除可視區域內,以此來實現元素的隱藏。

          5.z-index: 負值:來使其他元素遮蓋住該元素,以此來實現隱藏。

          6.clip/clip-path: 元素仍在頁面中占據位置,但是不會響應綁定的監聽事件。

          7.transform: scale(0,0): 將元素縮放為 0,元素仍在頁面中占據位置,但是不會響應綁定的監聽事件。

          8、color alpha 透明度

          9、可以通過使用width、height、padding、border-width 或 font-size 來縮小元素的尺寸

          10、覆蓋另一個元素

          11、transform 屬性可以用于元素的平移、縮放、旋轉或傾斜等。

          1. visibility: hidden;   這個屬性只是簡單的隱藏某個元素, 但是元素占用的空間任然存在 
          
          2. opacity: 0;   一個CSS3屬性, 設置 0 可以使一個元素完全透明, 制作出和 visibility 一樣的效果 。 與 visibility 相比, 它可以被 transition 和 animate 。
          
          3. position: absolute;    使元素脫離文檔流, 處于普通文檔之上, 給它設置一個很大的 left 負值定位, 使元素定位在可見區域之外 。
          
          4. display: none;  元素會變得不可見, 并且不會再占用文檔的空間 。
          
          5. transform: scale(0);   將一個元素設置為無限小, 這個元素將不可見 。 這個元素原來所在的位置將被保留 。
          
          6. HTML5 hidden attribute; hidden 屬性的效果和 display:none; 相同, 這個屬性用于記錄一個元素的狀態 。
          
          7. height: 0; overflow: hidden; 將元素在垂直方向上收縮為0, 使元素消失 。 只要元素沒有可見的邊框, 該技術就可以正常工作 。
          
          8. filter: blur(0); 將一個元素的模糊度設置為0, 從而使這個元素“消失”在頁面中 。

          display:none

          設置元素的displaynone是最常用的隱藏元素的方法

          .hide {
              display:none;
          }

          將元素設置為display:none后,元素在頁面上將徹底消失

          元素本身占有的空間就會被其他元素占有,也就是說它會導致瀏覽器的重排和重繪

          消失后,自身綁定的事件不會觸發,也不會有過渡效果

          特點:元素不可見,不占據空間,無法響應點擊事件

          color alpha 透明度

          可以將元素的color、background-color 和 border-color 等屬性設置為rgba(0,0,0,0),這樣就會使元素完全透明:

          div {
           color: rgba(0,0,0,0);
            background-color: rgba(0,0,0,0);
          }
          

          這三個屬性都是支持設置動畫效果的,需要注意,透明度不能應用于帶有背景圖片的元素,除非它們是使用 linear-gradient 或類似方法生成的。

          Alpha 通道可以設置為:

          • transparent:完全透明(中間不能插入動畫);
          • rgba(r, g, b, a):紅色、綠色、藍色和 alpha;
          • hsla(h, s, l, a):色相、飽和度、亮度和 alpha;
          • #RRGGBBAA 或 #RGBA。

          transform

          transform 屬性可以用于元素的平移、縮放、旋轉或傾斜等。可以使用 scale(0) 或者 translate(-9999px, 0px) 屬性值來將元素隱藏:

          div {
           transform: scale(0);
          }
          
          div {
           translate(-9999px, 0px)
          }
          

          transform 屬性提供了出色的性能和硬件加速,因為元素被有效地移動到了單獨的層中,并且可以在 2D 或 3D 中進行動畫處理。原始的布局空間會保持原樣,并不會受影響。使用這種方式隱藏的元素不會觸發任何事件。

          z-index

          可以通過將元素的 z-index 屬性設置為負值,以實現元素的隱藏。這實際上就是將元素放在了我們看不到的層。

          div {
            z-index: -1;
          }
          

          position

          position屬性允許使用top、bottom、left、right 從頁面中的默認位置移動元素。因此,絕對定位的元素可以通過左鍵:-9999px 等值移出屏幕:

          div {
            position: absolute;
            left: -999px;
          }
          

          覆蓋另一個元素

          通過在元素的上面放置與背景顏色相同的元素,可以在視覺上隱藏一個元素。下面來使用::after偽元素來實現:

          div::after {
            position: absolute;
            content: '';
            top: 0;
            bottom: 100%;
            left: 0;
            right: 0;
            background-color: #fff;
          }
          

          雖然這從技術上講是可以實現的,但是這樣做需要更多的代碼。

          縮小尺寸

          可以通過使用width、height、padding、border-width 或 font-size 來縮小元素的尺寸以實現元素的隱藏。可能還需要應用 overflow: hidden; 來確保內容不會溢出。

          div {
            height: 0;
            padding: 0;
            overflow: hidden;
          }
          

          使用這種形式我們可以在隱藏過程中使用動畫效果,并且他的性能會比 transform 好很多。

          visibility:hidden

          設置元素的visibilityhidden也是一種常用的隱藏元素的方法

          從頁面上僅僅是隱藏該元素,DOM結果均會存在,只是當時在一個不可見的狀態,不會觸發重排,但是會觸發重繪

          .hidden{
              visibility:hidden
          }

          給人的效果是隱藏了,所以他自身的事件不會觸發

          特點:元素不可見,占據頁面空間,無法響應點擊事件

          opacity:0

          opacity屬性表示元素的透明度,將元素的透明度設置為0后,在我們用戶眼中,元素也是隱藏的

          opacity: N 和 filter: opacity(N) 屬性可以傳遞一個 0 到 1 之間的數字,或者 0% 和 100% 之間的百分比,對應地表示完全透明和完全不透明。

          • opacity: N:該屬性用來設置元素的透明度;
          • filter: opacity(N) :filter屬性用來設置元素的濾鏡,opacity是濾鏡重的透明度,用來設置元素的透明度。

          不會引發重排,一般情況下也會引發重繪

          如果利用 animation 動畫,對 opacity 做變化(animation會默認觸發GPU加速),則只會觸發 GPU 層面的 composite,不會觸發重繪

          .transparent {
              opacity:0;
          }

          由于其仍然是存在于頁面上的,所以他自身的的事件仍然是可以觸發的,但被他遮擋的元素是不能觸發其事件的

          需要注意的是:其子元素不能設置opacity來達到顯示的效果

          特點:改變元素透明度,元素不可見,占據頁面空間,可以響應點擊事件

          在現代瀏覽器中,這兩者之間幾乎沒有實際的區別,但如果同時應用多種效果(模糊、對比度、灰度等)時,應該使用 filter 屬性。

          注意:opacity 可以設置動畫并提供出色的性能,但頁面上保留完全透明的元素可能會觸發事件。


          設置height、width屬性為0

          將元素的marginborderpaddingheightwidth等影響元素盒模型的屬性設置成0,如果元素內有子元素或內容,還應該設置其overflow:hidden來隱藏其子元素

          .hiddenBox {
              margin:0;     
              border:0;
              padding:0;
              height:0;
              width:0;
              overflow:hidden;
          }

          特點:元素不可見,不占據頁面空間,無法響應點擊事件

          position:absolute

          將元素移出可視區域

          .hide {
             position: absolute;
             top: -9999px;
             left: -9999px;
          }

          特點:元素不可見,不影響頁面布局

          clip-path

          通過裁剪的形式

          .hide {
            clip-path: polygon(0px 0px,0px 0px,0px 0px,0px 0px);
          }

          特點:元素不可見,占據頁面空間,無法響應點擊事件

          小結

          最常用的還是display:nonevisibility:hidden,其他的方式只能認為是奇招,它們的真正用途并不是用于隱藏元素,所以并不推薦使用它們

          區別

          關于display: nonevisibility: hiddenopacity: 0的區別,如下表所示:


          display: none

          visibility: hidden

          opacity: 0

          頁面中

          不存在

          存在

          存在

          重排

          不會

          不會

          重繪

          不一定

          自身綁定事件

          不觸發

          不觸發

          可觸發

          transition

          不支持

          支持

          支持

          子元素可復原

          不能

          不能

          被遮擋的元素可觸發事件

          不能

          代碼實現

          <!DOCTYPE html>
          <html lang="en">
          <head>
            <meta charset="UTF-8">
            <meta http-equiv="X-UA-Compatible" content="IE=edge">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title> CSS 幾種隱藏元素的方法(瑣碎知識點整理) </title>
          </head>
          
          <style>
          .w_vis-hid-outer {
            background-color: steelblue;
            display: flex;
            justify-content: flex-start;
            align-items: center;
            margin-bottom: 42px;
          }
          .w_vis-hid-outer p {
            line-height: 62px;
            padding: 0 24px;
          }
          .w_l-con {
            background-color: tomato;
          }
          .w_r-con {
            background-color: yellowgreen;
          }
          /* visibility: hidden 設置隱藏 */
          .w_now-vis {
            background-color: brown;
            margin: 0 12px;
            /* visibility: hidden; */
          }
          
          
          
          .w_opac-hid-outer {
            background-color: slategray;
            display: flex;
            justify-content: flex-start;
            align-items: center;
            padding: 0 12px;
            margin-bottom: 42px;
          }
          .w_opac-hid-outer p {
            line-height: 62px;
            padding: 0 24px;
          }
          .w_l-opa-con {
            background-color: snow;
          }
          .w_r-opa-con {
            background-color: tan;
          }
          /* opacity: 0  設置隱藏 */
          .w_now-opac {
            background-color: skyblue;
            margin: 0 12px;
            /* opacity: 0; */
          }
          
          
          
          .w_posi-hid-outer {
            background-color: slategray;
            display: flex;
            justify-content: flex-start;
            align-items: center;
            padding: 0 12px;
            margin-bottom: 42px;
          }
          .w_posi-hid-outer p {
            line-height: 62px;
            padding: 0 24px;
          }
          .w_l-pos-con {
            background-color: snow;
            margin-right: 12px;
          }
          .w_r-pos-con {
            background-color: tan;
            margin-left: 12px;
          }
          /* opacity: 0  設置隱藏 */
          .w_now-posi {
            background-color: skyblue;
            /* position: absolute; */
            /* left: -6666px; */
          }
          
          
          
          .w_disp-hid-outer {
            background-color: red;
            display: flex;
            justify-content: flex-start;
            align-items: center;
            padding: 0 12px;
            margin-bottom: 42px;
          }
          .w_disp-hid-outer p {
            line-height: 62px;
            padding: 0 24px;
          }
          .w_l-dis-con {
            background-color: #ccc;
            margin-right: 12px;
          }
          .w_r-dis-con {
            background-color: #212121;
            margin-left: 12px;
            color: #FFF;
          }
          /* display: none  設置隱藏 */
          .w_now-disp {
            background-color: blueviolet;
            /* display: none; */
          }
          
          
          .w_trans-hid-outer {
            background-color: darkorange;
            display: flex;
            justify-content: flex-start;
            align-items: center;
            padding: 0 12px;
            margin-bottom: 42px;
          }
          .w_trans-hid-outer p {
            line-height: 62px;
            padding: 0 24px;
          }
          .w_l-tran-con {
            background-color: #ccc;
            margin-right: 12px;
          }
          .w_r-tran-con {
            background-color: #212121;
            margin-left: 12px;
            color: #FFF;
          }
          /* transform: scale(0)  設置隱藏 */
          .w_now-trans {
            background-color: blueviolet;
            /* transform: scale(0); */
          }
          
          
          .w_hidd-hid-outer {
            background-color: darksalmon;
            display: flex;
            justify-content: flex-start;
            align-items: center;
            padding: 0 12px;
            margin-bottom: 42px;
          }
          .w_hidd-hid-outer p {
            line-height: 62px;
            padding: 0 24px;
          }
          .w_l-hid-con {
            background-color: steelblue;
            margin-right: 12px;
          }
          .w_r-hid-con {
            background-color: #212121;
            margin-left: 12px;
            color: #FFF;
          }
          /* hidden attribute  設置隱藏 (在 html 元素標簽上設置) */
          .w_now-hidd {
            background-color: red;
          }
          
          </style>
          <body>
            <div class="w_hide-shel">
              <!-- visibility: hidden  方法 -->
              <div class="w_vis-hid-outer">
                <p class="w_l-con">左側元素 -- 方法 1: visibility: hidden</p>
                <p class="w_now-vis">中間  隱藏  元素</p>
                <p class="w_r-con">右側元素  -- 方法 1: visibility: hidden</p>
              </div>
          
              <!-- opacity: 0  方法-->
              <div class="w_opac-hid-outer">
                <p class="w_l-opa-con">左側元素 -- 方法 2: opacity: 0</p>
                <p class="w_now-opac">中間  隱藏  元素</p>
                <p class="w_r-opa-con">右側元素  -- 方法 2: opacity: 0</p>
              </div>
          
              <!-- position: absolute 方法 -->
              <div class="w_posi-hid-outer">
                <p class="w_l-pos-con">左側元素 -- 方法 3: position: absolute</p>
                <p class="w_now-posi">中間  隱藏  元素</p>
                <p class="w_r-pos-con">右側元素  -- 方法 3: position: absolute</p>
              </div>
          
              <!-- display: none -->
              <div class="w_disp-hid-outer">
                <p class="w_l-dis-con">左側元素 -- 方法 4: display: none</p>
                <p class="w_now-disp">中間  隱藏  元素</p>
                <p class="w_r-dis-con">右側元素  -- 方法 4: display: none</p>
              </div>
          
              <!-- transform: scale(0) -->
              <div class="w_trans-hid-outer">
                <p class="w_l-tran-con">左側元素 -- 方法 5: display: none</p>
                <p class="w_now-trans">中間  隱藏  元素</p>
                <p class="w_r-tran-con">右側元素  -- 方法 5: display: none</p>
              </div>
          
              <!-- hidden attribute -->
              <div class="w_hidd-hid-outer">
                <p class="w_l-hid-con">左側元素 -- 方法 6: hidden attribute</p>
                <p class="w_now-hidd">中間  隱藏  元素</p>
                <!-- <p class="w_now-hidd" hidden="true">中間  隱藏  元素</p> -->
                <p class="w_r-hid-con">右側元素  -- 方法 6: hidden attribute</p>
              </div>
            </div>
          </body>
          </html>
          

          給大家分享我收集整理的各種學習資料,前端小白交學習流程,入門教程等回答-下面是學習資料參考。

          前端學習交流、自學、學習資料等推薦 - 知乎

          至少讓其更難抓取)

          這篇文章我翻譯自:https://github.com/JonasCz/How-To-Prevent-Scraping,因為最近在看一些反爬的資料,無意間在 Github 發現這篇文章,我覺得寫很全面,所以想要翻譯一下,順便進行吸收。另外讓我覺得非常贊的是這個文章從服務端和前端的角度都做了分析,我們應該從哪些點去做優化,而且每個點都舉了例子,有些還給出了注意點。雖然文中有些提到的一些點很基礎,也有很多我們目前在業務中也在使用,但是我還是從中吸收到了一些新東西,里面文中外部鏈接有很多,但是公眾號這里不允許外鏈,所以大家可以點擊文末最后的"閱讀原文"到 Github 去查看,Github Markdown 的排版可能也比這里更好 : )。

          (最后,有些倉促,可能有些注意不到的措別字,還請多多包涵)

          提示:這篇文章是我 Stack Overflow 這個問題回答的擴展,我把它整理在 Github 因為它實在是太長了,超過了 Stack Overflow 的字數限制(最多 3 萬個字,這文章已經超過 4 萬字)

          歡迎大家修改、完善還有分享,本文使用 CC-BY-SA 3.0 許可。

          本質上說,防抓的目的在于增加腳本或機器獲取你網站內容的難度,而不要影響真實用戶的使用或搜索引擎的收錄

          不幸的是這挺難的,你需要在防抓和降低真實用戶以及搜索引擎的可訪問性之間做一下權衡。

          為了防爬(也稱為網頁抓取、屏幕抓取、網站數據挖掘、網站收割或者網站數據獲取),了解他們的工作原理很重要,這能防止他們能高效爬取,這個就是這篇文章的主要內容。

          通常情況下,抓取程序的目的是為了獲取你網站特定的信息,比如文章內容、搜索結果、產品詳情還有網站上藝術家或者相冊信息。他們爬取這些內容用于維護他們自己的網站(甚至通過你的內容賺錢!),或者制作和你網站不一樣的前端界面(比如去做移動 APP),還有一些可能作為個人研究或分析使用。

          實際上,有特別多的爬蟲類型,而且他們的爬取方式都不太相同:

          • 蜘蛛,比如 Google's bot 或者網站復制工具 HTtrack,他們訪問你的網站,而且在頁面中尋找鏈接后遞歸的去爬取以獲取頁面的數據。有時候他們只用于獲取特定數據,而不會全部爬取,通常結合 HTML 分析器在頁面中獲取想要的數據。
          • Shell 腳本,有時候,通用的 Unix 工具也被用來爬取:wget 或者 curl 用于下載頁面,用 Grep (Regex) 去分析獲取想要的數據,一般都會寫一個 Shell 腳本。這些都是最簡單的爬蟲,也是最脆弱的一類爬蟲(Don't ever try parse HTML with regex !),所以是最早發現和防范的爬蟲。
          • HTML 爬取器和分析器,會基于 Jsoup、Scrapy 還有其他一些工具。和 shell 腳本基于正則類似,他們呢基于特定模式(pattern)分析你的 HTML 結構從而獲取想要的數據。舉個例子:如果你的網站有搜索功能,那這個爬蟲可能會模擬提交一個搜索的 HTTP 請求,然后從搜索結果頁中獲取所有的鏈接和標題,有時候會構造有成千上百不同的請求,只是為了獲取標題和鏈接而已。這是最常見的一類爬蟲。
          • 屏幕爬取,比如會基于 Selenium 或者 PhantomJS,他們實際上會通過真實瀏覽器打開你的網站,因此也會運行你網站的 JavaScript、AJAX 或者其他的,然后他們從你的頁面獲取自己想要的文本內容,通常:基于瀏覽器的爬取很難處理,他們運行腳本,渲染 HTML,就像真實用戶一樣訪問你的網站。
            • 等頁面加載完畢, JavaScript 也執行之后,從瀏覽器獲取 HTML 結構,然后用 HTML 分析器去獲取想要的數據或者文本。這是常見做法,所以有很多方法可以防止這類 HTML 分析器或爬蟲。
            • 獲取加載完頁面的屏幕截圖,然后使用 OCR 分析從截屏中獲取想要的數據。這類不唱將,而且只有非常想要你網站內容的爬蟲才會使用。
          • Web爬取服務,比如 ScrapingHub 或者 Kimono。實際上,很多人的工作就是找出如何爬取你的頁面獲取其中內容并給其他人使用。他們又是會用大量的代理甚至修改 IP 地址來繞過頻率限制和封禁,所以他們反爬的關鍵對象。毫無疑問,防止專業的爬取服務是非常困難的,但是如果你增加爬取的難度,或者增加他們找出爬取方法的時間,那這些人(或者付錢讓他們做的人)可能會放棄爬取你的網站。
          • 把你的網站頁面通過 frames 嵌入其他站點,或者把你的頁面嵌入移動 APP。雖然沒有什么技術含量,但是確實也是個問題,比如移動 APP(Android 和 iOS)可以嵌入你的網站,甚至可以注入一些自定義的 CSS 和 JavaScript,所以可以完全改變你網站的外觀,然后只展示想要的信息,比如只展示文章內容或者搜索結果,然后隱藏你網站的 headers、footers 還有廣告。
          • 人肉復制粘貼:人肉復制和粘貼你網站的內容到其他地方。很遺憾,這個沒有好的方法加以防范。

          以上不同的爬蟲類型有很多相同點,很多爬蟲的行為也很相似,即使他們使用了不同的技術或者方案去爬取你的內容。

          這些大多數都是我自己的想法,我在寫爬蟲時也遇到許多困難,還有一些是來源于網絡。

          如何反爬

          一些常見的檢測和防止爬蟲的方法:

          監控你的日志和請求;當發現異常行為時限制訪問

          周期性的檢查你的日志,如果發現有異常活動表明是自動爬取(爬蟲),類似某一個相同的 IP 很多相同的行為,那你就可以阻止或限制訪問。

          一些常用的方法:

          • 頻率限制
          • 只 允許用戶(或爬蟲)在一段時間內訪問特定的次數,舉個例子,某個 IP 或用戶只允許一分鐘搜索很少的次數。 這個會減慢爬蟲的爬取速度,讓他們變得低效。 如果次數特別多或者比真實用戶多很多,那你也可以顯示驗證碼頁面。
          • 檢測異常行為如果你能看到異常行為,比如同一個 IP 有很多相同的請求,有些會翻很多頁或者訪問一些異常的頁碼,你可以拒絕訪問或者在后續的請求中展示驗證碼。
        1. 不要只通過 IP 檢測和限制,也要用其他的用戶標識如果你做了訪問限制或頻率限制,不要只簡單的根據單個 IP 地址去做;你可以通過其他的標識和方法去識別一個用戶或爬蟲。一些可以幫你識別用戶/爬蟲的標識:
          • 用戶填寫表單的速度,還有他們點擊按鈕的位置
          • 你可以通過 JavaScript 獲取很多信息,比如屏幕的大小 / 分辨率,時區,安裝的字體等等,你可以用這些去識別用戶
          • 攜帶的 HTTP 頭,特別是 User-Agent

          舉個例子,如果某個 IP 請求了你網站很多次,所有的訪問都有相同的 UserAgent 、屏幕尺寸(JavaScript 檢測),還有全都使用同樣的方式和固定的時間間隔點擊同一個按鈕,那它大概是一個屏幕爬蟲;你可以臨時限制相似的請求(比如 只限制來自那個 IP 特定 User-Agent 和 屏幕尺寸的請求),這樣你不會誤傷同樣使用這個 IP 的真實用戶,比如共享網絡鏈接的用戶。

          更進一步,當你發現相似的請求,但是來自不同的 IP 地址,表明是分布式爬蟲(使用僵尸網絡或網絡代理的爬蟲)。如果你收到類似大量的請求,但是他們來自不同的 IP 地址,你可以拒絕訪問。再強調一下,小心不經意限制了真實用戶。

          這種方法對那種運行 JavaScript 的屏幕爬蟲比較有效,因為你可以獲得他們大量的信息。

          Stack Exchange 上關于 Secruity 的相關問題:

          How to uniquely identify users with the same external IP address?

          Why do people use IP address bans when IP addresses often change? 關于僅使用 IP 的其他限制

        2. 使用驗證碼,而不是臨時限制訪問對于頻率限制,最簡單的方式就是臨時限制訪問,然而使用驗證碼會更好,看下面關于驗證碼的部分。
        3. 要求注冊和登錄

          如果可行,要求創建用戶才可以查看你的內容。這個可以很好遏制爬蟲,但很容易遏制真實用戶:

          • 如果你要求必須創建賬戶和登錄,你可以精準跟蹤用戶和爬蟲的行為。這樣的話,你可以很簡單就能檢測到有爬取行為的賬戶,然后封禁它。像頻率限制或檢測濫用(比如段時間大量搜索)就變得簡單,你也可以不僅僅通過 IP 去識別爬蟲。

          為了防止爬蟲創建大量的用戶,你應該:

          • 注冊時需要提供 email 地址,發送一個驗證鏈接到郵箱,而且這個鏈接必須被打開才可以激活這個賬戶。一個郵箱只允許一個賬戶使用。
          • 在注冊或創建用戶時,必須通過驗證碼驗證,為了防止創建用戶的自動腳本。

          要求注冊用戶對用戶和搜索引擎來說不友好;如果你要求必須注冊才可以看文章,那用戶也可能直接離開。

          阻止來自云服務商和抓取服務的 IP

          有時爬蟲會被運行在云服務商,比如 Amazon Web Services 或 Google App Engine,或者其他 VPS。限制這些來自云服務商的 IP 地址訪問你的網站(或出驗證碼)。你可以可以直接對來自爬取服務的 IP 地址限制訪問。

          類似的,你也可以限制來自代理或 VPN 的 IP 地址,因為很多爬蟲會使用它們來防止被檢測到。

          但是要知道限制來自代理服務器或 VPN 的 IP,也很容易影響到真實用戶。

          當你封禁時不要展示具體錯誤信息

          如果你要封禁或限制訪問,你應該確保不要把導致封禁的原因告訴爬蟲,他們會根據提示修改自己的爬蟲程序。所以下面的這些錯誤最好不要出現:

          • 你的 IP 訪問太多次了,請重試
          • 錯誤,沒有 User Agent

          想法的,展示一些不包含原因的友好信息會更好,比如下面的信息會更好:

          • 對不起,有些不對勁。如果問題持續出現,你可以聯系 helpdesk@example.com 以獲取支持。

          如果真實用戶看到這個錯誤頁面,這個對真實用戶來說也十分友好。在后續訪問中,你也可以考慮展示驗證碼而不是直接封禁,如果真實用戶看到這個錯誤信息,對于合法用戶也會聯系你。

          如果有爬蟲訪問,請使用驗證碼

          驗證碼(Captcha,“Completely Automated Test to Tell Computers and Humans Apart”)對于防爬十分有效。不幸的是,它也很容易惹惱用戶。

          因此,如果你發現疑似爬蟲,而且想要阻止它的爬取行為,而不是封禁它以免它是真實用戶。你可以考慮顯示驗證碼在你再次允許訪問之前。

          使用驗證碼的注意事項:

          • 不要造輪子,使用類似 Google 的 reCaptcha 的一些服務:比你自己實現一套驗證碼服務要簡單太多,對于用戶來說,也比識別模糊或扭曲的文字更友好(用戶一般只需要點擊一下),而且相對于你自己提供的簡單驗證碼圖片,爬蟲也更難去破解
          • 不要在 HTML 結構中包含驗證碼答案:我曾經看到過一個網站在它自己頁面上有驗證碼的答案,(雖然隱藏很好)所以讓驗證碼根本就沒有用。不要做類似的事情。再強調一次,用像 reCaptcha 的服務,你將不會有類似的問題(如果你正確地使用它)

          將你的文字轉為圖片

          你可以在服務端將文字渲染成圖片顯示,他將防止簡單的爬蟲去獲取文字內容。

          然而,這個對于屏幕閱讀器、搜索引擎、性能還有一些其他一些事情都不太好。這個在某些方面也是不違法的(源于訪問性問題,eg. the Americans with Disabilities Act),而且對于一些 OCR 爬蟲也能非常簡單的規避,所以不要采用這種方式。

          你也可以用 CSS sprites 做類似的事情,但是也有相同的問題。

          不要暴露你完整的數據

          如果可以的話,不要讓腳本/爬蟲能獲取你所有的數據。舉個例子:你有一個新聞站,有大量的個人文章。你應該確保文章只能通過你自己網站的搜索到,如果你網站不是到處都有你的文章還有鏈接,那么確保它們只能被搜索功能訪問到。這意味著如果一個腳本想要獲取你網站的所有文章,就必須通過你站點文章中所有可能的短語去進行搜索,從而獲取所有的文章列表,但是這個會非常耗時,而且低效,從而讓爬蟲放棄。

          以下操作會讓你完全暴露:

          • 爬蟲/腳本并不想/需要獲取所有的數據
          • 你站點文章的鏈接看起來是這種方式 example.com/article.php?articleId=12345 ,這樣做(或類似的其他做法)會讓爬蟲很簡單的迭代 articleID 就能獲取你所有的文章
          • 還有一些其他方式獲取所有的文章,比如寫一個腳本去遞歸的爬取你文章中其他文章的鏈接
          • 搜索一些常用的詞比如 "一" 或者 "的" 將會暴露幾乎所有的內容。所以這點是要注意的(你可以通過只返回 top 10 或 top 20 來避免這個問題)
          • 你的文章需要被搜索引擎收錄

          不要暴露你的 API、節點或其他類似的東西

          確保你不會暴露你的任何 API,很多時候都是無意間暴露。舉個例子,如果你正在使用 AJAX 或 Adobe Flash 的網絡請求 或 Java Applet(千萬不要用!)來加載你的數據,從這些網絡請求中找到要請求的 API 十分簡單,比如可以進行反編譯然后在爬蟲程序中使用這些接口。確保你混淆了你的 API 并且其他人要用它會非常難破解。

          阻止 HTML 解析器和爬取器

          由于 HTML 解析器是通過分析頁面特定結構去獲取內容,我們可以故意修改這些結構來阻止這類爬蟲,甚至從根本上他們獲取內容。下面大多數做法對其他類型爬蟲如搜索引擎蜘蛛、屏幕爬蟲也有效。

          經常修改你的 HTML 結構

          處理 HTML 的爬蟲通過分析特定可識別的部分來處理 HTML。舉個例子:如果你所有的頁面都有 id 為 article-contentdiv 結構,然后里面有你的文章內容,那要獲取你站點所有文章內容是十分簡單的,只要解析那個 article-content 那個 div 就可以了,然后有這個結構的爬蟲就可以把你的文章隨便用在什么地方。

          如果你常常修改 HTML 還有你頁面的結構, 那這類爬蟲就不能一直使用。

          • 你可以經常修改你 HTML 的 idclass ,甚至讓他能自動改變。所以,如果你的 div.article-content 變成 div.a4c36dda13eaf0 ,而且每周都會變化,那么爬蟲一開始可能能正常工作,但是一周之后就不能使用了。同時也確保修改你 id/class的長度,這樣也可以避免爬蟲使用類似 div.[any-14-characters] 來找到想要的 div
          • 如果無法從標記中找到所需的內容,則抓取工具將通過HTML的結構方式進行查找。所以,如果你的所有文章都有類似的結構,比如每個 div ,并且里面通過 h1 放文章的標題,爬蟲將基于這個結構獲取文章內容。同樣的,為了防止這個,你可以在你的 HTML 添加/刪除 額外的標記,周期并且隨機做,eg. 添加額外的 divspan 。對于服務端渲染的程序,這應該不會很難。

          注意事項:

          • 它的實現、維護和調試都是很復雜困難的
          • 你要注意緩存。特別是你修改你 HTML 元素的 id 或 class 時,也要去修改相應的 CSS 和 JavaScript 文件,這意味著每次修改都要修改這些,而瀏覽器每次都要重新下載他們。這將導致頁面打開慢也會導致服務端負載升高。不過這也不是一個大問題,如果你只是一個星期改變一次。
          • 聰明的爬蟲仍然能推斷出你文章的位置,比如,頁面上大塊的文本大概率是文章內容。這個讓爬蟲從頁面找到、獲取想要的數據。Boilerpipe 就是這樣做的。

          本質上來說,就是確保爬蟲從相似頁面獲取想要的內容變得不那么容易。

          可以參考這個 PHP 的實現:How to prevent crawlers depending on XPath from getting page contents

          基于用戶地理位置修改 HTML

          這個和前一個類似。如果你根據不同用戶的位置/國家(根據 IP 獲取)來提供不同的 HTML,這個可能會破壞將站點 HTML 給用戶的爬蟲。比如,如果有人寫了一個移動 APP 來抓取你的站點,一開始可以用,但是對于不同地區的用戶就不起作用了,因為他們會獲取到不同的 HTML 結構,嵌入式的 HTML 將不不能正常使用。

          經常改變 HTML,并與爬蟲斗智斗勇!

          舉個例子:你有一個包含搜索功能的網站, example.com/search?query=somesearchquery 的搜索結果是下面的 HTML 結構:

          <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)
          

          你可以猜到這個非常容易爬取:一個爬蟲需要做的就只是訪問搜索鏈接,然后從返回的 HTML 分析想要的數據。除了定期修改上面 HTML 的內容,你也可以 保留舊結構的 id 和 class,然后使用 CSS 進行隱藏,并使用假數據進行填充,從而給爬蟲投毒 。比如像下面這樣:

          <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 獲取特定數據的爬蟲仍然能繼續工作,但是他們將會獲取假數據甚至廣告,而這些數據真實用戶是看不到的,因為他們被 CSS 隱藏了。

          與爬蟲斗智斗勇:在頁面插入假的、不可見的蜜罐數據

          對上個例子進行補充,你可以在你的 HTML 里面增加不可見的蜜罐數據來抓住爬蟲。下面的例子來補充之前說的搜索結果:

          <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.)
          

          一個來獲取所有內容的爬蟲將會被找到,就像獲取其他結果一樣,訪問鏈接,查找想要的內容。一個真人將不會看到(因為使用 CSS 隱藏),而且更不會訪問這個鏈接。而正規或者期望的蜘蛛比如谷歌的蜘蛛將不會訪問這個鏈接,因為你可以將 /scrapertrap/ 加入你的 robots.txt 中(不要忘記增加)

          你可以讓你的 scrapertrap.php 做一些比如限制這個 IP 訪問的事情,或者強制這個 IP 之后的請求出驗證碼。

          • 不要忘記在你的 robots.txt 中添加禁止訪問 /scrapertrap/ 的規則避免所有的搜索引擎不會中招
          • 你可以/應該和上個經常更換 HTML 結構的例子一起使用
          • 也要經常修改它,因為爬蟲可能會周期性的了解并不去訪問它。修改蜜罐 URL 和文本。同時要考慮使用 id 屬性或外部的 CSS 來取代內聯的 CSS,要不然爬蟲將會學會防止爬取所有包含隱藏屬性 style 的節點。并且只是偶爾啟用它, 這樣爬蟲一開始正常工作,但是過段時間就不起作用。這個同樣也適用于上個例子。
          • 要注意可能會有惡意的人在論壇發布像 [img]http://yoursite.com/scrapertrap/scrapertrap.php[img] ,然后當正常用戶訪問然后點擊到你的蜜罐鏈接。所以上個注意事項中經常更換你的蜜罐鏈接是非常重要的,當然你也可以檢查 Referer。

          當識別為爬蟲時,提供假的或無用的數據

          如果你確定某個訪問是爬蟲,你可以提供假的或者無用的數據;這將破壞爬蟲從你網站獲取的數據。你還應該把它和真實數據進行混淆,這樣爬蟲就不知道他們獲取的到底是真的還是假的數據。

          舉個例子:如果你有一個新聞站,你檢測到了一個爬蟲,不要去直接封禁它,而是提供假的或者隨機生成的文章,那爬蟲獲取的數據將會被破壞。如果你將假數據和真實的數據進行混淆,那爬蟲很難獲取到他們想要的真實文章。

          不要接受沒有 UserAgent 的請求

          很多懶惰的程序員不會在他們的爬蟲發請求時帶上 UserAgent,而所有的瀏覽器包括搜索引擎蜘蛛都會攜帶。

          如果請求你時沒有攜帶 UserAgent header 頭,你可以展示驗證碼,或者直接封禁或者限制訪問(或者像上面說的提供假數據或者其他的)

          這個非常簡單去避免,但是作為一種針對書寫不當的爬蟲,是值得去做的。

          不要接受 UserAgent 是通用爬蟲或在爬蟲黑名單的請求

          很多情況下,爬蟲將會使用真實瀏覽器或搜索引擎爬蟲絕對不會使用的 UserAgent,比如:

          • "Mozilla" (就只有這個,我曾經看到過一些爬蟲的問題用這個,但真實瀏覽器絕對不會用)
          • "Java 1.7.43_u43" (Java 的 HttpUrlConnection 的默認 UserAgent)
          • "BIZCO EasyScraping Studio 2.0"
          • "wget", "curl", "libcurl",.. (基礎爬蟲有時候會用 Wget 和 cURL)

          如果你發現一些爬蟲使用真實瀏覽器或合法蜘蛛絕對不會使用的 UserAgent,你可以將其添加到你的黑名單中。

          檢查 Referer header 頭

          對上一章節的補充,你也可以檢查 [Referer] (https://en.wikipedia.org/wiki/HTTP_referer header) (是的,它是 Referer,而不是 Referrer),一些懶惰的爬蟲可能不會攜帶的這個,或者只是每次都攜帶一樣的(有時候是 “google.com”)。舉個例子,如果用戶是從站內搜索結果頁點擊進入文章詳情的,那要檢查 Referer 這個 header 頭是否存在還要看搜索結果頁的打點。

          注意:

          • 真實瀏覽器并不總是攜帶 Referer;
          • 很容易被避免

          還是,作為一種防止簡單爬蟲的方法,也值得去實現。

          如果不請求資源(CSS,images),它可能不是真實瀏覽器

          一個真實瀏覽器(通常)會請求和下載資源比如 CSS 和 圖片。HTML 解析器和爬取器可能只關心特定的頁面和內容。

          你可以基于訪問你資源的日志,如果你看到很多請求只請求 HTML,那它可能就是爬蟲。

          注意搜索引擎蜘蛛、舊的移動設備、屏幕閱讀器和設置錯誤的設備可能也不會請求資源。

          要求使用 Cookie;使用它們來跟蹤用戶和爬蟲行為

          訪問你網站時,你可以要求 cookie 必須開啟。這個能識別沒有經驗和爬蟲新手,然而爬蟲要攜帶 Cookie 也十分簡單。如果你要求開啟 Cookie,你能使用它們來追蹤用戶和爬蟲的行為,然后基于此來實現頻率限制、封禁、或者顯示驗證碼而不僅僅依賴 IP 地址。

          舉個例子:當用戶進行搜索時,設置一個唯一的 Cookie。當搜索結果加載出來之后,驗證這個 Cookie。如果一個用戶打開了所有的搜索結果(可以從 Cookie 中得知),那很可能就是爬蟲

          使用 Cookie 可能是低效的,因為爬蟲也可以攜帶 Cookie 發送請求,也可以根據需要丟棄。如果你的網站只能在開啟 Cookie 時使用,你也不能關閉 Cookie 的用戶提供服務。

          要注意如果你使用 JavaScript 去設置和檢測 Cookie,你能封禁那些沒有運行 JavaScript 的爬蟲,因為它們沒辦法獲取和發送 Cookie。

          使用 JavaScript 和 AJAX 加載內容

          你可以在頁面加載完成之后,使用 JavaScript + AJAX 來加載你的內容。這個對于那些沒有運行 JavaScript 的 HTML 分析器來說將無法取得數據。這個對于沒有經驗或者新手程序員寫的爬蟲非常有效。

          注意:

          • 使用 JavaScript 加載內容將會降低用戶體驗和性能;
          • 搜索引擎也不會運行 JavaScript,因此不會對你的內容進行收錄。這對于搜索結果來說可能不是問題,但是要注意其他頁面,比如文章頁面;
          • 寫爬蟲的程序員獲取到加載內容的 API 后可以直接使用它

          混淆你的數據和網絡請求,不要讓其直接通過腳本就能獲取

          如果你用 Ajax 和 JavaScript 加載你的數據,在傳輸的時候要混淆一下。比如,你可以在服務器端 encode 你的數據(比如簡單的使用 base64 或 負載一些的多次混淆、位偏移或者是進行加密),然后在客戶端在 Ajax 獲取數據之后再進行 decode。這意味著如果有人要抓包獲取你的請求就不能直接看到你頁面如何加載數據,而且那些人也不能直接通過 API 獲得你的數據,如果想要獲取數據,就必須要去解密你的算法。

          • 如果你用 Ajax 加載數據,那你應該強制在頁面加載之后才可以獲取,比如要求獲取數據必須包含 session 信息,這些你可以在頁面加載的時候嵌入到 JavaScript 或 HTML 中
          • 你也可以直接把混淆的數據嵌入到 HTML 中,然后用 JavaScript 去解密然后再顯示它們,這樣的話,你就不需要再使用 Ajax 去做額外的請求。這樣做可以讓那些不運行 JavaScript 的 HTML 解析器更難獲取你的數據,他們必須要反解你的 JavaScript(沒錯,JavaScript 也要做混淆)
          • 你應該經常更換混淆方法以免爬蟲找出方法揭秘它

          下面是一些這個方式的缺點:

          • 實現、維護和調試都非常麻煩
          • 雖然讓爬蟲變得不容易抓取,但是對于截屏類的爬蟲來說,它們實際上會運行 JavaScript,所以能獲取到數據(不過很多簡單的 HTML 解釋器不會運行 JavaScript)
          • 如果真實用戶禁用了 JavaScript,那你的網站將不能正常顯示
          • 性能和頁面加載速度會受到影響

          其他非技術做法

          你的服務器供應商可能提供搜索引擎蜘蛛或爬蟲的防御:

          比如,CloudFlare 提供反蜘蛛和反爬蟲的防御,你只需要直接啟用它就可以了,另外 AWS 也提供類似服務。而且 Apache 的 mod_evasive 模塊也能讓你很輕松地實現頻率限制。

          直接告訴別人不要抓取,會有人尊重而且停止抓取

          你應該直接告訴人們不要抓取你的網站,比如,在你的服務條款中表明。有些人確實會尊重它,而且不在你允許的情況下不會再去抓取數據。

          尋求律師的援助

          律師們知道如何處理侵犯版權的事情,而且他們可以發送律師函。DMCA(譯者注:Digital Millennium Copyright Act,數字千年版權法案,是一個美國版權法律) 也能提供援助。

          直接提供 API 獲取你的數據

          這看起來適得其反,但是你可以要求標明來源并包含返回你站點的鏈接。甚至也可以售賣你的 API 而賺取費用。

          還有就是,Stack Exchange 提供了 API,但是必須要標明來源。

          其他補充

          • 要在用戶體驗和反爬之間做權衡:你做的每個舉措都有可能在某種程度上影響用戶體驗,所以你必須要權衡和妥協;
          • 不要忘你的移動站點和 APP:如果你的站點有移動版,要小心爬蟲也可以通過它爬取你的數據。或者說你有移動 APP,他們也可以截屏分析,或者可以抓取你的網絡請求去直接找到你的 RESTful 的 API 直接使用;
          • 如果你對一些特定瀏覽器提供了特定的版本,比如對很老的 IE 版本提供網站的閹割版,不要忘記爬蟲也可以直接爬取它;
          • 選出集中最適合你的策略結合起來使用,而不是只用一種;
          • 爬蟲可以抓取其他爬蟲:如果有個網站顯示的內容都是從你網站爬取的,那另外一個爬蟲也可以直接爬取那個網站。

          有哪些最有效的方法 ?

          以我自己寫和幫忙別人寫爬蟲的經驗,我認為最有效的方法是:

          • 經常修改 HTML 的結構
          • 蜜罐和假數據
          • 使用混淆的 JavaScript、Ajax 還有 Cookie
          • 頻率限制、爬蟲檢測和請求封禁

          擴展閱讀:

          • 維基百科關于 Web 爬蟲的文章,其中提到了很多 Web 爬蟲的相關技術和爬蟲類型,看完如何進行 web 爬取的一些信息,也不要忘記看一看爬取的合法性。

          最后祝你在保護你網站的內容坎坷路上一路順風...

          作者:h1z3y3

          來源:微信公眾號: 360搜索技術團隊

          出處:https://mp.weixin.qq.com/s?__biz=MzA5ODIxODE2Ng==&mid=2651137205&idx=1&sn=664a46d66f132c96780750d4e9b206eb


          主站蜘蛛池模板: 日本一区二区三区高清| 国产香蕉一区二区三区在线视频| 久久人妻内射无码一区三区| 午夜一区二区免费视频| 在线电影一区二区| 丰满少妇内射一区| 精品成人av一区二区三区| 国产激情一区二区三区在线观看| 乱精品一区字幕二区| 久久久一区二区三区| 日本不卡一区二区三区| 中文字幕一区视频一线| 无码人妻精品一区二区三区99仓本| 日韩精品一区二区三区不卡| 国产精品成人99一区无码| 日韩一区二区三区四区不卡| 麻豆一区二区99久久久久| 高清一区二区三区日本久| 久久精品国产一区二区三区日韩| 中文字幕精品无码一区二区三区| 国产观看精品一区二区三区| 一区二区三区杨幂在线观看| 亚洲国产精品一区二区第四页| 日韩AV在线不卡一区二区三区| 无码精品前田一区二区| 精品乱子伦一区二区三区高清免费播放| 激情综合丝袜美女一区二区| 精品一区二区三区在线播放| 制服丝袜一区二区三区| 国产激情视频一区二区三区| 无码人妻一区二区三区在线视频| 性色AV一区二区三区| 日韩国产免费一区二区三区| 亚洲午夜电影一区二区三区| 一区二区不卡在线| 波多野结衣一区二区免费视频 | 日本在线电影一区二区三区 | 无码精品视频一区二区三区| 精品一区二区三区四区在线播放 | 在线免费视频一区| 视频一区二区三区在线观看|