整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

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 有很多相同的请求,有些会翻很多页或者访问一些异常的页码,你可以拒绝访问或者在后续的请求中展示验证码。
  • 不要只通过 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 的其他限制

  • 使用验证码,而不是临时限制访问对于频率限制,最简单的方式就是临时限制访问,然而使用验证码会更好,看下面关于验证码的部分。
  • 要求注册和登录

    如果可行,要求创建用户才可以查看你的内容。这个可以很好遏制爬虫,但很容易遏制真实用户:

    • 如果你要求必须创建账户和登录,你可以精准跟踪用户和爬虫的行为。这样的话,你可以很简单就能检测到有爬取行为的账户,然后封禁它。像频率限制或检测滥用(比如段时间大量搜索)就变得简单,你也可以不仅仅通过 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