平常的样式排版中,我们经常遇到将某个模块隐藏,下面我整理了一下隐藏元素的多种方法以及对比(有的占据空间,有的不占据空间。有的可以点击,有的不能点击。):
( 一 ) display: none;
特点:元素不可见,不占据空间,无法响应点击事件。
.hide{ display: none; }
( 二 ) opacity: 0; ( IE8以下版本:filter:Alpha(opacity=50) )
特点:改变元素透明度,元素不可见,占据页面空间,可以响应点击事件。
.hide{ opacity: 0; filter:Alpha(opacity=0); }
( 三 ) visibility: hidden;
特点:元素不可见,占据页面空间,无法响应点击事件。
.hide{ visibility: hidden; }
( 四 ) transform: scale(0);
( 1 ) zoom: 0.1; transform: scale(0);
特点:元素不可见,IE 6 7 9 不占据页面空间,IE8 谷歌 火狐 欧朋 等浏览器占据空间,无法响应点击事件。
.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);
特点:元素不可见,不占据页面空间,无法响应点击事件。
.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;
特点:元素不可见,不占据页面空间,无法响应点击事件。但 padding值 和 margin值 依然存在,需要将内外边距都调整为0。
.hide{ display: inline-block; width: 0; height: 0; padding: 0; margin: 0; overflow: hidden; }
( 六 ) position: absolute; left: -200%; 或者 top: -200%;等,父级需要相对定位,这种left top值可以根据具体的实际情况去定义
特点:元素不可见,不占据页面空间,无法响应点击事件。
. father{ position: relative; overflow: hidden; } .hide{ position: absolute; left: -200%;//或top: -200%; }
( 七 ) clip-path: polygon(0px 0px,0px 0px,0px 0px,0px 0px)
特点:元素不可见,占据页面空间,无法响应点击事件。
.hide{ float: left; width: 150px; margin: 20px; clip-path: polygon(0px 0px, 0px 0px, 0px 0px, 0px 0px); }
( 八 ) margin: top | right | bottom | left ;父级添加overflow: hidden; (margin的值 一定要小于(子级的宽度加上边距的总和的负数))
特点:元素不可见,不占据页面空间,无法响应点击事件。
.father{ width: 400px; height: 400px; overflow: hidden; } .hide{ display: inline-block; width: 200px; height: 200px; margin-left: -200px; }
以上就是几种隐藏元素的方法,我在以前的面试中,也碰到了面试官提出的一些关于隐藏元素css的对比,查阅了一些资料,做了以下整理:
( 一 ) display: none 和 visibility: hidden 的区别
1. 占据页面空间( display: none 将元素隐藏后,在页面是是不占有空间位置的,而visibility: hidden 将元素隐藏后,还保留着元素大小的空间位置 ) ;
2. display: none 影响了 reflow和repaint(回流与重绘),而visibility: hidden并没有影响
3. 某个模块添加了display: none; 它下面的任何子级都会被隐藏,而添加了visibility: hidden,子级一旦有添加visibility: visible的css,该子级将不会被隐藏。
( 二 ) display: none 和 opacity: 0的区别
1. 占据页面空间( display: none 将元素隐藏后,在页面是是不占有空间位置的,而opacity: 0 只是改变了元素的透明度将其隐藏,还保留着元素大小的空间位置 ) ;
2. display: none 不会被子类继承,但是子类一样不会显示。 opacity: 0 会被子类继承,但不能像visibility的属性一样,给子类添加opacity:1,并不能将子类显示。
3. css3 transition 属性对display:none 并无效果,但对opacity 则有效果。(附加一句,对visibility: hidden也无效果)
avaScript奇技淫巧:隐形字符
本文,分享一种奇特的JS编程技巧,功能是:可以使字符串“隐形”、不可见!
如下图所示,一个字符串经物别的操作之后,其长度有621字节,但内容却是“隐形”不可见的!
这个技术可以应用到很多领域,非常具有实用性。
比如:代码加密、数据加密、文字隐藏、内容保密、隐形水印,等等。
实现字符串隐形,技术原理是“零宽字符”。
什么是“零宽字符”呢?
在Unicode编码中,有一类奇怪的字符格式,它们不可见、不可打印,主要用于调整字符的显示格式。
常见零宽字符类型:
空格符:格式为U+200B,用于较长字符的换行分隔;
非断空格符:格式为U+FEFF,用于阻止特定位置的换行分隔;
连字符:格式为U+200D,用于阿拉伯文与印度语系等文字中,使不会发生连字的字符间产生连字效果;
断字符:格式为U+200C,用于阿拉伯文、德文、印度语系等文字中,阻止会发生连字的字符间的连字效果;
左至右符:格式为U+200E,用于在混合文字方向的多种语言文本中,规定排版文字书写方向为左至右;
右至左符:格式为U+200F : 用于在混合文字方向的多种语言文本中,规定排版文字书写方向为右至左;
在编程实现隐形字符功能时,先将字符串转为二进制,再将二进制中的1转换为\u200b;0转换为\u200c;空格转换为\u200d,最后使用\ufeff 零宽度非断空格符作分隔符。这几种unicode字符都是不可见的,因此最终转化完成并组合后,就会形成一个全不可见的“隐形”字符串。
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是专业且强大的JS代码混淆加密工具";
var binary_text = text_2_binary(text);
var hidden_text = binary_2_hidden_text(binary_text);
console.log("原始字符串:",text);
console.log("二进制:",binary_text);
console.log("隐藏字符:",hidden_text,"隐藏字符长度:",hidden_text.length);
接下来介绍“隐形”后的内容如何还原。
在了解上文内容之后,知道了字符隐形的原理,再结合源代码可知:还原隐形内容,即进行逆操作:将隐形的unicode编码转化成二进制,再将二进制转成原本字符。
直接给出源码:
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("隐形字符转二进制:",hidden_text_2_binary(hidden_text));
console.log("二进制转原始字符:",binary_2_Text(hidden_text_2_binary(hidden_text)));
运行效果:
如果在代码中直接提供“隐形”字符内容,比如ajax通信时,将“隐形”字符由后端传给前端,并用以上解密方法还原,那么这种方式传递的内容会是非常隐秘的。
但还是存在一个安全问题:他人查看JS源码,能看到解密函数,这可能引起加密方法泄露、被人推导出加密、解密方法。
对此问题,可以采用JS代码混淆加密,进一步提升整体JS代码安全性。
用JShaman对上面两个解密函数进行代码混淆加密。
如下图,来到JShaman网站,贴入要加密的JS代码:
使用如下配置:
得到加密的JS代码:
将代码粘贴回源文件中:
加密的JS代码,运行起来跟之前完全一样。
但此时,已不再是裸露的透明JS代码,从这混乱复杂的代码中很难看出功能逻辑。
注:“隐形字符”技术,可用于前后端JS执行环境,即可在Node.JS中执行,也可在浏览器中使用。
这篇文章我翻译自: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),还有一些可能作为个人研究或分析使用。
实际上,有特别多的爬虫类型,而且他们的爬取方式都不太相同:
以上不同的爬虫类型有很多相同点,很多爬虫的行为也很相似,即使他们使用了不同的技术或者方案去爬取你的内容。
这些大多数都是我自己的想法,我在写爬虫时也遇到许多困难,还有一些是来源于网络。
一些常见的检测和防止爬虫的方法:
周期性的检查你的日志,如果发现有异常活动表明是自动爬取(爬虫),类似某一个相同的 IP 很多相同的行为,那你就可以阻止或限制访问。
一些常用的方法:
举个例子,如果某个 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 的其他限制
如果可行,要求创建用户才可以查看你的内容。这个可以很好的遏制爬虫,但很容易遏制真实用户:
为了防止爬虫创建大量的用户,你应该:
要求注册用户对用户和搜索引擎来说不友好;如果你要求必须注册才可以看文章,那用户也可能直接离开。
有时爬虫会被运行在云服务商,比如 Amazon Web Services 或 Google App Engine,或者其他 VPS。限制这些来自云服务商的 IP 地址访问你的网站(或出验证码)。你可以可以直接对来自爬取服务的 IP 地址限制访问。
类似的,你也可以限制来自代理或 VPN 的 IP 地址,因为很多爬虫会使用它们来防止被检测到。
但是要知道限制来自代理服务器或 VPN 的 IP,也很容易影响到真实用户。
如果你要封禁或限制访问,你应该确保不要把导致封禁的原因告诉爬虫,他们会根据提示修改自己的爬虫程序。所以下面的这些错误最好不要出现:
想法的,展示一些不包含原因的友好信息会更好,比如下面的信息会更好:
如果真实用户看到这个错误页面,这个对真实用户来说也十分友好。在后续访问中,你也可以考虑展示验证码而不是直接封禁,如果真实用户看到这个错误信息,对于合法用户也会联系你。
验证码(Captcha,“Completely Automated Test to Tell Computers and Humans Apart”)对于防爬十分有效。不幸的是,它也很容易惹恼用户。
因此,如果你发现疑似爬虫,而且想要阻止它的爬取行为,而不是封禁它以免它是真实用户。你可以考虑显示验证码在你再次允许访问之前。
使用验证码的注意事项:
你可以在服务端将文字渲染成图片显示,他将防止简单的爬虫去获取文字内容。
然而,这个对于屏幕阅读器、搜索引擎、性能还有一些其他一些事情都不太好。这个在某些方面也是不违法的(源于访问性问题,eg. the Americans with Disabilities Act),而且对于一些 OCR 爬虫也能非常简单的规避,所以不要采用这种方式。
你也可以用 CSS sprites 做类似的事情,但是也有相同的问题。
如果可以的话,不要让脚本/爬虫能获取你所有的数据。举个例子:你有一个新闻站,有大量的个人文章。你应该确保文章只能通过你自己网站的搜索到,如果你网站不是到处都有你的文章还有链接,那么确保它们只能被搜索功能访问到。这意味着如果一个脚本想要获取你网站的所有文章,就必须通过你站点文章中所有可能的短语去进行搜索,从而获取所有的文章列表,但是这个会非常耗时,而且低效,从而让爬虫放弃。
以下操作会让你完全暴露:
确保你不会暴露你的任何 API,很多时候都是无意间暴露。举个例子,如果你正在使用 AJAX 或 Adobe Flash 的网络请求 或 Java Applet(千万不要用!)来加载你的数据,从这些网络请求中找到要请求的 API 十分简单,比如可以进行反编译然后在爬虫程序中使用这些接口。确保你混淆了你的 API 并且其他人要用它会非常难破解。
由于 HTML 解析器是通过分析页面特定结构去获取内容,我们可以故意修改这些结构来阻止这类爬虫,甚至从根本上他们获取内容。下面大多数做法对其他类型爬虫如搜索引擎蜘蛛、屏幕爬虫也有效。
处理 HTML 的爬虫通过分析特定可识别的部分来处理 HTML。举个例子:如果你所有的页面都有 id 为 article-content 的 div 结构,然后里面有你的文章内容,那要获取你站点所有文章内容是十分简单的,只要解析那个 article-content 那个 div 就可以了,然后有这个结构的爬虫就可以把你的文章随便用在什么地方。
如果你常常修改 HTML 还有你页面的结构, 那这类爬虫就不能一直使用。
本质上来说,就是确保爬虫从相似页面获取想要的内容变得不那么容易。
可以参考这个 PHP 的实现:How to prevent crawlers depending on XPath from getting page contents
这个和前一个类似。如果你根据不同用户的位置/国家(根据 IP 获取)来提供不同的 HTML,这个可能会破坏将站点 HTML 给用户的爬虫。比如,如果有人写了一个移动 APP 来抓取你的站点,一开始可以用,但是对于不同地区的用户就不起作用了,因为他们会获取到不同的 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 之后的请求出验证码。
如果你确定某个访问是爬虫,你可以提供假的或者无用的数据;这将破坏爬虫从你网站获取的数据。你还应该把它和真实数据进行混淆,这样爬虫就不知道他们获取的到底是真的还是假的数据。
举个例子:如果你有一个新闻站,你检测到了一个爬虫,不要去直接封禁它,而是提供假的或者随机生成的文章,那爬虫获取的数据将会被破坏。如果你将假数据和真实的数据进行混淆,那爬虫很难获取到他们想要的真实文章。
很多懒惰的程序员不会在他们的爬虫发请求时带上 UserAgent,而所有的浏览器包括搜索引擎蜘蛛都会携带。
如果请求你时没有携带 UserAgent header 头,你可以展示验证码,或者直接封禁或者限制访问(或者像上面说的提供假数据或者其他的)
这个非常简单去避免,但是作为一种针对书写不当的爬虫,是值得去做的。
很多情况下,爬虫将会使用真实浏览器或搜索引擎爬虫绝对不会使用的 UserAgent,比如:
如果你发现一些爬虫使用真实浏览器或合法蜘蛛绝对不会使用的 UserAgent,你可以将其添加到你的黑名单中。
对上一章节的补充,你也可以检查 [Referer] (https://en.wikipedia.org/wiki/HTTP_referer header) (是的,它是 Referer,而不是 Referrer),一些懒惰的爬虫可能不会携带的这个,或者只是每次都携带一样的(有时候是 “google.com”)。举个例子,如果用户是从站内搜索结果页点击进入文章详情的,那要检查 Referer 这个 header 头是否存在还要看搜索结果页的打点。
注意:
还是,作为一种防止简单爬虫的方法,也值得去实现。
一个真实浏览器(通常)会请求和下载资源比如 CSS 和 图片。HTML 解析器和爬取器可能只关心特定的页面和内容。
你可以基于访问你资源的日志,如果你看到很多请求只请求 HTML,那它可能就是爬虫。
注意搜索引擎蜘蛛、旧的移动设备、屏幕阅读器和设置错误的设备可能也不会请求资源。
访问你网站时,你可以要求 cookie 必须开启。这个能识别没有经验和爬虫新手,然而爬虫要携带 Cookie 也十分简单。如果你要求开启 Cookie,你能使用它们来追踪用户和爬虫的行为,然后基于此来实现频率限制、封禁、或者显示验证码而不仅仅依赖 IP 地址。
举个例子:当用户进行搜索时,设置一个唯一的 Cookie。当搜索结果加载出来之后,验证这个 Cookie。如果一个用户打开了所有的搜索结果(可以从 Cookie 中得知),那很可能就是爬虫
使用 Cookie 可能是低效的,因为爬虫也可以携带 Cookie 发送请求,也可以根据需要丢弃。如果你的网站只能在开启 Cookie 时使用,你也不能给关闭 Cookie 的用户提供服务。
要注意如果你使用 JavaScript 去设置和检测 Cookie,你能封禁那些没有运行 JavaScript 的爬虫,因为它们没办法获取和发送 Cookie。
你可以在页面加载完成之后,使用 JavaScript + AJAX 来加载你的内容。这个对于那些没有运行 JavaScript 的 HTML 分析器来说将无法取得数据。这个对于没有经验或者新手程序员写的爬虫非常有效。
注意:
如果你用 Ajax 和 JavaScript 加载你的数据,在传输的时候要混淆一下。比如,你可以在服务器端 encode 你的数据(比如简单的使用 base64 或 负载一些的多次混淆、位偏移或者是进行加密),然后在客户端在 Ajax 获取数据之后再进行 decode。这意味着如果有人要抓包获取你的请求就不能直接看到你页面如何加载数据,而且那些人也不能直接通过 API 获得你的数据,如果想要获取数据,就必须要去解密你的算法。
下面是一些这个方式的缺点:
比如,CloudFlare 提供反蜘蛛和反爬虫的防御,你只需要直接启用它就可以了,另外 AWS 也提供类似服务。而且 Apache 的 mod_evasive 模块也能让你很轻松地实现频率限制。
你应该直接告诉人们不要抓取你的网站,比如,在你的服务条款中表明。有些人确实会尊重它,而且不在你允许的情况下不会再去抓取数据。
律师们知道如何处理侵犯版权的事情,而且他们可以发送律师函。DMCA(译者注:Digital Millennium Copyright Act,数字千年版权法案,是一个美国版权法律) 也能提供援助。
这看起来适得其反,但是你可以要求标明来源并包含返回你站点的链接。甚至也可以售卖你的 API 而赚取费用。
还有就是,Stack Exchange 提供了 API,但是必须要标明来源。
以我自己写和帮忙别人写爬虫的经验,我认为最有效的方法是:
扩展阅读:
作者:h1z3y3
来源:微信公众号: 360搜索技术团队
出处:https://mp.weixin.qq.com/s?__biz=MzA5ODIxODE2Ng==&mid=2651137205&idx=1&sn=664a46d66f132c96780750d4e9b206eb
*请认真填写需求信息,我们会在24小时内与您取得联系。