first commit
This commit is contained in:
149
专栏/反爬虫兵法演绎20讲/00开篇词如何突破“爬虫反爬虫”内卷之怪现状?.md
Normal file
149
专栏/反爬虫兵法演绎20讲/00开篇词如何突破“爬虫反爬虫”内卷之怪现状?.md
Normal file
@ -0,0 +1,149 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
00 开篇词 如何突破“爬虫反爬虫”内卷之怪现状?
|
||||
你好,我是DS Hunter。
|
||||
|
||||
这位朋友,你进来的时候,我就知道了,你一定遇到了不平凡的需求,而且很可能来自你那个不懂技术的老板。因为普通的工程师是很少关注爬虫和反爬虫这个冷门理论的,尤其是反爬虫。
|
||||
|
||||
我之前是一个反爬虫专家,现在到了一个大厂转型做了前端负责人,请记住这个转变,这在反爬行业是一个梗,后续要用。
|
||||
|
||||
由于一些个人原因,本课程选择了匿名编写。我的笔名是DS Hunter,你可以用任意方式理解DS,总之,我虽然是Hunter,但不是猎头,我是一个纯纯的技术人员。
|
||||
|
||||
我在反爬过程中积累了大量的技巧和新奇理论,并且一直都觉得“技术手段大同小异,但使用方法更为精髓”。毕竟,反爬手段可能谁都会,但是,怎么从众多的反爬虫手段中挑选一个来使用,怎么低成本地达到目的,这里的取舍,就变得没那么容易了。
|
||||
|
||||
接下来,我会带你走进一个不一样的爬虫和反爬虫的世界。
|
||||
|
||||
为什么要学这门课?
|
||||
|
||||
根据我的猜测,你关注反爬虫理论,可能是因为你是个爬虫工程师,你想知道反爬虫到底是怎么和你斗争的。也可能你饱受爬虫困扰,想要学习一些技术保护自己。
|
||||
|
||||
无论是哪一种情况,你都陷入了一个无止境的深坑,这个深坑的名字叫做“内卷”。“爬虫反爬虫”内卷了好多年了,未来也没有停止的趋势。这个困境一直伴随着你,无法消失。
|
||||
|
||||
这里我们一起回忆一下:“爬虫”和“反爬虫”的需求是什么时候开始变得重要起来的?仔细想想,似乎是随着Web 2.0起来的。
|
||||
|
||||
之前有很多爬虫,一般都是作为搜索引擎出现的。我们不但不反对这样的爬虫,还要想办法欢迎它们过来,毕竟这样的“搜索引擎优化”,对双方都是有益的。
|
||||
|
||||
而Web 2.0时代,那些乘着风口起来的人,一个个都将自己的数据视为护城河,大家本来倡导的数据共享渐渐变成了不肯和任何人分享。这虽然有违Web 2.0的精神,但是非常符合人性。那么最终的结果就是,大家通过爬虫技术来拿别人的数据,攻破别人的护城河。到后来,大数据横行,更是提升了数据的价值。我们的防守方,也就是反爬方,会不断调整防守方式来保护自己的数据。从此,这个行业就一发不可收拾了。
|
||||
|
||||
当然了,吐槽是没有意义的,内卷一旦开始,我们光举着道德的旗帜说“不要内卷啊”,是什么也改变不了的。我们能做的就是,努力提升自己,不要被别人卷输。
|
||||
|
||||
所以,这个课程主要就是教你如何卷赢对方。
|
||||
|
||||
当然了,因为课程的特殊性,你可以看到,这门课程虽然是以反爬虫为主,但是爬虫也会被大量提及。因此,我是又在卖矛又在卖盾。所以不要问我,“用你的矛去戳你的盾会发生什么”这类无聊的问题。我只能说,这取决于你自己对课程的掌握程度,以及自己感悟出的其它东西。
|
||||
|
||||
这门课的设计思想是什么?
|
||||
|
||||
在设计课程的时候,我和编辑一直在讨论一个事情:这个课程里,实战能占多少?这个问题困扰了我很久,我最终给了一个解释:实践会很多,但是实战并不多。
|
||||
|
||||
为什么?这里容许我小小地自我膨胀一下,用自己的课程来对比一下《孙子兵法》。
|
||||
|
||||
你可以看到,整部《孙子兵法》,并没有用任何一场战争进行举例,也就是说,没有给你分析一场战争是怎么从头打到尾的。但是几千年来,一直没有过时。
|
||||
|
||||
为什么?
|
||||
|
||||
兵者,诡道也。这个世界没有任何一场战争是可以用上一场的打法继续打的。因为在战场上,你面对的是活生生的人,而不是固定的套路。
|
||||
|
||||
如果我想不断地写实战相关的东西,当然是没问题的,甚至可以用来充字数。对我来说,这是稳赚不赔的买卖。但是,这样的一系列课程下来,你得不到任何干货。
|
||||
|
||||
事实上,我在酒桌上经常和别人吹牛:我们当时的反爬是如何做的,如何如何碾压对手,我们有多么多么牛。但是最后,曲终人散,盛筵难再。朋友分别的时候,他们回想起来我吹的那些牛,会觉得似乎也没有收获到什么。因此,我们的课程不需要太多实战。
|
||||
|
||||
是的,超人不依赖披风,课程不依赖实战。
|
||||
|
||||
所以,这个课程更倾向于培养思维层面的东西,为你提供一条条反爬虫的思路。虽然我也会通过几个实战的例子帮你融会贯通,但是直接实战,肯定会限制住你的想象力。甚至有些可能实战并不是什么光明的做法,我也不可能告诉你历史上是否真的有人用过。爬虫与反爬虫的战场瞬息万变,被几个实战的例子困住,实在是得不偿失。
|
||||
|
||||
最后,请相信这个行业的黑暗:任何一个做法无论多么不道德,只要是好用的,就一定会被用过,而且肯定不止一次。具体次数,取决于多少人知道怎么用。因此,有些知识会比较黑暗。虽然这段陈诉有劝退消费者的风险,但是我觉得还是得提前说明——提前高能预警,避免给你带来任何“惊喜”。
|
||||
|
||||
课程结构设计
|
||||
|
||||
在这个指导思想下,我把这门课划分成了4个模块,帮你实现爬虫反爬虫领域从新手到专家的突破。
|
||||
|
||||
1. 历史背景篇
|
||||
|
||||
也叫导学篇。主要介绍爬虫反爬虫的历史,以及一些小故事。
|
||||
|
||||
以史为镜可以知兴替。同样,爬虫反爬虫的历史,以及一些有意思的小故事,可以帮你轻松、快速地理解技术的来龙去脉。
|
||||
|
||||
尤其是,这么多年过去了,爬虫技术虽然在不断发展,但总体思路其实并没有什么变化。站在历史长河的一端回望,你就可以更深刻地了解爬虫反爬虫,那后续的学习也就是自然而然的了。
|
||||
|
||||
2. 理论与实践案例篇
|
||||
|
||||
这一部分是整个课程的核心。如果你时间紧天分高,那么学完这部分内容,其实就算达成学习这门课的目标了,也就是:做为一个独立的非管理岗位的爬虫或者反爬虫工程师,我应该了解哪些知识,这里,你是没什么问题了。
|
||||
|
||||
这一篇主要是介绍爬虫和反爬虫的基础理论,以及部分实践案例。出于一些法务考虑,实践案例主要是以反爬虫为主,并且一般以故事形式出现。不要去追究发生在什么企业里,无故事王国总是充满了故事。
|
||||
|
||||
何况我相信,即使你是一个爬虫工程师,你更关注的也是反爬虫,而不是爬虫如何爬,对吧?而且知道了如何反爬虫,就自然知道如何爬了。
|
||||
|
||||
3. 项目实战篇
|
||||
|
||||
这个部分主要会列举几个实战的例子。就像我刚刚说的,反爬的单个实战,参考意义极弱,因此这里的实战,主要是指如何在系统层面进行实战,而非与反爬的单个缠斗。可以说,学完第二个模块的时候,你在反爬虫领域就可以达到60分的水平了,不过你会满足于此吗?
|
||||
|
||||
项目实战篇存在的意义,就是帮助你把第二模块中学到的知识运用到实战中,融会贯通,发起向100分的冲刺。
|
||||
|
||||
有一句话可能比较拗口,但是等学完你就会理解,那就是:反爬虫里,最重要的就是如何识别爬虫。但是,最难的,永远不是识别爬虫。
|
||||
|
||||
别急,我们再把这句话反过来再说一次:反爬虫里,最难的肯定不是识别爬虫。但是,最重要的,永远是识别爬虫。
|
||||
|
||||
这两句话描述了相同的意思,但是你一定有着不同的感受。这样的感受,会贯穿我们整个课程——不仅仅是项目实战篇。请一定要牢记。
|
||||
|
||||
4. 进阶篇
|
||||
|
||||
你可能会说了:等等,不是说我已经向满分冲刺了吗?怎么还要继续?
|
||||
|
||||
这样理解吧,假设我们有期末考试的话,那么出题范围一定是到三就结束了。学完二,考试能及格。学完三,大概能达到九十五分。
|
||||
|
||||
不过,即便你的单兵作战能力已经达到了极致,难道就不会产生成为将领的想法吗?这五分,就是从单兵作战到团战的跨越,更是从技术到管理团队的跃迁。进阶篇,就是为了帮助你打破发展上限,开启反爬虫团队作战的新模式。
|
||||
|
||||
所以,这里就是管理技能以及团队组建等知识,也就是“反爬是如何组建团队的”。毕竟了解对方是如何组建团队的,是不是也是一种“知己知彼”?我只能说这么多了。
|
||||
|
||||
当然,如果读完了觉得难以理解,也没关系,这并不影响你日常与爬虫对抗,但总有一天,你会需要它的。
|
||||
|
||||
这门课适合我吗?
|
||||
|
||||
了解了这门课程能学到什么内容之后,你的另一个困惑可能是:这个课程是否适合我?
|
||||
|
||||
首先我们看下做反爬虫的人是如何划分层次的:
|
||||
|
||||
|
||||
|
||||
|
||||
第一层:重视如何区分具体每一个爬虫,最好有人手把手教。
|
||||
第二层:能自己主动识别一个未知的爬虫,即使网上搜不到办法,也能自己创造办法识别。
|
||||
第三层:更关注系统设计、扩展相关的知识。
|
||||
第四层:更关注如何组建团队。
|
||||
第五层:一切都不是问题了,这个时候,返璞归真,发现最关键的还是如何识别爬虫。于是专心搜索这方面的知识。
|
||||
|
||||
|
||||
对于这门课来说,其实是会覆盖到二、三、四层的全部用户的。而如果你是第一层用户,那么你可以通过本课程提供的第二层知识,自行学会,还可以找到自己区分爬虫的办法。至于第五层,我想说的是:你是大佬,也许我要向你学习。
|
||||
|
||||
写在最后
|
||||
|
||||
由于“爬虫和反爬”是一个创新领域,所以很多定义还是很模糊的。甚至你的公司内部可能都不用“爬虫”和“反爬”这些词,可能是“抓取”和“反抓取”。为了后续的统一,这里就和你一起定义一下它们吧:
|
||||
|
||||
|
||||
|
||||
爬虫:使用任何技术手段,批量获取网站信息的一种方式。关键在于批量。
|
||||
反爬虫:使用任何技术手段,阻止别人批量获取自己网站信息的一种方式。关键也在于批量。
|
||||
误伤:在反爬虫的过程中,错误地将普通用户识别为爬虫。误伤率高的反爬虫策略,效果再好也不能用。
|
||||
拦截:成功地阻止爬虫访问。这里会有拦截率的概念。通常来说,拦截率越高的反爬虫策略,误伤的可能性就越高。因此需要做个权衡。
|
||||
资源:机器成本与人力成本的总和。-
|
||||
-
|
||||
引用来源:《携程:关于反爬虫,看这一篇就够了》
|
||||
|
||||
|
||||
|
||||
其实这些定义并不复杂。你看完后会发现:当我们在讨论爬虫的时候,是讨论战略意义的爬虫,而不是单独的一个小爬虫是否能通过。同理,讨论反爬虫的时候,也是战略意义上的反爬虫,而不是赌气式的反爬虫。这点一定要清晰明确。
|
||||
|
||||
做反爬其实和战争差不多,有的时候要闪电出击,有的时候要龟缩示弱。而且一定要记住,不打无意义的战争。同时,反爬也是一个很腐蚀人心智的行业,很多人在做了反爬之后,学会了各种坑蒙拐骗的技巧,整个人都变得不好了——这也是我选择写这个课程的一个原因。除了讨论各种技术以外,我真心希望,通过这个课程,能让所有的反爬工程师都学会一件事,并应用于工作以及生活中,那就是:“我就是想站着,还把钱挣了。”
|
||||
|
||||
推理到爬虫工程师,就是:“我就是想堂堂正正,还把工作完成了。”
|
||||
|
||||
好了,最后的最后,我也希望你来讲讲,你有没有一些有趣的反爬虫经历、你对爬虫反爬虫的看法是什么,欢迎在留言区分享你的思考感悟和学习心得,咱们一起交流讨论。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
147
专栏/反爬虫兵法演绎20讲/01爬虫需求的诞生:我们是正经的软件工程师.md
Normal file
147
专栏/反爬虫兵法演绎20讲/01爬虫需求的诞生:我们是正经的软件工程师.md
Normal file
@ -0,0 +1,147 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
01 爬虫需求的诞生:我们是正经的软件工程师
|
||||
你好,我是DS Hunter,反爬虫专家。
|
||||
|
||||
也许你是一个爬虫工程师,也许是反爬虫工程师,甚至,也许你只是一个业务方的普通研发,被授予了反爬的重任。但是,不论你的身份是什么,“什么是爬虫”这个问题都是你必须要了解的。
|
||||
|
||||
为什么这么说呢?
|
||||
|
||||
可能你常把爬虫挂在嘴边,觉得自己已经很熟悉爬虫了,但当你尝试自己做一个爬虫或者完成一个反爬虫动作时,却发现无从下手。其实,很大的一个原因就是你对于“什么是爬虫”这个问题了解得并不透彻。
|
||||
|
||||
从历史的视角来了解爬虫从哪里来、能做什么,以及从诞生到现在的这段时间里都发生了什么样的变化,可以让你对“什么是爬虫”这个问题产生更深度的思考,这也是我要在课程里特地为你设置一个“历史背景篇”的主要原因。咱们接下来正式开始吧。
|
||||
|
||||
什么是爬虫?
|
||||
|
||||
爬虫是一个历史悠久的需求,严格来说,它甚至比网络出现得还早。或者你也可以理解为,网络出现之后,网络和爬虫才结合成了我们所熟知的网络爬虫。因为互联网大部分的功能其实并没有什么新意,只不过是把线下的场景搬到线上来了。
|
||||
|
||||
而爬虫,其实就起源于线下。再聚焦一些,爬虫,起源于再平常不过的——菜市场。
|
||||
|
||||
买菜和爬虫?买菜也爬虫?
|
||||
|
||||
前几天我听了一首很喜欢的歌,叫《说走就走》。里面有一段话,说的是:“走世界,看精彩,从18岁讲到现在,最后到巷口去买菜。”
|
||||
|
||||
本意是说,年少充满理想,长大后被生活压垮,每天沉迷于菜场买菜这种小事,再也没有了理想。但是实际上,买菜并不是小事,它充满了技术含量。
|
||||
|
||||
菜场买菜的大妈们砍价非常厉害——我感觉我这辈子都学不来。对她们来说,即使只差一毛钱,也可能会让她们选择去别的摊位买菜。也许你不太理解这种行为,觉得,我都在这问了价了,就因为隔壁少一毛钱,就去隔壁,这多不好意思啊。但是对于菜场的顾客来说,这很正常啊,“同样的东西, 哪里便宜我就去哪呗”,这是再正常不过的“博弈”了。
|
||||
|
||||
说回喜欢在网上买东西的你。一个小东西,A网站比B网站便宜一毛钱,你是不是就果断抛弃了B网站?或者A说,价格一样,我包邮。你是不是就直接去A网站买了?这个时候,因为没有面对面的交流,你就没什么不好意思的了。所以说,趋利避害这是人性使然,自古如此,与年代性格都无关。只要有人的地方,就会有“博弈”。
|
||||
|
||||
最后,在买菜或者买东西的故事里,除了“你”这个主角,商贩们其实也没闲着。他们也会做一些操作,比如让自己的家人去四处转转,看看别的摊位卖多少钱、有没有偷偷降价。如果有顾客来自己的摊位买菜,也会顺便问问,“哎你这个菜多少钱买的啊”,只要不低于成本,他就敢降到一样的价格,甚至更低。
|
||||
|
||||
实际上,大妈们获取价格的方法、你对比价格的过程以及商贩们相互获取价格的方法,都可以理解为“爬虫”行为,和网络爬虫其实也没有什么区别。只是人工问价效率低,爬虫效率高。价格,就是在这样不断博弈的过程中,慢慢均衡下来的。而博弈的第一步,就是“问价”——获取数据。
|
||||
|
||||
不止买菜:我只是要数据
|
||||
|
||||
为什么获取数据这么重要?其实《孙子兵法》就提到过:知彼知己者,百战不殆。商场如战场,获取数据自古就是胜负的关键。
|
||||
|
||||
至于获取数据的需求是怎么产生的,我给你举个例子吧。获取数据的手段——爬虫,很难学的一个主要原因就是描述它的词汇太多了。你可以看下网络上对爬虫的定义,有几个常用的词:爬虫、抓取、spider、crawler……可能我也说不全。日常使用的话,这些词你随便挑哪一个都行。但是搜索对应知识的时候,为了更全面一些,就要全搜一遍。那如果你不想连搜四次,怎样操作才能一次性拿到所有的结果呢?
|
||||
|
||||
这个时候,聪明的你可能已经想到了,我要不要写个爬虫全拿下来呢?恭喜你,你为了获取爬虫的知识,已经自发地产生了一个爬虫的需求。
|
||||
|
||||
因此你会发现,爬虫需求的产生是自然而然的,而你的需求不一定是一个坏的需求——你看,我们多正经。是的,技术只是工具,与善恶无关。
|
||||
|
||||
最早的Google工程师就是这么想的,或者再早的Yahoo。我们无从得知当时具体发生了什么、第一个爬虫是如何被写出来的。但可以想象的是,因为当时的互联网数据越来越多,获取信息变得越来越难,于是他们就写了一个网络爬虫来获取数据。从此,潘多拉的魔盒就被打开,后面的事情就不再可控了。
|
||||
|
||||
搜索引擎和爬虫
|
||||
|
||||
既然提到了Google和Yahoo,我们就紧接着从历史视角,审视一下搜索引擎和爬虫的关系,看看爬虫的早期历史和相关的技术变迁。
|
||||
|
||||
美好的上古田园时代
|
||||
|
||||
搜索引擎可以认为是爬虫的集大成者了。它本质上就是用爬虫爬取天下数据,汇聚在自己的网站上,让大家可以在自己的网站上直接搜索到全天下的知识。这个操作对于搜索引擎和站点两方都是有利的,搜索引擎自己能够获得稳定客户,甚至商业利益;站点本身可以获得流量,未来也可以获得商业价值。
|
||||
|
||||
为了这个双赢的局面,还引发了一个叫robots.txt(也叫robots协议)的君子协定,里面会约定,哪些可以爬,哪些不可以爬。但是因为大家很依赖搜索引擎,所以除非是用户信息,否则一般都是开放的。甚至有些站点不写robots.txt,默认对搜索引擎全部开放。除此之外,还可以写sitemap来指定自己网站都有什么,欢迎搜索引擎来赶紧爬走,给自己打个好评,引导用户过来。大家主动交流,相互沟通,真的是一个美好的上古田园时代。
|
||||
|
||||
春秋时期
|
||||
|
||||
但是美好的上古田园时代由于网络的不断发展,注定不会持久,很快,爬虫就发展到了春秋时期。
|
||||
|
||||
|
||||
春秋前期
|
||||
|
||||
|
||||
在春秋前期,爬虫已经不是新技术了。你的那个不懂技术的老板,可能都已经知道了:想要寻找大量数据,可以用爬虫去爬别人。所以,你就接受了这样的需求,开始学习相关的知识。
|
||||
|
||||
但是你也知道,网络历史从 TCP 到 HTTP,现在又回到了 TCP。随着历史的变化,爬虫本身的技术也会随之变化。毕竟,服务器使用了什么类型的网络,爬虫就要被迫使用什么类型的网络。
|
||||
|
||||
|
||||
春秋中期
|
||||
|
||||
|
||||
当爬虫开始受网络发展的影响,就注定也会被其它因素影响。在春秋前期,大家逐渐产生“爬取数据”的需求,到了春秋中期,这些需求逐渐演变成了一个业务的雏形。也就是说,在这个时候,不同的业务开始对爬虫技术产生影响了。
|
||||
|
||||
咱们先说扒站这件事。最初爬虫都是一些大公司的特权,小公司自己的业务都做不完,哪有时间去搞爬虫。但是出于业务的需要,一个新的行为就诞生了——站点复制,俗称扒站。
|
||||
|
||||
也就是说,别人网站做得好,我刚创业,追赶别人根本来不及。怎么办呢?答案很简单,我写个爬虫把整个网站抓下来不就好了。然后把数据放在我的服务器上,就可以瞬间追上别人的进度,站在同一起跑线。
|
||||
|
||||
还有就是浏览量的需求了。站长很想让搜索引擎来爬自己的数据,因为有了搜索引擎的爬取,就会有排名,就会有业绩。而为了提高搜索引擎的分数,他们十分渴望搜索引擎来抓取自己所有的数据。
|
||||
|
||||
关于搜索引擎爬取自己数据的这件事,我们可以回顾一下历史。
|
||||
|
||||
早年的网站结构其实很简单,就是一个服务器,上面挂了一些静态的文件。有的站点甚至会打开目录遍历权限,也就是说你去找一个目录看一下,能直接看到目录下面有什么文件,这种站点扒起来简直太舒服了。 但是如果没有开目录遍历权限,就要麻烦很多了,似乎抓起来就没有前面说得那么容易。
|
||||
|
||||
好了,从历史回顾里跳出来,春秋中期的站长,为了给搜索引擎抓取数据提供便利,通常会有两种操作:一种是sitemap,也就是给整个站点建一个地图,给对方使用;还一种就是内链,通过自己不断引用自己,来实现引导爬虫爬取完整站。
|
||||
|
||||
这样一来,爬虫工程师的爬虫思路就显而易见了:既然站长提供了sitemap和内链两种便利,我只要声称自己是搜索引擎就好了。这样对方不但不会拒绝,还会引导我去爬取整个站点。这样,想扒整个站就变得非常容易。
|
||||
|
||||
你可能会觉得,这里有点引狼入室的感觉了——难道站长已经有准备了?没有。等狼真的来了也没有什么办法——撑死就是封一封明显太过分的IP。
|
||||
|
||||
最后我来给你总结一下这个时期爬虫的爬取思路吧。春秋中期,爬虫基本上就两个爬取思路,一个是深度优先遍历, 一个是广度优先遍历,它们的最终目的都是抓完整站。所以爬虫会有一个“spider”的名字,蜘蛛能结网,指的就是这个遍历方式。如果你以后面试的时候,面试官着重考查这两个知识点,你要理解,他已经很久不做爬虫了。这是远古时代的基本技能,现在大家已经不太关注这个了。
|
||||
|
||||
|
||||
春秋后期
|
||||
|
||||
|
||||
后来两件事情改变了这个行业的格局。一个是电子商务的出现和普及,一个是站点的动态化和伪静态化,我们也就随着这两件事从春秋中期进入到了春秋后期。
|
||||
|
||||
先看第一件事:电子商务的出现和普及。你还记不记得我在开头提到的一句话:互联网大部分功能其实并没有什么新意,只不过是把线下场景搬到线上来了。
|
||||
|
||||
电子商务其实就是把菜场搬到了线上。 菜场有爬虫,电子商务就会有爬虫。与搜索引擎不同的是,商场如战场,战场上的较量,有时候就没有那么强调道德了。爬虫也就渐渐为所欲为了起来。
|
||||
|
||||
另一件事就是站点的动态化和伪静态化,动态化页面导致站点内容变得十分丰富,甚至可以认为近乎无穷无尽,通过改变参数就可以不断改变站点内容,这一点对搜索引擎非常不友好。但是好消息是,这一点对其它爬虫,一样很不友好。
|
||||
|
||||
因此,站点开始进行伪静态化。假装自己依然是个静态站点后,爬虫的需求开始变得复杂,单纯的深度优先和广度优先满足不了大家的要求了。尤其是随着Web 2.0的诞生,站点更加复杂,本身也开始了分层,界面是界面,数据是数据。那么我们的爬虫最关注的是什么?是数据。那就是说,爬虫甚至可以只抓数据,跳过界面。这个时候,爬虫就变得十分高效。
|
||||
|
||||
不过,当爬虫变高效之后,服务器的噩梦就诞生了。由于前后端分离, 静态资源放置于CDN,通常并不是很怕爬虫。但是数据位于服务层,服务层比CDN脆弱得多,爬虫一来,可能打爆链接数,甚至可能击穿数据库、拖慢站点性能,各种诡异的情况都可能发生。
|
||||
|
||||
总的来说,电子商务的出现和普及以及站点的动态化和伪静态化这两件事出现之后,爬虫就很容易不小心惹事。很多文章都会教你,尽量控制频率,不要把站点爬挂。而我们被爬的站长那一方,他欢迎搜索引擎,但是不喜欢爬虫,不过依旧没有太好的办法区分彼此。
|
||||
|
||||
如果说爬虫是一场战争,那么现在的春秋时代,大家打仗还是讲究一个“礼”字的。截止到目前,还没有彻底崩坏。但是,根据历史我们可以知道,这样的事情不会持续多久,战国,很快就要来了。
|
||||
|
||||
小结
|
||||
|
||||
好了,最后我来给你小结一下。今天和你聊了爬虫的产生、早期历史以及一些相关的技术变迁。
|
||||
|
||||
可以说,“爬虫”是竞争的必然产物,而网络的出现,赋予了爬虫在互联网领域的生命。再次强调,这项技术只是工具,与善恶无关。
|
||||
|
||||
|
||||
|
||||
在美好的上古田园时代,爬虫彬彬有礼,用技术不断辅助大家,让整个互联网变得更好。搜索引擎自己能够获得稳定客户,甚至商业利益。而站点本身可以获得流量,未来也可以获得商业价值。你看,需求正经,做的也是正经事。
|
||||
|
||||
截止到这个时候,爬虫还没有任何过错,还没有到现在这种人人喊打的地步。如果人类的爬虫技术止步于此,那么这个世界将非常美好。遗憾的是,人性自古不变,行业建设到一定程度就会产生内卷。
|
||||
|
||||
在春秋时期,随着不同业务需求的诞生,爬虫技术也随之发展。春秋前期,我们发现爬虫开始不停地迭代,适应网络环境。后来,春秋中期的扒站行为,本身已经是一种轻度内卷了。同时,站长出于对浏览量的需求,提供了sitemap这张地图以及内链的方式,助长了爬虫疯狂爬取的气焰。而到了春秋后期,电子商务更为爬虫增添了不少的商业气息,商人逐利,爬虫也逐渐为所欲为。站点的动态化和伪静态化,让爬虫直接爬取数据层,站点无法承受攻击……
|
||||
|
||||
下一讲,我们会进入到战国时期,看下礼乐制度彻底崩溃、内卷到血流成河的时候,整个行业会成为什么样子。而这,也是你我共同面临的环境。
|
||||
|
||||
思考题
|
||||
|
||||
好了,这次是我第一次给你留思考题。下面有三个方向,你可以选择一个来和我分享:
|
||||
|
||||
|
||||
站长在喜欢搜索引擎的同时痛恨爬虫,不过搜索引擎本身也是一种爬虫。那么,假如一个爬虫冒充搜索引擎,怎么办?
|
||||
爬虫为这个世界做出了什么贡献?
|
||||
你的爬虫或者反爬虫经历是什么?有什么奇葩的经历吗?
|
||||
|
||||
|
||||
期待你在评论区的分享,我会及时回复,不过要记得注意保密脱敏。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
208
专栏/反爬虫兵法演绎20讲/02爬虫的内卷和黑化:我们变得不正经啦.md
Normal file
208
专栏/反爬虫兵法演绎20讲/02爬虫的内卷和黑化:我们变得不正经啦.md
Normal file
@ -0,0 +1,208 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
02 爬虫的内卷和黑化:我们变得不正经啦
|
||||
你好,我是DS Hunter。
|
||||
|
||||
在上节课里,我们讲了上古田园时代和春秋时代的爬虫发展,这个时候爬虫还是有礼节的。但是到了后面的战国时期,就彻底礼崩乐坏,慢慢变得无恶不作了。爬虫也从一门技术,变成了一门生意。
|
||||
|
||||
因此,面临这种超出想象的变化,在激烈的对抗间,我们的各类招式也层出不穷。这节课,我们就聚焦到战国时代,我会给你讲解几个在爬虫和反爬虫的斗争期间,双方常用到的招式,像爬虫方常用的接口定制化爬虫、机器人工双校验,以及反爬虫方常用的数据混淆策略和字体文件反爬。
|
||||
|
||||
这些招式会按照相互克制的顺序展开。我们一块来看看,在商业的高度内卷下,爬虫变成了什么样子。
|
||||
|
||||
黑化的爬虫和反爬虫的对抗
|
||||
|
||||
在战国时期爬虫和反爬虫的对抗中,服务器的压力已经不再是最大的问题了。
|
||||
|
||||
服务器是固定成本,而且大厂通常十分冗余,或者说浪费。即使有部分爬虫来,也不会造成什么影响。这个时候大家更关注的是:如何在商业上获胜。商业竞争逐渐激烈,面对这样的环境,爬虫越来越接口定制化。
|
||||
|
||||
爬虫第一招:接口定制化爬虫
|
||||
|
||||
定制化,简单地说就是只拉接口,不拖泥带水地进行没用的请求。我给你画了一个接口定制化爬虫产生的过程图,你可以参考一下。
|
||||
|
||||
|
||||
|
||||
最早,爬虫还没有开始接口定制化,而反爬虫会根据IP以及访问频率进行简单的封锁。举例来说,假设一个IP地址只访问你的价格接口,不访问你的其余接口,也不访问静态页面,那么,超过一定的阈值,这个IP地址就会被拉黑。
|
||||
|
||||
时间长了,爬虫就会选择多爬一点没用的数据来伪装自己,把想爬的接口隐藏在自己的请求中。但是随着代理服务器成本下降以及大环境的改变,这种方法就不再适用了。
|
||||
|
||||
这里还是用价格战来给你举例:如果反爬虫服务器针对一个IP拉黑的阈值是访问10次价格接口,那么爬虫方如果想发起10000次的接口请求,只需要使用1000个代理。
|
||||
|
||||
我们先说第一条走向定制化的路,代理服务器成本下降。成本下降,突破IP封锁就从一个技术问题变成了ROI(return on investment,投资回报率)的问题。而能用钱解决的,就不再是问题了。毕竟只要增加代理服务器,增加接口隐藏自己,总是可以爬取到需要的数据的。但是,这样会给对方的服务器带来更大的压力,对方崩了,自己也得不到数据。
|
||||
|
||||
而第二条路,不仅和代理服务器成本下降有关,更有大环境影响的因素。随着移动互联网的普及,用户的请求IP不再是固定的,同一个IP上一秒还归路人甲使用,下一秒可能就给路人乙了。反爬虫方也不太敢继续依据固定IP的访问频率封锁了。
|
||||
|
||||
所以,在这个时候,爬虫方开始大胆使用接口定制化的爬虫,而不再使用通用爬虫。不过后面这个还会再反转。这个在结尾我们会再谈。
|
||||
|
||||
反爬第一式:数据混淆策略
|
||||
|
||||
爬虫和反爬虫打了一段时间后,反爬虫的业务方就提出了新的要求:就算被爬取了,也要让被爬取的数据产生价值。这里我们创设一个情境来说明。
|
||||
|
||||
例如,AB两家公司,A的商业策略是,优先保证盈利,保护股东利益。而B的商业策略是,尽可能低价占领市场。那么当他们互相爬取对方的时候,反爬团队都会如何处理呢?这里我为你准备了一个表格,你可以在学习的时候思考一下,AB两家公司双方都在想些什么。-
|
||||
|
||||
|
||||
A公司的日常定价必然是高价优质服务,B公司的日常定价必然是低价低质服务,甚至无服务。
|
||||
|
||||
这个时候,B公司的爬虫如果来爬A公司,A公司的业务会如何考虑问题?
|
||||
|
||||
|
||||
我们公司的商品卖100,他们一般是卖99;
|
||||
对方爬虫抓到我们的价格,一定会在定价的时候减价售卖;
|
||||
基于这个考虑,我们做一个提价吧,就告诉他们的爬虫,我们卖120;
|
||||
对方拿到120的价格,一定会降价到比我们低的价格卖,可能就是119。这样,我们的100还是有价格优势的。-
|
||||
好了,推测先到这里,我给你总结了一张爬虫方B爬取A的思路与做法表格:
|
||||
|
||||
|
||||
|
||||
|
||||
爬虫方B公司找反爬虫方A公司爬取数据的情况说完,我们来看看反过来的情况,也就是说,现在博弈中的两个角色变成了爬虫方A和反爬虫方B。
|
||||
|
||||
实际上,A公司的爬虫在爬取B公司的时候,B公司的业务必然也是反向思考的。也就是说,B给的价格必然是比实际价格还低一点的(你也可以列表试试推理这种情况)。
|
||||
|
||||
这里你也可以参考一下我给你提供的爬虫方A爬取反爬虫方B的博弈过程:
|
||||
|
||||
|
||||
|
||||
可以看到,B会给出较低的价格(例如表格中的80),有本事你就跟进,我就不信你敢放弃股东利益,降价到这个程度。
|
||||
|
||||
这样,同样的商品,本来售价100,结果A告诉B,我卖120。B告诉A,我卖80。爬虫就像一个间谍,拿到数据不可怕,可怕的是拿到错误的数据,给出错误的商业决策。
|
||||
|
||||
你看,这个时候,反爬虫方并非专注于技术手段的提升,而是开始利用起了被爬取数据这件事。就算被爬取,也要让这个被对方抓到的数据产生价值。通过给对方错误的信息,使对方产生错误的判断,并在这条路上越走越远。这手段,多不正经。不过也不用觉得复杂,刚刚我们填好的表格,就是这场反爬战的思路。
|
||||
|
||||
爬虫第二招:机器人工双校验
|
||||
|
||||
“机器人工双校验”这个招数,你可以把它看成一个动作链条,在这个链条里的爬虫会使出各种手段与反爬虫方斗争,获取想要的数据。这里的“不正经”成分达到了巅峰,在爬虫与反爬虫的博弈之间,充满了尔虞我诈。
|
||||
|
||||
下面是一张机器人工双校验的动作链条示意图(空格处待填写)。接下来我们就一起让整个动作链条完整起来——置身于战场,才能了解隐藏在战争背后的每一个想法。在整个动作链条里,逻辑对抗无处不在,那直接就开始吧。
|
||||
|
||||
|
||||
|
||||
我们现在来看一个新的战况:爬虫方B公司,在爬取走高端路线的A公司的价格的时候,每次都拿到80。也就是说,反爬虫方A选择用不同的价格迷惑对方。时间长了,爬虫方B公司就会发现不对了:80是一个亏本价格,不符合A走高端路线的风格。稍加分析就会发现:价格被掺假了,下降了20%。
|
||||
|
||||
面对刚刚说到的反爬方A的数据混淆策略,爬虫不得不做出改变。那么这个时候爬虫的第一个办法就出现了:既然所有的价格都下降了20%,那么如果我真的无法突破反爬虫系统,就去抓错误的价格,然后再加回来,不就行了吗?我干嘛死磕对面的反爬虫系统呢?没错,它们选择了不在技术上交锋,而是用自己的推断得出正确的价格信息。
|
||||
|
||||
现在看来,这样奇葩的做法可能有些不可思议。但是在历史上,这是真实存在的。很多反爬虫系统都有过这样的黑历史,那就是:防住了,但是等于没有防住。
|
||||
|
||||
|
||||
随机虚假价格和两次请求
|
||||
|
||||
|
||||
|
||||
|
||||
另一方面,面对爬虫的第一个方法——回推价格,反爬方开始了将价格的变更幅度做成随机的策略。这次展示80的价格,下次展示75的价格,每次都不一样,这样就没办法反推回来了。
|
||||
|
||||
为了应对随机变化的价格,爬虫方开始了我们的第一个机器校验方法:进行两次请求。这样,通过检查价格是否一致,就可以轻松校验自己的爬虫系统是否被拦截了。例如,第一次请求一个商品的时候,价格是80,相同的参数再请求一次,价格又变成了75,前后时间可能只差1秒,但是1秒内商品变价的概率并不高——那就可以证明,自己被拦截了。
|
||||
|
||||
好了,大致的博弈先告一段落。你可能已经迫不及待开始预测爬虫方下一步的动作了:这个时候是不是就可以停掉爬虫,慢慢调试自己的代码,等每次价格都正确的时候再爬呢?毕竟爬取也是需要消耗资源的。停下来,能有效节约一部分成本,同时,也可以降低对方的服务器资源消耗,避免爬虫把对方爬崩之后两败俱伤。
|
||||
|
||||
如果你的回答是:Yes!那么恭喜你,你被反爬虫坑了!因为如果反爬虫方发现你的策略是,错一次就停下来重爬,那么他会无脑给一些低概率的错误价格。
|
||||
|
||||
举个例子,对方根本没有发现你的爬虫。但是,反爬虫系统用一个极低的概率,随机给一次错误价格。我们假设,反爬虫方给一次错误价格的概率设置为万分之一。那么,线上用户被影响的概率是极低的,并且影响了也不容易被发现。但是你的爬虫运行一万次,算过来可能就碰到一次错误的价格。如果就这样停下爬虫来调试,一定是一无所获。毕竟,这只是随机事件啊!所以你本着替双方着想的初衷做了这个熔断,但是结果却卷输了自己。实在是太冤枉了。
|
||||
|
||||
看看,是不是充满了不正经的尔虞我诈。
|
||||
|
||||
|
||||
部分随机价格和有意抓取
|
||||
|
||||
|
||||
|
||||
|
||||
回到爬虫方两次请求的进攻方式,反爬方选择让价格不随机。但是不随机不就回到开头的状态了吗?这个时候我们可以选择一个部分随机的解法。
|
||||
|
||||
简单地说就是,同一个商品,相同时间段内,价格随机幅度不变。例如商品A,价格是100元。当前一小时内你算出一个随机值,例如是13%,那么A商品在这一小时内,将一直提价13%。而另一个商品B在这一小时的提价幅度可能是15%。这样既实现了价格不确定,又避免了被相同请求验算。一举两得。因为相同的请求,必然得到相同的结果。
|
||||
|
||||
那么,爬虫方是否还有办法检测自己是否运行正常呢?
|
||||
|
||||
有的。答案就是:有意抓取错误价格。
|
||||
|
||||
其实道理很简单,相同的数据,相同的时间内价格是一样的。那么,哪个价格是真的我不好找,但哪个价格是假的,我还是很容易找的吧?我有意撞一下反爬不就行了?有意告诉反爬系统,我就是爬虫,快给我假价格。拿到假价格之后,你再进行一次正常的请求,看下是否一致不就行了吗?
|
||||
|
||||
|
||||
策略针对和人工校验
|
||||
|
||||
|
||||
|
||||
|
||||
那么现在再绕回来,假设你是反爬方,对方这样检查自己的爬虫是否正常,你如何处理?
|
||||
|
||||
答案其实也是显然的,你只需要针对不同的策略返回不同的假价格就行了。举个例子,你的反爬可能依赖一个Token。对方可能用Token缺失的请求来校验。这个时候,你给出13%的提价。当Token存在,但是Token错误的时候,你给出16%的提价。而Token长度不正确,你给出15%的提价。或者Token奇偶校验错误,你给出12%的提价,价格复杂多变起来,这个问题就轻松解决了。
|
||||
|
||||
那么爬虫方面对这个办法是不是无能为力了呢?也不是的!
|
||||
|
||||
这个时候,爬虫方就可以加入人工校验了。因为爬虫方只需要确认自己是否运行正常,那么只要有一个校验错误,就意味着自己不正常,所以这个成本还是很低的,只需要在爬取到的数据中抽样即可。也就是说,只要用人工来进行抽样检测,就可以在概率上检测自己运行是否正常。
|
||||
|
||||
从另一个角度来说,对方针对爬虫给出了各种花式的价格,他能保证100%命中爬虫,而不命中正常人吗?不能。这种价格混淆俗称“下毒”。那么,就像狼人杀里面的女巫一样,你能保证自己不毒到平民吗?不可能的,概率永远是存在的。那么你就可以通过众包的方式让真实的用户去访问,通过比对看到的价格,就可以确认自己是否运行正常。当然,这个过程中也必然会有真实用户被误伤。
|
||||
|
||||
也许你会很好奇:误伤了会怎么样呢?
|
||||
|
||||
不同的用户看到不同的价格,去投诉竞对大数据杀熟,让他领导开除他啊!
|
||||
|
||||
如果你刚刚真的想问这个问题,我还是很高兴的,这证明你还保持着纯真和善良。毕竟从刚刚一来一回的分析中你也肯定感受到了——反爬是一个很腐蚀心智的事情。而你,还是关心真实的用户的。
|
||||
|
||||
反爬第二式:字体文件反爬
|
||||
|
||||
是不是受不了了?快从刚才说的那些腐蚀心智的斗争中拉回来,回到一些正经的话题上来。这里的反爬手段,就没有那么的尔虞我诈了。
|
||||
|
||||
为了防止真正的用户受到反爬虫的误伤,通常网上的一些教程一定会教你“字体文件反爬”,也就是说,让展示出的价格使用自定义字体来实现反爬虫。简单地说,你可以创建一个自定义字体。因为字体可以定义文字书写方式,你完全可以在该字体下,将数字打乱。例如“1”显示成“3”,“3”显示成“7”,“7”显示成“5”等等。这样,你下发的价格其实是错误的价格。但是真正的用户通过这个字体文件加载之后,会被mapping(映射),显示成为一个正确的价格,不影响使用。
|
||||
|
||||
网络上对这个办法赞赏不已,但是我告诉你:这个办法虽然酷炫,但它其实是一个下下策。
|
||||
|
||||
为什么?
|
||||
|
||||
第一个,因为时间成本。你想一下,如果你做了这个字体文件,你需要花费多少时间?一天?这算效率高的了吧?但是对方发现之后,mapping回来需要多久?
|
||||
|
||||
五分钟。
|
||||
|
||||
你拿一天的时间拼人家五分钟,这划算吗?
|
||||
|
||||
我在开篇就提到了,反爬虫拼的就是资源。而资源包括机器和人力资源的综合。其中,机器资源成本越来越低,但是人力成本,却随着程序员的工资水涨船高。因此在人力资源上拼亏了,极大可能上,会输掉整个博弈。
|
||||
|
||||
除了不划算这个问题,第二点,就是依旧会误伤用户。如果字体文件加载失败,真实的价格是不是就被迫用默认字体渲染?默认字体可没这个mapping。所以,一旦字体文件加载失败,这个办法依旧会对普通用户造成伤害,并且伤害极大。而对爬虫,只会造成5分钟的困扰。这真的划算吗?
|
||||
|
||||
第三点,如果对方有意屏蔽你的字体文件,然后制造一个网络不好加载失败导致价格错乱的假象,接着导致在iPhone上价格变高了,对方截图,然后再截一个正常的Android系统的价格。两张图放到一起比对,iPhone价格高,Android价格低,看人下菜碟实锤了。这个投诉估计就够你处理半个月了。所以,这对你,也就是反爬方,也是一种伤害。
|
||||
|
||||
最后,如果非用这个办法不可,请一定要记住:字体文件并不大,请直接inline到HTML里,这样,只要HTML加载成功,字体文件不可能失败,两者是同进同退的,不用担心上面提到的价格错乱问题。而上面说的对普通用户的误伤甚至是对你的伤害,就不会存在。不过更好的选择是,不使用这个看起来酷炫实际上无意义的小技巧。
|
||||
|
||||
小结
|
||||
|
||||
好了,我们的爬虫反爬虫内卷的历史就这样告一段落。
|
||||
|
||||
当然,这里还没有讨论验证码和浏览器爬虫,以及针对浏览器爬虫的对策。这个我们会在下一讲里讨论。尤其是爬虫方可以用浏览器爬虫秒杀大部分的反爬机制,反爬被逼无奈放大招的时候,会让人忍不住怀疑人性到底可以多黑暗。
|
||||
|
||||
单看今天讲的内卷历史,确实你来我往,尔虞我诈,变得越来越“不正经”。
|
||||
|
||||
首先,接口定制化爬虫,其实就是只拉接口请求想要的数据;而针对这样的爬虫,反爬虫工程师开始了数据混淆策略。我们姑且把他们归为第一轮战争。也就是从这一轮开始,爬虫与反爬虫的斗争开始了对业务的影响。
|
||||
|
||||
之后爬虫方卷土重来,为了校验自己是否正常运行,开始使用机器人工双校验的方法。你可以把这个方法理解为一个链条,里面的每一个动作都是为了验证爬取到的数据是否是真实的;而反爬也不甘示弱,开始字体文件反爬。而这一轮的斗争,开始误伤到普通用户。
|
||||
|
||||
在你一招我一式的战争中,还有一些“大招”,它们不一定多高效,但适用性强。类似反爬方的验证码和爬虫的浏览器模拟这两种方法,就是万能的。不过,他们也有缺点。验证码误伤率高,浏览器模拟效率低。或者你可以理解为,伤敌一千,自损八百。
|
||||
|
||||
其实,爬虫和反爬虫一直以来是矛与盾的关系,彼此互相克制。最终总结下来如下图:
|
||||
|
||||
|
||||
|
||||
总体看起来,挑事的主要是爬虫,反爬主要是被动防守。这个世界好人难做啊。
|
||||
|
||||
那么反爬虫方就会思考了:好人难做,我是好人,是不是就意味着我难做呢?如果这个问题没办法解决,是不是可以反向思考呢?
|
||||
|
||||
比如,我也不做好人了?
|
||||
|
||||
思考题
|
||||
|
||||
好了,这一节课就告一段落了。爬虫反爬虫的不断反转,的确是个很内卷的事情,但这样的内卷又毫无意义——它并不创造价值。那么我们轻松一下,我给你留了三个思考题,你可以任选一个进行作答。
|
||||
|
||||
|
||||
刚刚提到的字体反爬虫虽然酷炫但得不偿失,那么你还知道什么别的酷炫但得不偿失的爬虫反爬虫技巧吗?
|
||||
数据混淆策略里提到了大量的勾心斗角。那你觉得怎么样才能避免自己多想了一步,导致“聪明反被聪明误”呢?
|
||||
我们多次提到,技术问题转为ROI问题的事情。那么,你在研发中碰到过类似的事情吗?你是如何选择的呢?
|
||||
|
||||
|
||||
期待你在评论区的分享,我会及时回复。反爬无定式,我们一起探索。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
208
专栏/反爬虫兵法演绎20讲/03反爬虫的发展以及展望:我们也不是什么正经工程师.md
Normal file
208
专栏/反爬虫兵法演绎20讲/03反爬虫的发展以及展望:我们也不是什么正经工程师.md
Normal file
@ -0,0 +1,208 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
03 反爬虫的发展以及展望:我们也不是什么正经工程师
|
||||
你好,我是DS Hunter。
|
||||
|
||||
在上一节课里,我们讲了反爬虫方是如何对抗爬虫方这个坏人的。这节课,咱们一起看一看,在内卷之下,反爬虫真的能保证“不作恶”吗?
|
||||
|
||||
这节课是我们历史背景篇的最后一节课,我们来点轻松的,我会首先讲一讲反爬虫方和爬虫方这两方各自最通用的两个手段——验证码和浏览器模拟的历史过程,然后再用几个故事来带你看看反爬虫的近期发展。
|
||||
|
||||
在一些故事的结尾,我也会预言一下后续的发展。当然了,预测未来是一个不怎么靠谱的事情,失败概率极高,不过我还是来无责预测下。
|
||||
|
||||
爬虫方和反爬虫方的大招
|
||||
|
||||
我们这里把大招理解为以不变应万变的经典招式,它们不会固定存在于爬虫和反爬虫克制链条中的某一环节,但是,却可以无处不在。当然,我还是把它放到了链条中,因为当斗争激烈到某个程度时,大家更倾向于想起这些经典大招(下面的链条图仅供参考)。-
|
||||
|
||||
|
||||
低效率的浏览器模拟
|
||||
|
||||
我们先来看看爬虫方的进攻手段,浏览器模拟。在我们上一讲中的爬虫第一招——接口定制化部分提到的反转,指的就是这里。爬虫从全面模拟浏览器,变为只抓指定接口,现在又变回了全面模拟浏览器,转了一圈又回到了原地。因为“浏览器模拟”和验证码一样,基本上是万能的——因为被封杀的可能性最低。
|
||||
|
||||
是的,爬虫厌倦了无休止的检测与反检测,决定直接使用浏览器模拟请求。这个时候,内卷重新开始。但是要知道,请求价格接口只有一个请求,而浏览器请求站点,请求量会急剧飙升,拖慢网站性能。
|
||||
|
||||
针对浏览器爬虫,业界内并没有特别好的解决方案。以前有canvas指纹,现在有DOM指纹,核心都是标记相同类型的浏览器。原因是,大部分的浏览器都是批量部署的,因此环境完全一致。
|
||||
|
||||
canvas指纹可以在一定程度上检测到相同类型的人,然后你可以给予封杀。但是这个并不准,甚至可以说误伤率很高。而且从描述我们就看得出,这里的封杀,并不是封杀爬虫,而是封杀“有相同特征的请求”,如果人工找到其中一个是爬虫,那么这一批就都不放过。但是我们并不在乎这种请求是否是真人。此外就是指纹也存在冒充,你要给予足够复杂的加密措施,让他拿不到原始指纹来冒充。DOM指纹也是一样的道理,主要用于检测Selenium之类的平台。
|
||||
|
||||
如果非说有什么解决方案,那就是瞄准性能——浏览器爬虫的死穴,开干。浏览器爬虫性能很糟糕,接口爬虫能爬一万次的话,相同资源下浏览器爬虫能爬到一百就了不起了——实际上可能更差,这就是我说它效率低的原因。
|
||||
|
||||
因此,反爬方极可能会随机拖慢网站性能,来进一步影响爬虫方的效率,甚至可以随机拖慢信息加载的时间。要知道,价格并不影响SEO(Search Engine Optimization,搜索引擎优化),就算有什么影响,也只是误伤用户。
|
||||
|
||||
只是,用户招谁惹谁了呢?为什么要拖慢网站性能呢?你们俩内卷,为什么要误伤我?
|
||||
|
||||
验证码
|
||||
|
||||
另一边,“验证码”是反爬方都会用到的大招。它可以存在于这个克制链条的任意一个环节。其实,验证码一开始就是为了反爬虫而生的——这是校验你是不是一个人类最好的办法。
|
||||
|
||||
首先我们来看下验证码是什么。
|
||||
|
||||
根据公开资料,验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自动区分计算机和人类的图灵测试)的缩写。也就是说,这个东西最开始设计的目的,就是为了区分请求来自机器还是人类。可想而知,验证码就是为了反爬而生的。假设这个世界没有爬虫,可能也就不会诞生验证码。
|
||||
|
||||
上古田园时期,验证码是一大杀器,虽然那个时候验证码只是能够把一些简单的文字转换成图片让你来识别。在OCR技术(Optical Character Recognition,光学字符识别)还不发达的时候,验证码可以说秒杀所有的爬虫。但是后来随着OCR的发展,识别验证码已经沦落为机器学习的入门课程,成了学生练手项目。最开始无敌的验证码,就这样被时代秒杀了。
|
||||
|
||||
而现在的验证码变得越来越奇葩,已经不仅仅是图片识别成文字的形式了。例如Google的找出人行道、12306的找出水果,甚至是沪牌拍卖网站的各种动态验证码等等,原本用于识别人类的验证码,逐渐变得越来越反人类。
|
||||
|
||||
本质上,验证码并不应该存在,而且它的效果也越来越不好,我们到了放弃验证码的时候了。
|
||||
|
||||
一方面,随着老龄化的到来,越来越多的老年人开始使用互联网。这个时候你用验证码让他算一个复杂的算式?或者让他找出图片里的佩奇——“嗯?啥是佩奇?”所以,这种行为我个人十分不提倡。验证码已经很难检测人类了,误伤人类的本事倒是越来越大。如果非做不可,我宁可选择滑块。
|
||||
|
||||
此外,还有一个重要的原因——“打码平台”工具。简单地说就是将你的验证码截图发送给平台,平台会众包给真人去识别,按次数计费,越难的验证码,费用越高。技术问题再次转换为了ROI(return on investment,投资回报率)问题。
|
||||
|
||||
你看,验证码虽然是反爬虫的万能大招,但是却对于普通用户的伤害极大。而且由于“打码平台”工具的存在也会影响反爬的结果,这项技术的收益越来越小,伤害越来越大。就如同一个农药,虫子在已经有了广泛的抗药性的同时,农药的毒性丝毫不减——你就没有理由选择它了。
|
||||
|
||||
所以,验证码的时代过去了,尽量忘记它吧。
|
||||
|
||||
不正经的反爬虫套路
|
||||
|
||||
在大家都放了大招的情况下,斗争逐渐进入白热化,用的办法也就越来越阴损了起来。之所以给反爬虫这个角色加上标题这一句“我们也不是什么正经工程师”的台词,就是因为,他,或者他们,至少可以做到以下三件不正经的事情:
|
||||
|
||||
|
||||
反向注入;
|
||||
社会工程学;
|
||||
心理战争。
|
||||
|
||||
|
||||
那我们就一一来看看,这些不正经的的反爬套路,都有哪些“不正经”。事先声明,这些反爬虫套路的事件绝对真实,不过在细节上会有一些改动。至于主语“我”,只是为了叙事方便。
|
||||
|
||||
反向注入
|
||||
|
||||
|
||||
那是一个平静的晚上,我像往常一样刷刷视频准备睡了,然而一个电话震醒了我:“哥,江湖救急,我们公司的服务器硬盘被格了!”-
|
||||
-
|
||||
我当时愣了一下,说:“哥,你才是哥,我和你说了多少次了,我不是做安全的,我是做反爬虫的,不要老是因为安全问题找我好吗?服务器硬盘没了你找安全或者报警啊。”-
|
||||
-
|
||||
“不好意思,安全没查到任何问题,而且报警不行,因为是爬虫机全跪了,所以……”-
|
||||
-
|
||||
我只好大半夜赶去解决问题。-
|
||||
-
|
||||
查看现场后发现,虽然不是每台机器都中招了,但是中招的机器爬虫机节点全跪,连根消失。运维紧急停掉了所有的爬虫节点,保住了剩余的机器。-
|
||||
-
|
||||
经过一番权限隔离,重现故障,最后终于拿到了能引发问题的js。然后对比之前的js代码,我们得出了一个差异:“如果存在process变量,并且可以require到child process,那么使用child process的功能,执行一段Linux命令:rm -rf / –no-preserve-root”。
|
||||
|
||||
|
||||
这是我第一次知道,原来默认Root也不可以直接rm掉根目录的,需要加一个额外的参数才行,我甚至有些纳闷写这段反爬虫代码的人是如何自测的。由于是跑了很久才出的结果,因此可以证明,这个代码是随机出现的——只是一旦出现,就没有后续了。
|
||||
|
||||
最终问题还是解决了:运行Token那段js的机器被拆分出来、Root权限被去除,最关键是使用了Docker(之前是虚拟机),后续再也没发生过类似的事情。由此我们也猜测,也许他们自测也是用Docker做的呢?毕竟Docker的恢复能力简直逆天。
|
||||
|
||||
但是这件事情给了我极大的震撼。如果说,反爬虫方可以删除任意文件,那么,这个反爬虫的想象力还是薄弱了。他完全可以创建文件,赋予可执行权限,这样相当于直接给爬虫机挂一个后门!
|
||||
|
||||
你可以理解为,一个小偷去偷东西,偷完了都放自己仓库里。结果有一个东西实际上是特洛伊木马,小偷也没当回事,毕竟自己才是坏人啊,也没想过防着别人。结果看起来被偷的可怜人,把小偷的仓库给端了。
|
||||
|
||||
我们甚至可以再开一点脑洞:既然可以挂后门,那么,SQL注入呢?XSS?我们能想到的安全漏洞,都可以试一遍。毕竟,爬虫工程师是多么的信任反爬虫!什么脚本都敢拿来放机器上跑的!
|
||||
|
||||
可见未来,反爬虫工程师不仅仅是前端的事情,更可能回归到安全领域。那么前端和安全合起来,就是前端安全工程师。也许,这将是反爬虫未来的主力军。
|
||||
|
||||
社会工程学
|
||||
|
||||
人们谈起社会工程学,总是会觉得,这有啥技术含量,这不就是坑蒙拐骗吗?是的,的确不是很有技术含量。但是相当管用。
|
||||
|
||||
我们来看这样一个故事。
|
||||
|
||||
|
||||
曾经有一个公司要求我去做一个反爬虫的讲座,然后我在现场拉他们的日志,给他们详细讲解每一个IP可能存在的问题。我当时举了个例子,我说:“你们看,排名前十的这些IP,基本都是有问题的,但是是不是一定要封锁呢?不一定。我们进行一下端口扫描。”-
|
||||
-
|
||||
本意我是想说,扫描出有开放端口的,嫌疑增加。无开放端口的,嫌疑降低,但是也不能算无辜。毕竟就是为了这个demo操作一下,也不觉得真的能扫描出什么,更别提确定有问题的IP了。-
|
||||
-
|
||||
扫描后发现,其中一个IP开放的端口是8080,我当时就顺手telnet上去,说:“大家看,端口连上去,只要随便发送点信息过去……”嗯?怎么看起来是个HTTP服务而不是代理服务?-
|
||||
-
|
||||
用浏览器直接打开8080端口,当时现场的人都惊呆了:这不仅仅是个爬虫节点,这是爬虫的管理系统啊!上面赤裸裸摆着所有的策略、数据、调度,而没有任何登录校验!-
|
||||
-
|
||||
我当时灵机一动,说了句:“嗯,这就是我们要讲的弱密码导致的问题……不对,这都无密码了,不过道理是一样的……”-
|
||||
-
|
||||
魔幻吗?并不魔幻。这种事情在小公司再正常不过了。-
|
||||
-
|
||||
当时对方说:“要不顺手把所有策略都删了吧,让他知道我们的厉害。”-
|
||||
-
|
||||
我当时心想:“这不一下子就让他知道我们来过了么?”但是脸上还是带着微笑,说:“我们更好的策略不是时刻偷窥他吗?知道他在干什么,知道他是怎么爬的,然后引导他去指定的位置任由我们拿捏。为什么要干掉人家呢?给人家一口饭嘛。”
|
||||
|
||||
|
||||
这个故事是想告诉你:很多反爬虫技巧,不一定会在期望的地方起作用,有时候会有意外收获。
|
||||
|
||||
也许你会觉得,这和社工好像没啥关系啊?我们仔细看看,这真的没关系吗?
|
||||
|
||||
诚然,故事中有极大的运气成分,说是天上掉馅饼也不为过。但是这种弱密码的系统,网络上少见吗?根本不少,甚至可以说遍地都是。
|
||||
|
||||
甚至有些人为了炫耀自己的技术,把爬虫代码直接放在了Github上面,甚至源代码里还有数据库连接串!关于如何社工Github我就不展开了,相信稍作尝试,你就能很快自行想通关键点。 如果不是用Github,线下如何获取这类信息?相信你在这个思路的带领下,会慢慢找到很多办法。比如,面试一下?
|
||||
|
||||
心理战争
|
||||
|
||||
心理战争其实和社会工程学有很大的交集。《孙子兵法》说:“上兵伐谋,其次伐交,其次伐兵,其下攻城。”也就是说,和对面对着死磕,那是下下策,最好是不动用兵力就搞定战争。同样的道理,最好的反爬虫,其实就是不和对方一起消耗资源——包括上面提到的人力资源,直接从根本上解决掉问题。
|
||||
|
||||
还是AB两家公司。A依旧是爬虫公司,B是反爬虫的公司。
|
||||
|
||||
|
||||
根据经验,逢年过节B公司一般都会上线新版反爬虫代码,抢占订单高峰期间的价格优势。大年三十,爬虫团队一群人在屏幕前面等着新版本的反爬策略。-
|
||||
-
|
||||
12点的钟声敲响了,反爬虫策略准时发生了变更。并且带了一行注释:“策略是系统自动切的,我们早下班了。我们是19薪,而且节假日不加班哦!”-
|
||||
-
|
||||
据说那次破解的时间非常久。是策略太难?还是人心散了,队伍不好带了?
|
||||
|
||||
|
||||
我们开篇就提到过,爬虫和反爬虫斗的就是资源。而资源,是机器资源和人力资源的总和。机器资源有钱就能加,而人力资源则不同。
|
||||
|
||||
诚然,有钱可以雇佣到更好的、更多的人,但是边际成本实在是太高了,越加越难。所以,如何尽量降低自己的资源消耗,增加对方的资源消耗呢?
|
||||
|
||||
我经常用战争来形容爬虫和反爬虫,而战争打的就是消耗。《孙子兵法》的作战篇是这么说的:“故智将务食于敌,食敌一钟,当吾二十钟。”可见战争的关键就在于消耗。甚至你在计算ROI的时候,对方的消耗,是可以计算在内的。这个我们进阶篇里,会详细给你展开。
|
||||
|
||||
而消耗对方人力资源,最好的办法往往不是技术办法,而是影响对方员工心理。你看,破解了那么久,得到的却是嘲讽的注释,心态可能不崩吗?
|
||||
|
||||
我们接下来再看一个新故事:有AB这么两家公司,A公司是做爬虫的,B公司是做反爬的。
|
||||
|
||||
|
||||
有一天,B公司在自己反爬代码里加了一行注释:“能跟踪到这里说明你水平非常牛,何不与我们的HR聊聊?QQ:xxxxx”(当时还是qq的时代)。-
|
||||
-
|
||||
A公司的爬虫工程师默默加了这个号码,结果HR给出的价格没有太大的诚意,这个爬虫工程师决定不跳了。-
|
||||
-
|
||||
不过,HR妹子每天在朋友圈各种晒自拍,经常找爬虫工程师吐槽生活的不顺,慢慢的居然和爬虫工程师成了朋友。两个人无话不谈,甚至爬虫工程师说要不把你挖来我们公司做HR算了。HR开心的表示好啊好啊。但是又用各种理由推脱。-
|
||||
-
|
||||
聪明的你应该已经想到了,这个HR一定是有意来套信息的。没错,她除了了解这个爬虫工程师的知识盲区,有时候还偶尔测试一下他的一些知识量——如果感觉他知道,就不在反爬里用,效果非常好。爬不到数据的时候,还安慰安慰他——也就知道了自己的反爬效果如何。-
|
||||
-
|
||||
可能你会很纳闷:真的有这么弱智吗,这不是很明显吗?-
|
||||
-
|
||||
毕竟,男人在恋爱中的智商为负数。在两家合并之后,反爬方都吐槽过:“你是不是傻,哪个妹子陪你没事聊ES6的特性?”
|
||||
|
||||
|
||||
嗯,没错,这个“HR妹子”,其实是个180斤的壮汉……
|
||||
|
||||
这个事情首先告诉了我们:网络交友并不可靠。你可能会觉得,不过这个和我们这节课似乎没有太大关系。不过,真的没关系吗?
|
||||
|
||||
你可以看看你身边的工程师们,年纪大的、拖家带口,随时可能为了家庭做出一些不可思议的事情,并且事前一点征兆都没有。而年轻的,尤其是年轻的小伙子,不可控性就更高了。所以不要觉得你的团队很稳定,说不定早已是暗流涌动。
|
||||
|
||||
我们说反爬虫主要打的不是机器资源也不是技术,打的是人!人才是胜负的关键。这些人如果不稳定,多好的系统都拦不住对方。这也是为什么后面我们会反复提到团队搭建,要知道,团队如果出问题了,那么反爬虫出问题是迟早的事情,甚至可能比没有反爬虫更糟糕。
|
||||
|
||||
小结
|
||||
|
||||
好了,我们这节课讲到这里,也就接近尾声了,最后我来和你总结一下今天讲的内容。今天我先给你讲了爬虫方和反爬虫方的经典招式:浏览器模拟和验证码。不论博弈进行到何种程度,它们总能快速进入战场开始厮杀。接着,我用四个小故事,给你讲了三种不正经的反爬虫套路,它们分别是:反向注入、社会工程学和心理战争。
|
||||
|
||||
回到我们这节课的标题,为什么我说反爬虫工程师不正经呢?通过这几个故事你应该明白了,反爬虫方虽然本来应该是光明磊落的防御方,但是实际上出于一些现实的原因,反爬虫方通常都会变得亦正亦邪,甚至可能做出一些出格的事情。甚至,这些事情不合理、不合法,但是你没办法通过法律手段来解决。但是无论如何,最无辜的,还是被爬虫反爬虫战争所误伤的普通用户。
|
||||
|
||||
至于不能走法律手段的原因,其实很简单:
|
||||
|
||||
第一,爬虫方自己就很不干净,起诉对方那是杀敌八千自损一万;
|
||||
|
||||
第二,谁主张谁举证,想证明反爬坑害自己,举证难度难于上青天。所以我们听过的案例一般都是反爬虫方起诉爬虫方。不过说实话,能拿到这个证据,也是说明爬虫的水平太低了。而如果爬虫能反诉反爬虫并获胜,那我觉得反爬虫方真的要弱出天际才行。
|
||||
|
||||
最后,还是给你预言一下未来吧。随着相关法规的不断完善,爬虫将逐渐变得正规化,不再以偷窃为主,而是走API(Application Programming Interface,应用程序接口)合作的路线。爬虫最终会在大厂消失,成为一个民间艺术,而反爬虫将成为大厂必备技能。
|
||||
|
||||
但是,这个过程会十分漫长。在这个过程中,由于爬虫的长期存在,将会催生出一些新的职业,反爬虫终将从安全团队剥离出来。从安全团队中跳出来,反爬的动作也将不再仅从安全的角度思考,更可以进行战略上防守反击的准备。那这个行业,我们暂定就叫前端数据安全工程师吧。
|
||||
|
||||
思考题
|
||||
|
||||
今天的思考题会相对轻松一些。不过虽然轻松,还是不要把“脱敏回答”抛到脑后啊。
|
||||
|
||||
|
||||
你的项目中有考虑过法务风险吗?法务评审是怎样的?法务对相关技术了解多少?
|
||||
你们考虑过用法律武器来维护自己的合法权利,或者攻击对方吗?你的对手最怕什么?你如何用非技术手段来攻击他?
|
||||
单纯从技术角度来看,除了Shell,XSS和SQL注入,你还能想到什么办法来“反向攻击爬虫团队”呢?
|
||||
|
||||
|
||||
期待你在评论区的分享,我会及时回复。反爬无定式,我们一起探索。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
216
专栏/反爬虫兵法演绎20讲/04爬虫的首轮攻势:如何低调地拿到自己想要的数据?.md
Normal file
216
专栏/反爬虫兵法演绎20讲/04爬虫的首轮攻势:如何低调地拿到自己想要的数据?.md
Normal file
@ -0,0 +1,216 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
04 爬虫的首轮攻势:如何低调地拿到自己想要的数据?
|
||||
你好啊,我是DS Hunter。又见面了。
|
||||
|
||||
前面我和你聊了聊爬虫和反爬虫的历史,感觉这是一个内卷的死结。
|
||||
|
||||
在开篇词里我提到过:内卷之下无胜者。也就是内卷一旦开始,你就只有两个结局:输,或者输得很惨。你的所有努力,都是让自己不要输得太惨,而不是考虑如何创造收益。有了这个基本方针之后,我们才能知道后续应该往哪个方向去努力,才好进一步制定对应的策略。
|
||||
|
||||
通过第一个模块的历史视角回顾,相信你已经对什么是爬虫有了更深刻的了解。而从这一讲开始,我们就正式进入爬虫、反爬虫的理论环节。接下来所有的讨论,就从发起攻势的爬虫方开始吧。
|
||||
|
||||
从“5W1H分析法”到爬虫行动
|
||||
|
||||
我首先要问你一个问题:老板把任务给你了之后,爬虫要干什么?
|
||||
|
||||
根据5W1H原则(万恶的方法论啊),你可以看到,需要讨论的有:WHAT、WHERE、WHEN、WHO、WHY、HOW。那么迁移到爬虫身上呢?
|
||||
|
||||
老板把任务布置下来之后,这个WHO就没什么可讨论的了,肯定是你,爱干不干,不干走人。 至于WHY?老板有需求,有什么可WHY的,还是不干就走人。而WHERE,WHEN?当然是Anywhere,Anytime,卷起来!只要对方站点扛得住,就日以继夜地死命干他。后面在06讨论分布式的时候,我会和你分享分享关于WHERE和WHEN的思考。
|
||||
|
||||
现在,我们就只剩下了WHAT和HOW。这也就简单了很多。我们的问题只有:爬什么,怎么爬?所以,接下来我会带你了解爬虫的抓取流程。在这个过程中,你就能理解怎么在完成老板需求的同时,保护好自己。而整个过程的关键词只有一个,那就是“低调”。
|
||||
|
||||
抓取流程
|
||||
|
||||
爬虫随着网络而生,那么我们讨论的爬虫要么基于TCP协议,要么基于HTTP相关的协议。也许有些爬虫是爬FTP的,但是这种情况非常少。当然,不管使用什么技术,我们都要始终记住一点:保持低调。毕竟爬虫本身就不是一个光明正大的事情,再高调地去抓取自己想要的东西,就会死得很快。
|
||||
|
||||
既然确定了技术方向,那么接下来,就要进行抓取了。根据大多数爬虫系统的经验来看,无论是什么爬虫,我们主要的抓取步骤都是以下四个部分:
|
||||
|
||||
|
||||
|
||||
其中,最能帮助我们保持低调的就是步骤二和步骤三了。而至于步骤一和步骤四,我会详细地跟你说说和提升能力、降低消耗有关的事情,也会对你有不小的帮助。我们就从第一步开始吧。
|
||||
|
||||
使用对应的网络协议请求服务器
|
||||
|
||||
关于使用对应的网络协议请求服务器,简单来说,就是对方用什么我们就用什么,而Web一定是HTTP,App大部分是TCP。这一句话就可以解释第一步的动作方向了。
|
||||
|
||||
今天这一讲,我们主要讨论使用HTTP协议请求服务器的情况。不要觉得武断,我们还是从历史的角度来进行说明。
|
||||
|
||||
我们都知道,在本质上,爬虫就是一个Cosplay。服务器开放了端口给浏览器访问,那么就必然无法验证来访问的是不是一个真的浏览器。
|
||||
|
||||
最早我们是使用TCP协议直接发起请求的,写爬虫的人需要创建一个TCP链接,按照HTTP协议的格式逐字节去写入数据,分析返回数据,来实现数据的抓取。
|
||||
|
||||
谢天谢地,这种残酷的日子一去不复返了。现在各大语言都直接加入了HTTP请求相关的库,甚至随着爬虫的发展,很多爬虫专用的库也出现了,越做越精细,也越来越不需要你关注底层了。
|
||||
|
||||
目前来看,大多数情况下,我们抓取服务器都是用HTTP协议,毕竟爬虫是随着Web 2.0发展起来的,而Web 2.0的主要载体就是HTTP。
|
||||
|
||||
你可能会觉得,随着App时代的到来,HTTP越来越不吃香,反而是TCP的爬虫又追了上来。但我要说的是,虽然现在各大公司的信息主要以App为主了,不过HTTP爬虫也并非一无是处,首先它可以快速抓取,其次它可以用来辅助验证App的抓取结果。因此HTTP爬虫会长期存在,不会消失,这也就是我们主要讨论HTTP协议请求服务器的原因。
|
||||
|
||||
所以,虽然有些HTTP的技巧会慢慢变得不实用,但只要大家没有抛弃 Web,HTTP爬虫就一直有用武之地。
|
||||
|
||||
除此之外,关于这里的能力提升,我的建议是:
|
||||
|
||||
去撸一个TCP爬虫。
|
||||
|
||||
|
||||
为什么又到了TCP爬虫?-
|
||||
-
|
||||
原因很简单,爬虫,这个过度封装的Cosplay爱好者,它过度封装之后的好处就是无需关注细节。但是坏处也就是一旦细节出了问题,你根本不知道问题出在哪里。像是03中反向注入的故事,就是在封装好的爬虫的内部动了手脚。因此,直接用底层TCP撸一个线上爬虫用于生产,我是绝对不赞成的,这属于炫技,毫无用处。但是作为入门,这种练习对细节的考察还是很深入的。后续如果碰到高阶反爬虫,在底层原理上下绊,也能处理得游刃有余。-
|
||||
-
|
||||
此外,如果你后续要进阶到App爬虫,大部分是要回到TCP层来抓取的,因为基本上没有哪家App还在使用HTTP协议了,都是自有的定制协议。这类协议要用TCP抓包,然后猜测每个字节的用处。
|
||||
|
||||
|
||||
确定抓取数据及抓取策略
|
||||
|
||||
确定对应的网络协议请求服务器之后,我们就可以着手准备挑选抓取对象了。
|
||||
|
||||
为了后续能够顺利讨论,我们先来明确一下各个名词的含义。
|
||||
|
||||
抓取数据部分,我们通常会将商品数据分为两类,重点商品和热卖商品。重点商品,可能是我们后续需要观察的商品;热卖商品,则是用户关心的、经常点击的商品。当然,两者可能有重叠。
|
||||
|
||||
至于抓取数据的手段,从抓取的时机维度,我们通常将抓取手段分为两类,一类是Job抓取,一类是实时抓取,这两种手段各有优劣。Job类型的抓取,周期性很强,在流量曲线中容易被抓;实时抓取相对来讲不易被抓,但是因为是通过用户点击商品实时触发,所以我方的热卖产品信息,很容易泄露。我们能做的,就是利用它们的优劣来决定我们要抓取的数据和抓取策略。
|
||||
|
||||
好了,所有的概念明确之后,我们来看看抓取数据和抓取策略的选定吧。这一步,是我们整个抓取流程的重点之一。想要低调,就要先收一收自己的野心。
|
||||
|
||||
毕竟你的老板一定会说:我全都要!但是这并不现实。
|
||||
|
||||
不现实的第一个因素:流量问题。要知道,你们是竞对,假设你们各占50%的市场份额,这就意味着如果你有N个商品,那对方也有N个商品。你的N个商品要和对方的信息来对比,那么你至少抓取量是N。如果价格实时变化,每天需要抓取k次,那么抓取量就是kN。再假设你的每日PV(Page View,页面浏览量)数是M,那么每个用户在查询价格的时候,你们会触发一个实时比价爬虫,那么对方就会收到M的爬虫流量。这样算下来,对方一共要接受M+kN的流量。
|
||||
|
||||
而他是你竞对,你们的PV是M,他的PV十有八九也是这个级别的。这意味着他系统承受的爬虫流量要超过自己业务流量。你如果还奢望在这种情况下隐藏自己,实在是太不现实了。
|
||||
|
||||
所以,一定要和老板砍掉“我全都要”这种需求!再次强调,要低调!
|
||||
|
||||
第二个因素:爬虫的危险性。实时爬虫一旦触发,竞对如果借着你的爬虫顺藤摸瓜,记录下来你的热卖产品,然后进行分析,那才是最可怕的。况且,能立刻得到你的销售数据,这一点可比反爬虫本身更有价值。因此,实时爬虫一定不要做!非做不可的话,一定要做随机,不能全量实时抓取,否则,全量实时抓取就等于对方本来不知道你这面的销售数据,结果你主动推送数据给对方。
|
||||
|
||||
通过咱们刚刚聊到的两个点,我们可以知道,圈定重点商品之后,再加上部分随机热卖产品,就是我们要抓取的数据了。而我们的抓取策略就是:重点商品数据用Job抓取,热卖商品数据用实时爬虫抓取。
|
||||
|
||||
最后,还是要和你强调一下,确定数据是爬虫的一个重点,绝对不能随意圈定。尤其是不能让产品经理随意定,屁股决定脑袋,产品经理的职位注定了他们需要尽可能多的数据,如果你问他们一个数据需要不需要,那答案一定是需要。
|
||||
|
||||
他们完全不懂爬虫的可怕之处,也不了解反爬虫的阴险之处,即使了解,他们也可能为了自己的业绩,假装不知道。一定要有专业的人来决定这个事情。或者,增设一个爬虫产品经理的岗位,他可以不仅仅对“数据全面”这一个指标负责,也综合考虑公司利益。产品经理并非坏人,KPI才是万恶之源。
|
||||
|
||||
执行抓取
|
||||
|
||||
确定了网络协议、抓取的数据和抓取策略之后,就可以开始执行抓取了。根据第2步我们知道,现在需要抓取的数据被分成了两部分,一部分是重点商品,一部分是热卖商品。我们先来看重点商品部分应该怎么执行抓取。
|
||||
|
||||
|
||||
重点商品:Job抓取
|
||||
|
||||
|
||||
重点商品是走Job的,因此,需要定期触发。Job不要过于频繁,否则就无法低调的抓取。
|
||||
|
||||
此外这里有个误区,很多人为了避免对方服务器被抓出问题,就赶在业务低谷期(错过业务高峰)去抓取,这可就大错特错了!
|
||||
|
||||
国内业务低谷期一般在凌晨三、四点左右,这个时候,服务器压力的确小了很多。但是你要考虑对方的程序员也都下班了,一旦出了问题,没有人能快速上线解决,只能靠值班的人先壮士断腕——降级熔断,然后再联系对方的程序员。你的本意可能是想对竞争对手好一点、保留一些善意,可是发生这样的事情,是不是与你的预期完全不一样呢?
|
||||
|
||||
而高峰期,虽然服务器压力较大,但是要注意,对方的人是齐全的,不管发生什么事情都可以迅速搞定,甚至秒级扩容,这个时候抓取出问题的概率比低谷期还更低一些。这个与我们的直觉可能完全不同。
|
||||
|
||||
此外,很多商品可能价格是随时变动的,你大半夜抓个价格,到了白天的时候还有什么参考价值呢?
|
||||
|
||||
因此,Job正常设置,不用刻意挑时间,唯一需要注意的是频率。此外,Job开始,并不意味着抓取开始,Job应该只是将抓取消息发送给节点,具体的抓取时间应该由节点自己来决定。简单的说就是:将在外,君命有所不受。
|
||||
|
||||
最终节点再将信息汇总,抓取就结束了。这就是Job类型的抓取。
|
||||
|
||||
|
||||
热卖商品:实时爬虫
|
||||
|
||||
|
||||
刚刚提到还有一种抓取就是实时爬虫。这里要注意两点,一个是数据范围,另一个就是具体抓取习惯。
|
||||
|
||||
首先,数据范围,也就是商品选择。实时爬虫的范围要尽可能小,并且不能全是热卖商品,一定要再加入一些非关键商品。尽可能将部分头部商品加入池,部分中部产品加入池,然后每天轮换,头部商品和中部商品的比例也要一直调整。
|
||||
|
||||
虽然这样会带来业务的一些不满——毕竟他们期待的理想结果是全爬。但是为了保护公司隐私,这是不得不做的策略——并且要尽可能保密。要知道,商场没有太大的秘密可言,如果你信任你的同事,把策略都告诉他了,可能你就是酒足饭饱吹个牛而已。但是下个月,他也许就会跳槽到了竞对。到时候他还会保密吗?
|
||||
|
||||
第二点,具体抓取的习惯,一定要是和Job爬虫不一样的。为什么要注意这些问题呢?其实主要是怕被对方反抓。
|
||||
|
||||
我们刚刚说过,Job爬虫是非常容易被对方抓的,如果对方抓了之后不拦截你,假装没抓到,就可以根据你的请求特征,顺藤摸瓜抓你的实时爬虫,后果会很恐怖。实时爬虫通常意味着这些商品对你最重要,那么未来在商业上,他们会重点打击这些商品。
|
||||
|
||||
如果针对Job爬虫和实时爬虫使用不同的抓取代码,能大大降低这个概率,因为看起来像两拨人,很难串联起来。这样,也就做到了低调。不过因为人的惰性,一般即使用了两套代码,也不会相差特别大,会有相同的个人习惯在里面。
|
||||
|
||||
理想的状况,是有足够的资源支持,两个团队互不交流、分别抓取。不过这样的成本实在不低,至少代码库要用两套。但是这样的好处就是,对方即使抓到你了,也会质疑自己的判断,认为不可能是同一拨爬虫。
|
||||
|
||||
解析、验证数据
|
||||
|
||||
拿到了数据却无法快速解析、无法验证真伪,其实就相当于拿到了没用的数据,那接下来我们就一起帮助数据发挥自己的价值。
|
||||
|
||||
|
||||
解析数据
|
||||
|
||||
|
||||
解析数据是个千古难题。
|
||||
|
||||
这里推荐一篇叫《火星人的耳机》的文章给大家。虽然是一篇很老的文章,但是他详细解释了为什么Web标准这么难做,HTML标签那么混乱。
|
||||
|
||||
简单来说,就是因为浏览器版本的更新迭代,要持续保持兼容性,因此HTML的解析就变得逐渐混乱起来。遵循标准本身没有商业利益,浏览器厂商动力也不大。加上标准诞生于浏览器之后,不可能让前置的浏览器穿越时空来遵循后制定的标准,这就好比我们不能要求古装剧的人像现在的人去思考,他们有他们那个时代的思考逻辑。
|
||||
|
||||
这一点, 直接导致了解析HTML一直以来占据了爬虫的大部分工作量。
|
||||
|
||||
谢天谢地,现在有很多库可以支持帮你解析,不用自己来写正则一个一个匹配了。但是碰到畸形的标签,还是要手动调整——甚至对方可能是故意的!很多反爬虫方对一些畸形的HTML标签了如指掌,并且他们知道浏览器可以解析:因为他们可以通过线上用户帮自己去测试。这也就是我们解析数据的第一个方法,库的支撑和手动调整相结合。一般说来,这样就不至于自己写正则了。
|
||||
|
||||
除此之外, 我们还有一个方法就是走浏览器渲染直接拿到DOM(Document Object Model,文档对象模型)。这种办法原理上没有任何问题,唯一的死穴就是,性能太慢了。DOM渲染是前端一大难题。大部分前段框架,核心的功能就是在减少DOM操作,提高浏览器性能。因此本地拉浏览器引擎进行渲染,并非不能做,但是你需要极大的资源,需要评估是否值得。
|
||||
|
||||
总体表现如下表:-
|
||||
-
|
||||
-
|
||||
我们说过,一旦一个技术问题成为一个ROI问题,那么反倒好办了。你只需要在收益上打平消耗即可。因此,我们现在需要考虑的问题是:我们在解析数据上大概能付出的成本有多少?
|
||||
|
||||
从表格中可以看出,浏览器直接解析DOM会导致机器消耗高,而手动解析HTML会导致人力资源消耗高。但我们根据常识可以知道,机器成本是线性的,而人力资源消耗是一次性的,或者认为是边际递减的。所以,如果你的解析量并不大,那么可以考虑用浏览器解析来降低总成本,让机器消耗去吧。而如果解析量很大,那么尽可能使用代码来解析,是时候消耗人力资源了,这样能够获得一个高效率的解析,降低总成本。
|
||||
|
||||
|
||||
验证数据
|
||||
|
||||
|
||||
最后是验证数据,也就是验证你抓取到的数据是不是真实数据。
|
||||
|
||||
验证数据有两种,一种是机器验证,一种是人工验证。机器验证在前面我们已经详细介绍过了,还介绍过反爬虫方的反验证方式。因此打到最后,难免会进入人工验证。这里,你也可以参考在02中的机器人工双校验部分,具体的步骤内容非常详细。今天,我们重点来看看这两种验证方式的注意事项。
|
||||
|
||||
首先是机器验证。
|
||||
|
||||
机器验证一般就是交叉验证,也就是PC端、小程序等等各个渠道互相校验。但是,这样做会增大对方服务器的压力,会有被发现的风险,因此不是很推荐。
|
||||
|
||||
此外机器验证还有一种取巧的办法就是,有意中个爬虫试试,看下对方提价数值是多少。如果你的爬虫也拿到了这个价格, 那就说明你的机器验证策略被发现了。当然,这种办法只能针对那些提价策略并不复杂的反爬虫团队。不过总的来说,还是一个很好的补充手段。
|
||||
|
||||
而人工验证,则没有任何技术含量,基本就是人工抽检即可。当然,也有一些需要注意的事情。
|
||||
|
||||
第一,人工验证不再有小概率性事件的概念。你需要时刻记住:你面对的是活生生的人,而不是自然界的随机事件。一旦你的爬虫中了,那就是中了,人工干预的事件,是不符合概率论的。直接丢弃全部数据即可,它们没有一个是可信的。至于何时重试, 需要根据成本来综合考虑。
|
||||
|
||||
第二,要熟知对方的业务逻辑,知道价格计算方式,避免因为不了解对方的价格计算模式而误以为自己价格抓错了。例如有些价格与优惠券、地区、用户属性相关等等。如果你不了解,拉到不同的价格就以为自己做错了,将寸步难行。因此验证数据这一步,建议对业务熟悉的人员来操作,而不是通用的测试人员。
|
||||
|
||||
基于这一点,我一直反对把爬虫做成中台。中台看起来节约了研发成本,但是天花板实在是太低了。有些公司,前期还能做得有模有样,但是,一旦对方发力做反爬,就无法招架。这就是因为中台方对对方的业务了解程度不高,被欺骗了都不知道。
|
||||
|
||||
再看另一个例子,有个公司抓取别人的小说,一直以为自己抓得好好的,实际上都是对方拿别的章节来冒充的。在没有业务端和读者反馈的情况下,技术人员很难发现这一点,甚至还觉得自己特别厉害。
|
||||
|
||||
总结
|
||||
|
||||
好了,到这里,我就介绍完了低调完成爬虫操作的全过程,给你总结一下吧。
|
||||
|
||||
首先,我们会使用对应的网络协议请求服务器,这里根据对方服务器使用的协议,我们就可以直接确定我们需要使用的协议。接下来是确定要抓取的数据并且制定抓取策略,这里也是整个工程的重中之重,能不能实现低调就看这个策略了。我们能做的,就是挑选出重点需要关注的商品,舍弃一部分并不重要的商品,甚至为了隐藏自己的商业数据,可以有意减去一些重点商品,避免因小失大。
|
||||
|
||||
然后,就是执行抓取了。这里需要注意的是,实时爬虫并不推荐,非做不可的话,一定要注意,把低调刻在自己的骨子里。尤其是数据集上面,一定要敢于舍去部分重点商品,壮士断腕,避免被对方反向分析,得不偿失。
|
||||
|
||||
最后,是数据的解析和验证。解析这里,我为你提供了两种解析方式以及它们的选择方法。记住,只要比对方消耗得少,你就胜利了。而验证的时候,我提到了可以通过有意被抓来验证数据,减小对方服务器的压力来保持低调。
|
||||
|
||||
要知道,低调不低调,不是给机器看的,是给对面的人看的。只要对面的人没发现你,那么你就低调成功了。
|
||||
|
||||
那么,足够低调的情况下,就能一直抓取了吗?答案是否定的,毕竟这是一个又卖矛又卖盾的课程。下节课,我们就从反爬虫的视角再看看,如何应对爬虫方低调的抓取。
|
||||
|
||||
思考题
|
||||
|
||||
最后,又到了愉快的思考题时间。还是老规矩,三选一,记得保密脱敏啊:
|
||||
|
||||
|
||||
假设你想实现低调的抓取,最多只能支持100QPS。但是要完成老板的需求,最少也要1000QPS。那么,如何解决这个问题?另外,在你眼里,100和1000的QPS,分别是一个什么样的量级?
|
||||
|
||||
假设在解析数据的时候,你发现每次解析都会引发一个埋点发送到服务端,证明自己解析成功了。那么,这个埋点你会模拟发送吗?是不发送显得低调,还是同步发送更低调?
|
||||
|
||||
如果有畸形的HTML标签要解析,不同浏览器解析方式不一样,你会在user-agent节点锁死浏览器版本吗?
|
||||
|
||||
|
||||
期待你在评论区的分享,我会及时回复。反爬无定式,我们一起探索。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
160
专栏/反爬虫兵法演绎20讲/05反爬虫的应对之策:通用且基本的检测规则是什么?.md
Normal file
160
专栏/反爬虫兵法演绎20讲/05反爬虫的应对之策:通用且基本的检测规则是什么?.md
Normal file
@ -0,0 +1,160 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
05 反爬虫的应对之策:通用且基本的检测规则是什么?
|
||||
你好,我是DS Hunter。
|
||||
|
||||
上节课,我通过爬虫方的一整个抓取流程,给你讲了爬虫是如何低调地爬取站点,闷声发大财的。那么今天,我们就要看看反爬虫方要如何应对爬虫的抓取了。
|
||||
|
||||
我们都知道,当爬虫诞生的时候,反爬虫的需求就诞生了,而反爬虫这个职业,也就水到渠成,自然而然地出现了。那么我们要想进行反爬虫,要做的第一件事是什么呢?
|
||||
|
||||
没错,就是识别爬虫。爬虫如果无法被识别出来,那么剩下的所有架构设计以及扩展性都是在瞎扯。爬虫识别,可以说是整个反爬虫的核心。
|
||||
|
||||
这节课是反爬虫的第一课,因此我们只会聚焦一个问题:反爬虫通用且基本的检测规则,是什么?
|
||||
|
||||
通用检测规则
|
||||
|
||||
考虑到是通用且基础,我们先排除一些定制化的拦截检测,总结出如下几种检测方式:
|
||||
|
||||
|
||||
TCP/IP级别检测;
|
||||
HTTP级别检测;
|
||||
浏览器特征级别检测;
|
||||
业务相关特性检测。
|
||||
|
||||
|
||||
这四条规则逐级递进,越往后,拦截越贴近应用,拦截效果越好;越靠前,对性能的影响越小,也就是性能越好。而较为特殊的拦截方式,我在第9和10讲也会给你提到一些。接下来,咱们就从TCP/IP级别检测开始了解吧。
|
||||
|
||||
TCP/IP级别检测
|
||||
|
||||
TCP/IP级别的检测,其实主要是IP级别的检测,也就是俗称的“封IP”。它可以说是反爬虫的基础操作,人人都能想得到。
|
||||
|
||||
当然,它理论上也包含TCP检测,但是这个大部分公司是碰不到的,除非一些公司的爬虫有协议级别的错误。此外,App爬虫大部分是直接走TCP协议,不过App爬虫我们在这门课程中是不讨论的。所以接下来,我们就看看IP级别的检测吧。
|
||||
|
||||
先说明一下,IP级别的封锁,由于IPv6还在完善的路上,任重道远。所以,当前的用户主要是以IPv4为主。
|
||||
|
||||
在一个完整的网络请求中,IP封锁可以选择在SLB(服务器负载均衡,Server Load Balancing)层操作,也可以选择在业务层操作,各有好处。
|
||||
|
||||
|
||||
|
||||
在 SLB层操作,优点是非常彻底、高效。我们都知道,拦截越靠近业务层,拦截时机就越晚。而这个时候,服务器的压力已经产生了,性能会受到影响。那么,整体的拦截效果就会不明显。另一方面,SLB层距离业务层有足够的距离,出于这种考虑,很多公司会在SLB做一层拦截。 但是这一层的拦截也有坏处,那就是SLB功能有限,不能定制化得特别复杂,只能进行简单的规则定制。
|
||||
|
||||
而业务层则截然不同。业务层的拦截,通常定制化极强。因为业务层本身使用了复杂的编程语言来实现,可以实现任意逻辑,而不再是像SLB一样只能进行规则的配置。
|
||||
|
||||
最后我再给你说说关于两个层封锁的区别和选择。
|
||||
|
||||
举个例子:你要针对指定IP段进行封锁,但是出于业务需要,必须放掉一小部分(放掉一小部分的原因,我会在春节的时候给你展开讲讲)。这个在业务层,你只需要走一层黑名单,然后再走一层白名单进行召回就行了。但是,如果是在SLB层,它没有这么强的逻辑,可能就必须定制脚本了,难度直接飙升。这还只是一个简单需求,需求再复杂一点的话,SLB可能根本无法完成。
|
||||
|
||||
那你可能就会问了:我到底应该选哪一个,才比较合适呢?嗯,实际上我们常说一句话:小孩子才做选择,成年人是全要的。是的,我这里的建议是一个都不能少,两个方法都用上,相互配合封杀即可。虽然可能会存在跨团队的情况,引发一些沟通成本,不过这是值得的。
|
||||
|
||||
了解了SLB层和业务层检测的不同之后,我就可以和你聊一聊怎么进行检测了。你可能认为,IP封锁是一个很没技术含量的行为。这个想法其实并不正确。
|
||||
|
||||
IP封锁一般来源于这样一个状况:你在网上搜索如何反爬虫,可以搜到的资料非常少,能搜到的基本也都是在教你怎么对IP频次进行检测并封锁。所以给人一种感觉:这个方法好low啊。但是,事实上这种办法只能叫基础,并不能叫做low。基础和low,在软件行业一直是两个不同的概念,不能划等号。
|
||||
|
||||
虽然说网上的办法,通常是对IP的频次进行检测然后封锁。可实际上,我们还能玩出更多的花样。
|
||||
|
||||
第一个是端口检测。我们都知道,网络上很多爬虫是通过代理爬取的。那么大部分的代理服务器为了让爬虫能连上去,都会开放一些端口给爬虫使用。一些低质的代理,通常开放的都是常用端口,比如80或者8080。普通用户开放这类端口的概率极低,因此可以极大地增加嫌疑性。在03讲一个演讲示范的故事中我们也提到过,没事扫扫端口,没准还有意外收获。
|
||||
|
||||
第二个是运营商检测,或者说IP段检测更好一些。我们都知道,有些爬虫会在公有云自己架设代理服务器,甚至有的节点干脆直接从公有云出来。对于这种请求我们没什么可客气的,整段都可以不留。
|
||||
|
||||
当然,这个方法的关键就在于检测IP段是否属于公有云。WHOIS提供了足够多的信息,可喜的是,它还顺便把整个段都给了你。你可以选择用range直接封锁,也可以选择用前缀树来操作。两者相比,前缀树的可读性好一些,但是显得没有range专业,速度也比range慢一些,不过差别并不大。
|
||||
|
||||
之前我的实践中,SLB层的封锁是使用range来做的,也就是子网,而业务方运营使用的是IP前缀树。因为SLB的操作人员通常是研发,所以面对子网没有任何障碍。而业务运营对range,或者说子网,有一定的理解障碍。当然,这个要具体问题具体分析,效果是一样的。
|
||||
|
||||
第三个就是SEO的洗白了。反爬不是一个莽夫行为,一定不要神挡杀神,毕竟我们有一个善意的爬虫叫搜索引擎。我们还要给他们洗白,避免产生被拦截的情况。不过,搜索引擎这个东西呢,有的时候也会抽风,一旦抽风起来和一个DDoS也没什么区别……所以洗白归洗白,我们也不能不管,这个度还是要把握一下的。
|
||||
|
||||
一个常见的做法是指定一个独立集群,如果rDNS之后认定为搜索引擎域名的,可以导到独立集群。这个集群可以不设置反爬,但是要设置资源上限,避免影响主业务。rDNS相对比较靠谱,不用太担心冒充。
|
||||
|
||||
以上就是TCP/IP级别的几个检测,我给你介绍了在SLB层和业务层的检测方式以及各自的优缺点,这里,建议你搭配使用。同时,除了网上经常推荐的简单封IP操作,你也可以了解下那三个额外的补充操作,来帮助自己更有效更安全地对爬虫进行封杀。
|
||||
|
||||
下面,我们就看看更靠近应用层的HTTP检测。
|
||||
|
||||
HTTP级别检测
|
||||
|
||||
HTTP级别的检测主要集中在HTTP的header。我们知道,爬虫和普通用户唯一的不同之处就是,它的伪装一定有瑕疵。HTTP的header就是一个重灾区。
|
||||
|
||||
每一次浏览器的升级,都是爬虫的噩梦。因为浏览器升级经常会带来一些小的错误,尤其是HTTP的header,甚至有的可能是拼写错误。举个最简单的例子,Chrome的Accept-Encoding,有个无用的属性叫SDCH。这个属性是干嘛的,以及为什么说它无用,这里就不展开了,毕竟与反爬的关系不大。我们关键是通过SDCH来看,它为爬虫以及反爬虫带来了什么影响。
|
||||
|
||||
你可以在线上拉下所有Chrome用户的日志看一下,哪些用户的Accept-Encoding带SDCH,哪些不带,以及哪些版本的SDCH拼写和别的版本不一样?带不带空格?都看完了,你就会发现,原来浏览器本身的问题也很多,像拼写、空格等等细节都有可能不同。
|
||||
|
||||
但是,这对反爬的人其实是好事,问题越多,爬虫学起来越累——浏览器本身就问题一大堆,还要Cosplay得一模一样,真是太痛苦了。
|
||||
|
||||
当然了,刚刚说的SDCH只是一个简单的例子,实际上所有HTTP的header都会多多少少有点问题,这些隐蔽的点都可以作为检测点。浏览器问题越多,模仿越有可能露出破绽。而数据,无需手动收集,只要跑下线上用户日志即可。
|
||||
|
||||
不过,在跑线上用户日志的时候要注意,不要跑爬虫重灾区的服务地址的数据,这样很可能把爬虫的错误当样本学习了。我们要尽可能用一些毫无意义的服务来提取样本。举个例子,价格页面,90%的流量都可能是爬虫,这种流量有什么好学习的呢?这不是越学越坏么?但是支付页面则不同,进去就付钱,正常哪个爬虫闲着没事来给你付钱?这个页面就是一个很好的样本点。
|
||||
|
||||
甚至,header会有一些组合规律。这个可以直接用机器搞定,不用费心费力上人工。
|
||||
|
||||
除了header之外,有一些简单的HTTP格式也可以做一些检测。尤其是有一些低级的爬虫,经常犯一些HTTP请求格式写错的错误。这种你可以直接拦截掉,无需担心太多。当然,如果你发现一些畸形的HTTP请求触发了你服务器的Bug,就要格外小心了。这可能不是低级爬虫,反倒是顶级爬虫,它在利用SLB的Bug来试图绕过反爬系统。
|
||||
|
||||
最后给你补充一个需要额外注意的地方:各种header检测的正则表达式一定要考虑扩展性。举个例子,近期Chrome版本号即将突破100,很多老的反爬系统都被迫需要被修改,就是因为当时的扩展性没有留好。
|
||||
|
||||
浏览器特征级别检测
|
||||
|
||||
浏览器特征级别检测主要集中在DOM。
|
||||
|
||||
我们先来看看大多数人的想法。很多人在反爬的时候,都期待有个唯一的key能让自己标记用户,于是就把希望放在了Canvas指纹上。不过,实际上Canvas指纹的冲突率还是挺高的,有的时候也会达不到我们期待的效果。
|
||||
|
||||
实际上,能够达到我们期待效果的key是存在的,你可以叫它DOM指纹。
|
||||
|
||||
单看反爬虫功能的话,我们不一定非要每个用户都有一个唯一的key,这样做的话识别量反而更大了。如果所有的爬虫有一个key,普通用户有另一个key,那不是封杀起来更开心吗?我们只需要识别一次就好了。
|
||||
|
||||
至于具体的操作过程,其实就是从Window开始往下拉一棵树,循环引用跳掉,最终得到的DOM结构,就是一个指纹,这个指纹与浏览器相关。实际使用的时候,你可以使用部分DOM,不要用全量DOM,这样抓起来更灵活,底牌也可以一张一张慢慢打。
|
||||
|
||||
此外,浏览器特征检测也可以利用一些浏览器 Bug,但这种方式也有缺点,毕竟爬虫模拟得可能不够完善。那这种情况下,爬虫花费多大体力,你就对应要花费多少体力,未必是一个划算的买卖。
|
||||
|
||||
所以,在使用这个方法之前,我们就要仔细权衡了。毕竟,要进行浏览器特征的收集,这也是一个很大的体力活啊。爬虫那么多,我和它们一个个卷,我并不赚啊,怎么办?
|
||||
|
||||
别急,你要明白一件事情,你的目标从来都不是“弄清楚浏览器有哪些特征”,而是“发现哪些请求的浏览器特征与其他人不一样”。这个需求明确之后,你就会发现问题变得简单了很多。
|
||||
|
||||
想求两个数据集的diff,这对于一个高级程序员来说,根本不是事。当数据量变大之后,无非就是如何优化降低复杂度、提升可靠性而已,最终将变成一个成本问题。所以,当一件事情从技术问题变成ROI问题之后,反倒简单了很多,你要做的只是打平收益和支出即可。
|
||||
|
||||
说到打平收益和支出,你可能要问了:那,我可以上机器学习吗?这样不就降低了人力成本,减少消耗,也就是减少支出了吗?
|
||||
|
||||
当然可以,没有任何问题,机器学习特别适合这种从混乱之中寻找规律的情况。但是,你一定要注意的是:机器学习本身解释性极差,如果发生了误伤,你很难给老板解释这一切为什么会发生,更不用说给客户解释了。
|
||||
|
||||
所以机器学习是可以上的,但是更多的是作为验证手段,或者让它替你发现一些特征。至于这些特征如何使用,一定要保证是人工控制,不能让机器替自己做决定。
|
||||
|
||||
业务相关特性检测
|
||||
|
||||
我在04讲说过:反爬绝对不要做成中台。主要原因,就在这个检测上。
|
||||
|
||||
事实上,在数据下毒的过程中,使用的很多特性都是业务特性,中台方根本不知道如何给对手下毒。这么说吧,如果一个用户通常不会按照某个组合条件来查询你的商品,那么,你就可以在对应条件上对用户进行大幅降分,降低对用户的信任度。最后,如果用户再在某些条件上出现反常,就可以直接封杀了。
|
||||
|
||||
除了检测外,数据处理上也是业务方更了解如何处理。我之前就给你讲过“某公司爬取小说”的故事。他们一直都以为自己爬得很好,直到后来接到用户反馈,说章节错乱,小说都大结局了,你们这咋还差几章呢?检查了下发现对方一直给自己的是旧的章节。这类下毒方式,就属于反爬虫方的业务特征下毒,而中台方因为并不了解具体业务,所以是很难想到的。
|
||||
|
||||
所以,在做这个检测的时候,你可以首先问自己一个问题:我们行业有什么奇葩之处?有没有什么我们看起来简简单单,但是外行看起来不可思议的业务特性?如果有,那这就是一个很好的监测点。
|
||||
|
||||
小结
|
||||
|
||||
今天我们一共介绍了四种不同的通用规则检测方式,分别是TCP/IP级别检测、HTTP级别检测、浏览器特征级别检测以及业务相关特性检测。你也可以通过下面的图片回顾一下这些检测方式的具体使用方法:
|
||||
|
||||
|
||||
|
||||
这四种检测方式的具体的内容并不难理解,但是我们可以发现它们有一个共同的特点,那就是,我们关心的往往不是用户到底是什么样子,而是用户与爬虫的差异点在哪里。只有找到差异点,才能更好地区分、检测,最后进行拦截。
|
||||
|
||||
至于这个差异是如何产生的,我们未必要穷追到底,只需能够利用即可。这些基础的封锁都做掉之后,爬虫再也不能低调的偷偷爬数据了,不得不和你正面开打。
|
||||
|
||||
目前为止,爬虫和反爬的斗智斗勇,还只能认为是打架斗殴。一旦规模上来了,我们才能称之为战争。
|
||||
|
||||
下一讲,我们将看到,分布式的爬虫是怎么和反爬虫方开战的。这样,爬虫和反爬虫的战争,就正式打响了。
|
||||
|
||||
思考题
|
||||
|
||||
好了,又到了愉快的思考题时间,还是三选一的老规矩,记得保密脱敏哦:
|
||||
|
||||
|
||||
我们知道任何线上操作,风险都与收益并存。你认为封IP这种最基础的操作,风险和收益分别是大还是小?具体风险和收益分别是什么?
|
||||
我们可以通过浏览器特征检测爬虫,那么如果爬虫固定一个版本的浏览器,我们其余的检测岂不是徒劳的?如何解决这个问题呢?
|
||||
检测的东西如何对爬虫方保密呢?毕竟他们一旦看到了,就知道如何绕过。
|
||||
|
||||
|
||||
期待你在评论区的分享,我会及时回复你。反爬无定式,我们一起探索。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
187
专栏/反爬虫兵法演绎20讲/06爬虫攻势升级:分布式的意义在哪里?.md
Normal file
187
专栏/反爬虫兵法演绎20讲/06爬虫攻势升级:分布式的意义在哪里?.md
Normal file
@ -0,0 +1,187 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
06 爬虫攻势升级:分布式的意义在哪里?
|
||||
你好,我是DS hunter。
|
||||
|
||||
上一讲,我们讲到了反爬虫做为一个合格的保安,会尽力对爬虫进行拦截。当然,不遗余力地拦截,从某种意义上来说也不一定是最优解。
|
||||
|
||||
关于最优解问题我们会在后续探讨。今天我们主要看一下:当保安尽力拦截爬虫的时候,爬虫方是怎么处理的?
|
||||
|
||||
这里,我就先从基础的爬虫思路给你引入。
|
||||
|
||||
爬虫基础思路
|
||||
|
||||
一些做过爬虫的人可能都知道,网上主要有两种爬虫思路。
|
||||
|
||||
第一种是,你要尽可能少爬一点,避免把服务器爬挂了。比如你的QPS(Queries-per-second,每秒查询率)本来是100,那么你尽量放到50。
|
||||
|
||||
而另一种流派则认为,反爬虫会根据单个IP的访问请求来统计你的请求是否均匀。如果不均匀,例如只请求价格接口,那么他会直接封锁你的IP。为了避免这一情况,你应该多请求一些与你无关的接口。这样你的QPS如果本来是100,那么实际上会扩大到500甚至更多。
|
||||
|
||||
这里可以注意这样一点,如果你的QPS本来是100,那么根据方案一, 你应该缩小到50。根据方案二,你应该扩大到500。可是,两者相差了十倍之多,到底哪个是正确的呢?
|
||||
|
||||
这里就要引入一个几乎所有的爬虫教程都会提到的词:分布式。似乎不做分布式,爬虫就不能称为爬虫了。那么,我们为什么一定需要分布式呢?还是说,仅仅是别人这么说了,我们就忍不住照做,慢慢成为了一种习惯?
|
||||
|
||||
为了避免无理由的直觉,我们先看一下,分布式是什么,以及它给我们带来了什么样的效果。了解了这两点,我们要选择哪种爬虫思路的问题,也就迎刃而解了。
|
||||
|
||||
爬虫思路中的分布式概述
|
||||
|
||||
分布式,顾名思义,就是使用多台机器一起工作。不管分布式的定义多么复杂,实际上它只是一个简单的分散作业而已。当一个技术很简单的时候,我们不要刻意去把它弄复杂,这样对解决问题是没有帮助的。接下来我们就看看在爬虫抓取思路的各个部分,是怎么做到分布式的,以及各个部分的分布式,又有什么样的作用。
|
||||
|
||||
技术分布1:IP的分布式
|
||||
|
||||
单IP可能被封,这个是很多人上分布式的核心理由,也是关键理由。我们在05讲中也提到过,封锁IP是反爬虫的基础技能,而分散式的IP自然就成为了爬虫的核心技能。获取多个IP地址的方法非常多,但是总的来分类无非就两种,一种是付费购买,一种是免费自建。
|
||||
|
||||
我们先看付费购买。事实上,不同费用下的IP质量差距很大。低价的IP有很多缺点,例如多人公用,可能这个IP早就在各大站点被拉黑了,但是你依然要为它付费——即使并不是很贵。但是高价的IP也不见得就好到哪里去,甚至有的没有隐藏端口,对方扫描一下就知道是个代理。这种情况下,我们就要货比三家了,不能一概而论。
|
||||
|
||||
接下来我们来看免费自建。免费自建看起来IP免费了,但是设备的费用可能让你有更多的支出。我们假设,你使用的是ADSL(Asymmetric Digital Subscriber Line,非对称数字用户线路)。那么设备分布在各个地方,除了设备本身的费用,还要考虑设备万一出了问题,需要去维修的费用。你看,正好印证了一句话:免费的就是最贵的。不过,也就是因为这么多的成本输出,才让它的稳定性更好。
|
||||
|
||||
此外还有一种是云主机。目前各大厂商都有自己的云主机服务了,IP也足够分散。但遗憾的是,这些IP基本上都上了各个大厂的黑名单,而且是整段拉黑。因此云主机是可以使用的,没有问题,但是还是要配合代理使用,才能实现IP的分布。
|
||||
|
||||
技术分布2:爬虫节点的分布式
|
||||
|
||||
爬虫节点的分布式能有效提升系统稳定性。而完成爬虫节点分布式的手段,就是单节点拆成多节点。
|
||||
|
||||
爬虫系统对于稳定性的要求肯定没有线上系统的要求那么高,但它有个特殊的地方,那就是对时间上稳定性的要求远远大于取数率上的要求。
|
||||
|
||||
这里我给你补充一下取数率的概念。假设,你需要1000个数据,实际上拿到了900个,那么取数率就是90%。不过业务方也没指望过拿到100%的数据,所以这个低一点没关系,不要太过分就行。你还记不记得我们在04中提到过,爬虫不要爬100%的数据?也就是说,我们在选定爬取数据范围的时候已经舍弃了很多了,这里再少一点,也不是什么大事。
|
||||
|
||||
而我说的时间上的稳定性,就是业务期望每天都能拿到数据的意思。假设十天里面有一天是拿不到数据的,这样虽然稳定性的数值也是90%,却是业务方无法忍受的。
|
||||
|
||||
也就是出于对时间稳定性的要求,我们才要进行单节点拆多节点。因为多台机器挂一部分,影响的是取数率。而单台机器挂一定的时间,影响的是时间稳定性。我们刚刚说过了,取数率的重要性低于时间稳定性,因此拆多台是划算的。再配合前面说的代理,取数率的稳定性也提升了。这样,时间稳定性和取数率,都有了一定的保障。
|
||||
|
||||
以上两个方法谈完之后,你应该会发现:分布式,无非就是两点,一个是最前端的代理层,也就是IP地址要分布,避免被单点封杀;一个就是应用层,也就是爬虫机要分布,避免在物理上集中出现问题。那么,还有别的要分布的吗?
|
||||
|
||||
这个就取决于我们对分布的定义了。如果“多样性”也算是技术上的一种分布的话,那么,我们还有两个地方可以分布,一个是数据库,一个是爬虫策略。
|
||||
|
||||
补充1:数据库的分布式
|
||||
|
||||
我们先来看看数据库的分布式。这里,我会给你创设一个反爬虫方反击的情境,你可以先看一下:
|
||||
|
||||
|
||||
数据库是反爬系统反向攻击的大头。其中,SQL注入则是重灾区。-
|
||||
-
|
||||
做这一行的都知道,普通用户在浏览器上做的请求,是当场消费掉的,不存在存储问题。那么如果在响应中存在SQL注入,目标就十分明确了:只要成功,一定是爬虫机。只要失败,一定是普通用户。100%无误伤,这对于反爬虫来说简直是橙色级别的武器。-
|
||||
-
|
||||
因此你会发现一个很可笑的事情:一个做爬虫的人,居然还要防止SQL注入,这太可怕了。-
|
||||
-
|
||||
尤其是对方可能趁你不注意忽然改版,即使你调试的时候没有SQL注入的响应过来,等你上线之后,响应随时可能改变。-
|
||||
-
|
||||
这时候,你做为一个爬虫工程师,居然要请求公司的安全部门帮忙给爬虫程序做SQL注入。更可怕的是,安全部门还不一定有工具可以使用:这个世界哪有人写爬虫的SQL注入工具呢?-
|
||||
-
|
||||
而且这种事情,即使被坑了,你还不方便起诉:“法官大人,我被SQL注入了,对对对,因为我爬别人,然后拿到的数据有问题……嗯什么我为啥要爬别人? 嗯嗯这个……”-
|
||||
那面对刚刚说的这个情境,你是很难走法律流程解决的,只能吃个哑巴亏。
|
||||
|
||||
|
||||
既然如此,那么一个比较折中的方案就是,数据库分开。如果跪了,那就跪一个,别全跪。那,具体要怎么做呢?
|
||||
|
||||
首先,我相信你是不会用公司的数据库服务器直接部署代码的……因此一定是外部的机器。这时候想必你一定会忽然恍然大悟:我懂了,要用分布式数据库。这个想法怎么说呢,也不是错的,其实不考虑成本,分布式数据库也许是最优解,注意我这里在强调成本。
|
||||
|
||||
后续的课程里,你会不断地碰到“成本”这个词,这是反爬虫的核心之一。我们要不断地把反爬虫问题转换成ROI问题。同样,对于爬虫来说,成本也是核心考虑因素之一。如果数据库的分布式成本太高, 有没有曲线救国的办法呢?
|
||||
|
||||
答案当然是有的,那就是数据库独立,把应用做成分布式,然后各自独立部署数据库。但是这里,我们又要如何把数据集中起来呢?
|
||||
|
||||
别急,我给你补充两种方式:一种是节点推送,一种是从中心去抓。两者各有利弊,建议使用第二个方案。
|
||||
|
||||
这里有两个理由:
|
||||
|
||||
第一,节点推送的话不可靠。有些情况下,中心节点性能顶不住了,这时候谁也不知道知道哪个节点可能忽然抽风了推一堆数据,一不小心就能把自己打挂。
|
||||
|
||||
第二:如果是推送,那么你要再写一个推送代码。但是如果是抓……额, 你本身就是爬虫工程师……把爬虫代码再部署一次就可以了。你看,是不是很省事?
|
||||
|
||||
补充2:爬虫策略的分布式
|
||||
|
||||
这里,我们就要从整体的战略部署上聊聊了。有人可能会说:爬虫策略哪有什么分布式可言,无非就是多样性而已。是的,这里主要讲的是多样性,但是用分布式这个词绝对不是偷换概念。你要考虑的是,你的多个节点,是统一行动的吗?我们假设你所有的节点都是统一行动的,爬取策略完全一致,那么,这样会导致两个缺陷:
|
||||
|
||||
|
||||
鸡蛋放在一个篮子里,要打碎就全碎,一个不剩,风险极高;
|
||||
策略没有梯度,无法互相验证,也无法提供送死的炮灰。
|
||||
|
||||
|
||||
我们一个一个来看。
|
||||
|
||||
第一个,鸡蛋放在一个篮子里。这个很好理解,你的所有节点策略都完全相同,那么如果对方反爬虫工程师发现了你,他不管什么时候,只要成功封锁你一次,就会在时间上影响你的爬取率。
|
||||
|
||||
刚刚我们提到过了,取数率低并不是大事,但是时间上如果受到影响,对业务影响无疑是巨大的。因此,绝对不能容忍这种事情的发生。
|
||||
|
||||
第二个,策略没有梯度,无法互相验证,也无法提供送死的炮灰。这里的互相验证,主要体现在,你如何知道自己被反爬发现了并已经被干掉了?一个很好的办法就是多个节点使用不同策略来进行抓取,一旦一个策略被发现并封锁了,那么其余的策略可以提供验算功能。
|
||||
|
||||
当然,如果你使用多个策略频繁抓取同一个接口,会对对方集群造成大量的负担,这是不合适的。所以你可以适当交叉,并非每个策略交叉都完全覆盖,这样实际增加的请求量并不会翻倍。
|
||||
|
||||
此外,“送死的炮灰”是什么意思呢?
|
||||
|
||||
对于一些小的爬虫团队来说,这是没有意义的,但是对于大型爬虫团队来说,这是必须的。
|
||||
|
||||
要知道,大型爬虫团队通常会面对大型反爬虫团队,而他们如果找不到爬虫,就会拼命检测每一个角落,直到找到蛛丝马迹把你干掉为止。这个时候,你可以考虑不断迭代自己的爬取策略,然后定制一个梯度,针对旧版本的策略,可以有意制造一些错误,让对方干掉自己。
|
||||
|
||||
这样,反爬团队的KPI得以完成,他们也许会去开个香槟庆祝一下,那你就可以让低调的爬虫默默地去取数据了。
|
||||
|
||||
记住,不要把敌人逼到绝境,要让他们过得开心。这样,他们才不会和你拼命。
|
||||
|
||||
数据汇总模块的分布式?
|
||||
|
||||
说完了爬取过程中所有的分布式场景后,你会发现:做爬虫,几乎所有的代码都要分布式,任何一个地方都不能集中。目前,只有一个地方还在集中,那就是爬取后的处理,也就是数据汇总模块。那么,这个模块还要不要分布式呢?
|
||||
|
||||
事实上这取决于你的业务规模。
|
||||
|
||||
举个例子,假设你的爬虫团队不是一个业务团队,而是一个爬虫中台,那么你的数据其实并没有太大的必要集中到一起。集中了反而提升了复杂度,降低了稳定性,还降低了效率。
|
||||
|
||||
如果业务需要访问数据,你完全可以提供一个数据访问层,使用的时候再去访问各个节点的数据,而不是汇总在一起随时查取。这样不但提升了稳定性,还降低了法务风险:毕竟数据没有集中存储,回头谁知道那些爬虫节点归谁呢?
|
||||
|
||||
而不同业务方虽然共用数据访问层,但是每个人都可以有一个自己的访问节点,这个节点做成分布式,可以有效避免业务间争抢资源,导致某个业务拉取数据的时候所有业务效率都变慢。
|
||||
|
||||
不过,如果你的业务没有这个规模,只有一个业务需要爬虫,那么就完全没有做成分布式的必要了,这样只会凭空增加复杂度。
|
||||
|
||||
重新定义爬虫基础思路
|
||||
|
||||
最后,让我们回到开头的问题:关于QPS,我们应该增加,还是减少呢?
|
||||
|
||||
原则上,我们当然是要减少QPS,避免对对方机器造成负担。但是实际上因为分布式的问题,加上可能有交叉验证,100的QPS实际上增加到120是一个不错的平衡点。再增加就是损人不利己的行为了,无疑是坑害双方,是一个严重的不智之举。
|
||||
|
||||
此外,如果你评估对方机器承受自己的上限是100,那么对业务评估就要按照80来评估,避免对方性能下降。
|
||||
|
||||
最后,因为分布式可以随意调度,当检测到对方机器响应下降的时候,一定要尽量减少节点,避免导致对方崩溃。目标集群就像洗衣机里的卫生纸一样,你把他卷死,自己的衣服也白洗了——多累啊,是不是?
|
||||
|
||||
所以,我们的QPS可以控制在一定的范围内上下浮动。
|
||||
|
||||
向下,只要调整单个节点爬取阈值,或者停掉部分节点,就可以实现;而向上,就要加大单节点的爬取上限,如果扩展性好,也可以增加节点。
|
||||
|
||||
至于什么时候向上,什么时候向下,就要取决于对方服务器压力,以及业务需求等等各方面的因素,并尽可能保守,能向下就向下,避免上得去下不来。
|
||||
|
||||
这个答案,就是分布式告诉我们的,也是分布式帮我们实现的。
|
||||
|
||||
小结
|
||||
|
||||
今天,我们从爬虫的基础思路入手,讨论了所有的分布式。其中包括两大类,第一类,也就是技术类的分布式,类似IP的分布式以及爬虫节点的分布式。第二类,是我们基于多样性的考虑进行的分布式补充,包括数据库的分布式以及爬虫策略的分布式。
|
||||
|
||||
除此之外,我们还讨论了爬取后的数据汇总环节采取分布式的必要性。总结起来就是,根据自身的业务规模,有多大本事,就揽多大的活。
|
||||
|
||||
|
||||
|
||||
最后,我们也重新定义了爬虫抓取数据的基础思路:不一味地多爬或少爬,控制在一定范围内浮动,才是最优解。
|
||||
|
||||
我们可以看到,在分布式这个大杀器下,爬虫能够很好地隐藏自己,并默默地执行自己的任务,就像无孔不入的间谍一样,即使被抓一部分,也不影响自己完成大部分任务。看起来,反爬虫系统似乎一筹莫展,无法应敌了。
|
||||
|
||||
事实上真的是这样的吗?别急,又到了反击的时间了。
|
||||
|
||||
下一讲,我们就说说,反爬虫是如何应对这种看似无解的局面的。
|
||||
|
||||
思考题
|
||||
|
||||
好了,又到了愉快的思考题时间,还是三选一的老规矩,记得保密脱敏哦:
|
||||
|
||||
|
||||
分布式是必须的吗?有没有可能一些爬虫根本不需要分布式?
|
||||
ADSL重新拨号会更换IP,那么你知道这样做的缺点是什么吗?会导致什么后果?
|
||||
分布式会导致成本的上升,这部分预算你打算如何向老板解释呢?
|
||||
|
||||
|
||||
期待你在评论区的分享,我会及时回复你。反爬无定式,我们一起探索。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
171
专栏/反爬虫兵法演绎20讲/07反爬虫升级:如何判定你是个真人?.md
Normal file
171
专栏/反爬虫兵法演绎20讲/07反爬虫升级:如何判定你是个真人?.md
Normal file
@ -0,0 +1,171 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
07 反爬虫升级:如何判定你是个真人?
|
||||
你好,我是DS Hunter。
|
||||
|
||||
上一讲,我们提到了,爬虫使用分布式,可以最大程度地隐藏自己。那么最大程度是到什么程度呢,反爬虫方如何应对呢?
|
||||
|
||||
还是回到反爬虫的核心问题:识别爬虫。
|
||||
|
||||
真人检测的相关探讨
|
||||
|
||||
我最开始做反爬虫的时候,痛苦不堪,完全不知道如何识别爬虫。有一天,我和老婆聊天,提到了这个事情。我说我们技术领域有个新的方向,就是识别一个请求是不是真人。如果不是真人,那就要封杀,但是难点在于识别真假,根本找不到任何通用的规则来指导大家去操作。
|
||||
|
||||
我老婆很不屑地说了句:这有什么难的,这和我们会计识别假钱不是一样的?每一个会计都会有一些自己的理论,但是如果说通用的规则,我们只有一个,那就是:假钱一定和真钱不一样。
|
||||
|
||||
真的是听妻一席话如听一席话啊。我当时觉得她在逗我,但是随着反爬虫做得越来越深入,我惊讶地发现,这句无心的话,居然真的点破了反爬虫的本质:这个世界上有各种爬虫,它们唯一的共同点就是,它们和真人不一样!
|
||||
|
||||
那么,我们可以进行真人检测吗?如果可以,进行真人检测的方法都有什么呢?它们各自的优劣是什么呢?别急,我们一个一个说。
|
||||
|
||||
真人检测是否可行
|
||||
|
||||
首先,我们可以直接下一个结论:真人检测,理论上不可行。
|
||||
|
||||
为什么这么说?
|
||||
|
||||
我们都知道,关于真人检测,有个专门的名词,叫图灵测试。在这个测试中,测试者是一个真人,而被测试者是一台机器。在两者隔开的情况下,测试者会通过一些装置向被测试者随意提问。一旦通过,被测试者就可以被判定为真人。
|
||||
|
||||
我们跳出一些阴谋论或者虚无主义的假设,直接认定:真实世界,现在没有机器人能通过图灵测试,每个人都是真人。
|
||||
|
||||
那么,上面的说法,不是恰恰说明了没有人能把人类模拟得尽善尽美吗?为什么反倒说理论上不可行呢?从被检测者的角度来说,我们应该是能检测出谁是真人、谁是机器人的啊!
|
||||
|
||||
这个原因,就在检测者身上。我们的反爬系统首先是一个程序,是一个机器人。而反爬虫相当于用一个机器人来替你,去给别人做图灵测试。
|
||||
|
||||
还记得我刚刚说过么?图灵测试的测试者必须是真人。那么,要做这个图灵测试,首先你的机器人要通过图灵测试,也就是有了“真人的资格”,可以像真人一样思考,这个逻辑没有问题,对吧?
|
||||
|
||||
所以在你编写出能通过图灵测试的机器人之前,你是没办法让程序去替你识别真人的。也就是说,理论上,由于检测者这一方的问题,反爬虫的真人检测是不可行的。
|
||||
|
||||
你可能会问了,那就不编码,用真人来进行测试不可以吗?毕竟图灵测试就是这么干的啊。这里要注意的是,真人测试就只能一个一个地进行了,反而失去了反爬虫定义中对“批量”的强调。
|
||||
|
||||
没错,就是真人测试会导致无法批量检测,而机器检测又没有办法像真人一样在检测者的位置给出判断,无法检测真人。所以,真人检测,理论上不可行。
|
||||
|
||||
但是,真人检测的理论不可行,实际上就不可行了吗?
|
||||
|
||||
不是的。这个世界有很多事情是理论不可行的,但这只意味着,完美解不存在。生活中很多方案都是用近似解来进行的。我们可以在一定程度上识别出机器人,这也并不违反理论。
|
||||
|
||||
如果用数学来做比喻,那就是,你需要的解可能是圆周率,这个是无限不循环小数,是无法使用的。但是,你可以使用3.14进行一个近似替代,大部分情况下是可以满足你的要求的。我们的反爬虫系统,大部分情况下,也就是做到了用“3.14”的地步。
|
||||
|
||||
真人检测的方式方法
|
||||
|
||||
那么,接下来我们要讨论的所有方式方法,就是真人检测的“近似解”了。我们回到今天这一讲最开头的那句话:假币没有什么特征,它唯一的特征,就是与真币不一样。
|
||||
|
||||
这句话看起来像废话,但是实际上效果很好。为什么呢?我们把它变换一下,成为下面这句话:
|
||||
|
||||
“机器人没有什么特征,它唯一的特征,就是和人类不一样。”
|
||||
|
||||
下面的这些方式方法,其实就是利用了真人和机器人的不同进行检测,我们一个个来看。
|
||||
|
||||
各种游戏验证码
|
||||
|
||||
验证码本质上其实是一个游戏,可以认为是“你画我猜”。具体的判别方式简单粗暴:猜不出来?嗯,智力不行——肯定不是真人了,拦!
|
||||
|
||||
但是,智力这个事情,会随着时间的推移而逐步下降的。每个用户都有老去的一天,智力也会下降,最终,会被检测为“非人类”,影响使用网络。
|
||||
|
||||
举个例子,在图片中找出人行横道。现在你可以想一下:这个游戏是不是每个人都会做的?
|
||||
|
||||
不是的。
|
||||
|
||||
别惊讶,就拿我自己来举例子吧。我是在一个小镇出生的,第一次看到人行横道,是在大学读书的时候。在那之前,只在课本上见过。而没有读书的同学,以及家里的老人,就完全不知道人行横道是什么。哦对,人行横道,就是我们常说的斑马线。
|
||||
|
||||
|
||||
|
||||
你可以再思考一个问题:如果你给出的题目是找出所有的人行道,那么人行道是否包含人行横道?事实上,有的人就会理解为,走人的都能叫人行道。所以人行横道当然也可以选。这个问题你可以找人调研一下,会存在很多争议,这就导致很难用程序判定。
|
||||
|
||||
例如下面这张图,虽然也算人行道、虽然明显不是人行横道,但肯定会有人问:步行街?步行街也能算人行道吗?人行道不是马路边上的吗?
|
||||
|
||||
|
||||
|
||||
你看,这争议不就来了吗?
|
||||
|
||||
除此之外,就更不要说“找出所有的地瓜”这种有严重歧义的问题了。在东北的地瓜,和江苏的地瓜完全不是一个东西,这类差异会导致大量的识别错误。
|
||||
|
||||
变态验证码
|
||||
|
||||
之前在03讲,我已经介绍过了一些简单的“看图识字”验证码。那么这里,我就给你说说验证码的升级版本——变态验证码。你可以把它理解为各种游戏和简单验证码的综合、升级版本。不过,这里的“变态”,也是因为业务方需求的特殊性。
|
||||
|
||||
咱们之前提到过的沪牌拍卖网站,就很适合在这里给你详细介绍一下。它简直可以说是验证码的天花板,甚至,它不在乎误伤人类。
|
||||
|
||||
沪牌验证码是一个组合,它会让你完成五个验证码的识别,随便举几个例子:
|
||||
|
||||
|
||||
给你两组数字,要求你只输入白底黑字的数字;
|
||||
给你多组数字,要求输入绿色圆圈的那组,并且六个数字,只能输入中间四个;
|
||||
给你一个饼图,让你输入某商品数量;
|
||||
给你一组数字,输入不为“3”的所有数字;
|
||||
给你一堆汉字,找出其中的成语,然后输入每个字下面的数字!
|
||||
|
||||
|
||||
你可以先想想……你看懂这些问题了吗?是一次性看懂的吗?想退出去了吗?
|
||||
|
||||
所以说,这种变态验证码的代价也是很明显的,那就是很多人类都无法通过。但是这与它特殊的业务需求是强关联的。沪牌是一个刚需,并且本身就有一定的随机性,无法通过验证码,可以认为是随机的一部分。
|
||||
|
||||
说得更直白一点,它根本不怕劝退用户。而你的站点具备这样的强刚需吗?具备不惧怕任何劝退用户行为的心理预期吗?我相信大部分互联网公司是没有这个底气的。因此尽量不要作死。
|
||||
|
||||
滑块
|
||||
|
||||
滑块是我心目中最完美的人类检测解决方案了。因为它恰到好处地卡在了检测率与伤害性的平衡点上。
|
||||
|
||||
也就是说,论检测能力,他远高于普通验证码,因为他不再是检测单一的通过不通过,而是直接分析用户行为分数,打码平台基本上失去作用。论伤害性,他远低于变态验证码,只要向右滑动即可,人人都会,所以普通用户没有任何学习成本——老年人也不用在碰到“找出佩奇”这种题目的时候,到处去问谁是佩奇了。
|
||||
|
||||
滑块检测真人和机器的时候,恰恰就用到了前面说的: “假币和真币唯一的区别就是它们不一样”。因此,滑块并非根据某几个检测点来进行检测,而是一个全面的检测并给出概率,像是拖动的准确度、速度以及轨迹等等信息, 整个拖动过程会携带很强的个人特征,可以有效鉴别真人与机器。
|
||||
|
||||
滑块检测方式,在安全领域已经是成熟的技术了,甚至已经有了商业化的产品。在这里就不多赘述了,避免有广告嫌疑。
|
||||
|
||||
真人检测的效果对比
|
||||
|
||||
真人检测的效果对比分两部分,一部分是识别率,一部分是误伤率。
|
||||
|
||||
用一个简单的比喻来理解吧:在狼人杀中,识别率,就是你指出的好人有多大概率真的是好人,误伤率,就是你把多少好人当狼人给杀了。
|
||||
|
||||
我们可以汇总这样一个表格:
|
||||
|
||||
|
||||
|
||||
仔细看这个表格,你就能理解我一直推崇滑块这类方式的原因了。从识别率来看,滑块、复杂验证码,变态验证码和滑块的识别率都很高。但是,如果考虑到“友好度”这件事,当然首选是误伤率低的,也就是在简单验证码与滑块之间做选择。滑块是最优选择,而简单验证码则可以用于拦截基础爬虫。
|
||||
|
||||
做出这个选择的原因就是,我们可以做安全,但是绝对不能因为做安全就完全不理用户的感受,这样饮鸩止渴的安全,是我们所不能接受的。
|
||||
|
||||
此外,反爬虫毕竟不是安全,这里讲到的所有办法,其实都是反爬虫和安全的交界地带。在大部分公司,这些都是安全来做的。反爬虫方应该想办法和安全来配合进行这些方面的操作,而尽量不要自己去动手。 不过考虑到一些公司可能没有安全部门,反爬虫工程师只能自己干,所以,了解相关知识,依然是必备技能,否则会导致难以配合。
|
||||
|
||||
小结
|
||||
|
||||
关于真人检测,我们大概就探讨到这个地步。
|
||||
|
||||
今天,我们首先打成了一个共识,那就是真人检测在理论上是不可行的。但是为了在一定程度上对爬虫造成阻力,我们决定放弃完美解,开始寻求近似解。
|
||||
|
||||
接着,我给你介绍了三种真人检测的方式方法,分别是各类游戏验证码、变态验证码以及滑块。当然,除了这些,还有我们之前在03中介绍过的简单“看图识字”验证码。其实,你看到的那些稀奇古怪的验证码,都逃不过这些分类。几类验证码各有优劣,所以在最后,我也给它们做了一个对比。至于怎么选择,就看你的需求了。
|
||||
|
||||
那么今天关于真人检测的几种方式,我的建议是,如果非使用验证码,尽可能用简单易懂的,你只需要使用它拦截掉一些低级的爬虫就可以了。很多学生做毕设的时候都没有实力去弄打码平台,能弄OCR的人更是少之又少。至于高级爬虫,你弄得再变态,它也过得去,还会误伤用户,得不偿失。
|
||||
|
||||
我们可以和爬虫卷,但是不要卷错对象。卷死用户?用户是上帝,对上帝好一点。
|
||||
|
||||
不过,除了这三种检测方式,我们就没有别的方法了吗?只能依靠这些简单无脑的判断题了吗?
|
||||
|
||||
不是的。
|
||||
|
||||
在阿西莫夫所有和机器人有关的科幻小说里,经常使用一个理论,那就是:机器人和人一定有区别,普通人可能识别不出来,但是机器人专家因为经过严格的训练,能敏感的捕捉到一些细微的差别,认出机器人来——虽然每次可能检测点并不一样。
|
||||
|
||||
同样的道理,作为一个反爬虫专家,你要训练的也是这种敏感的鉴别力,而不是记忆一些通用的鉴别方法。
|
||||
|
||||
在下一讲,我会以加餐的形式,给你补充一个新的检测方式:用户习惯检测。这样的动态拦截,你也一定会需要的。
|
||||
|
||||
思考题
|
||||
|
||||
好了,又到了愉快的思考题时间。老规矩,三选一:
|
||||
|
||||
|
||||
反爬在做权衡利弊时,如果你的职位和用户体验有了冲突,你是选择保自己的位置伤害用户体验,还是选择保护用户体验?
|
||||
在你们的公司决策里,真人爬虫按照爬虫处理吗?你认为当前你们的判定方式存在什么问题?需要如何改进?
|
||||
如果你是个爬虫工程师,发现对方在想办法提升用户体验。那么,你认为,这一点可以被你所利用吗?如何利用呢?
|
||||
|
||||
|
||||
期待你在评论区的分享,我会及时回复你。反爬无定式,我们一起探索。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
136
专栏/反爬虫兵法演绎20讲/08博弈的均衡:如何对抗道德的沦丧和人性的扭曲?.md
Normal file
136
专栏/反爬虫兵法演绎20讲/08博弈的均衡:如何对抗道德的沦丧和人性的扭曲?.md
Normal file
@ -0,0 +1,136 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
08 博弈的均衡:如何对抗道德的沦丧和人性的扭曲?
|
||||
你好,我是DS Hunter。
|
||||
|
||||
前面我们讲了大量的擦边球,在04~07讲提到的反爬与爬虫的对抗中,你一定也体会到了,爬虫和反爬,的确是一个很腐蚀人心智的行当。但是,在这个行当里,无论是为了生存,还是为了赚钱,都一定要牢记:我们首先要做一个好人,然后才要考虑赚钱。因此,法律和道德是我们逃不开的两件事,我们不得不仔细学习一下。
|
||||
|
||||
法律是道德的最低标准。但是呢,法律又有一定的滞后性。这就导致了我们做的一些事情,合乎道德的,与合乎法律的,未必是一个标准。所以我们分开两部分来讨论。
|
||||
|
||||
另外,我要说明一下,这一讲并不是法律教条以及道德指导,更多的还是指出我们可能碰到的法律条款以及道德约束。法律是生死线,是无条件执行的。道德呢,则更倾向于一种人生观,用于指导我们成为更好的人,而不是指导我们获取更好的业绩。当然,你也一定要相信,更好的人,总有机会取得更好的业绩。
|
||||
|
||||
因此,希望学习完这一讲的你,在选择指导自己工作项目的动作方向的时候,依然是“follow your heart”,而不是单纯的“follow the rules”。
|
||||
|
||||
法律风险
|
||||
|
||||
爬虫在法律上的风险主要体现在:版权法,破坏计算机系统罪以及用户隐私三样。我会和你聊聊法律约束的关键点以及常见的争议点。不过,这只是为了帮助你走上正确的道路,可不要理解错了。最后,我也会根据自身的经验给你一些建议,看看作为反爬虫方或者爬虫方,你都能做些什么。
|
||||
|
||||
此外,需要注意的一点是,我毕竟不是专业的法律人士,这里讲述的,都是我们平时与法务合作得出的经验。如果要使用的时候,我的说法与你们法务的说法发生了冲突,请一定以法务的为准,不要以我的为准。毕竟法律是一门严肃的学科,在不同场景下可能有不同的解读。
|
||||
|
||||
版权法
|
||||
|
||||
极为常见的反制措施——版权法,其实是早年针对爬虫的最大杀器。但是针对价格爬虫,这个方法几乎无效,因为价格没有版权可言。版权法主要保护的是文字相关的信息,例如评论,你可以在网上找到点评相关的案子,这里我也主要用文字类的情境给你举例。
|
||||
|
||||
客观,是法律的一大要素。法律主要讲究证据,你必须有足够的证据,证明他抓了你的数据。而版权法还有个特别的地方,你还得证明他用你的信息牟利了,而不是自己在家里没事看着玩。举个例子,你现在在听我的反爬虫教程,这是我授权极客时间的内容。所以你在极客时间听到,是毫无问题的。不管你是单独购买,还是通过超级会员来看,都是合法使用的。但是,如果你过两天发现在另一个站点也可以看这门课程,那么在没有新的授权的情况下,他就侵犯了版权法。
|
||||
|
||||
时间角度上来看的话,爬虫一定是比人工快很多的。这里发散思考一下:文字类情境下触犯版权法,一定是通过爬虫来实现的吗?
|
||||
|
||||
间接获取数据,或者说非技术手段获取数据,可能比直接获取数据成本更低,比如众包。可能他是自己比较勤奋,一篇一篇地复制粘贴过去,或者他雇佣了一个实习生,用比较低的价格,人肉搬运过去的。我们有很多低成本的人工搬运办法。冷知识:很多爬虫的成本,甚至超过了人工。
|
||||
|
||||
专业角度来解释的话,这个操作明显是不属于爬虫的。但是,他违法吗?依然是违法的。因为版权法并不在乎你是用什么手段把东西拿走的。违法是违在了,拿走这个动作,而不是拿走的方式。
|
||||
|
||||
用了什么技术,并不是定罪的关键所在。使用爬虫,与不使用爬虫,只要最终拿走了别人有版权的信息,都是违法的。这就是这次发散思考想告诉你的一件事。有些人总会说:爬虫无罪。这么说也是没什么问题的。因为有罪的不是爬虫,而是侵权,是偷窃。
|
||||
|
||||
在我们能保证自己不去侵权、去偷窃的情况下,又怎么在竞对这么做的时候保护自己呢?毕竟,法律归法律,还是有很多人铤而走险的。因此我们也不能光喊着竞对违法,要想使用法律武器,首先要学会法律。既然知道了法律是一个讲证据的行业,那么你在平时就要留好证据。不然,回头上了法庭,都不知道有什么证据能证明对方。
|
||||
|
||||
这里你的疑问可能是:有什么办法证明他爬的是我的数据吗?毕竟文字类的东西我不可能获得用户授权书,万一他两边都写了相同的文字呢?嗯,但是你在给竞对数据的时候也可以做一些操作啊。
|
||||
|
||||
举个例子,假设有人抓去了这篇文章的这一段,我们有办法证明他侵犯的是我们的版权吗?抛开正规的版权申请这些高成本方式不谈,你有没有发现,关于版权法这一段,每一小段开头的第一个字凑在一起刚好是“极客时间专用?读起来并没有什么违和感,但是我不说,是不是你也不一定注意得到?所以,文字是最容易隐藏陷阱的,甚至比直接改一个价格更容易。
|
||||
|
||||
破坏计算机系统罪
|
||||
|
||||
破坏计算机系统罪的历史不算短,但是把爬虫认定为破坏计算机系统,就是近些年的事情了。
|
||||
|
||||
从本质上说,“破解反爬虫系统“被认定为“破坏计算机系统”,是没有什么悬念的。但是问题在于,爬虫对此是否知情。这里会存在多种争议。
|
||||
|
||||
比如说,你作为反爬虫方写了一段加密,给请求参数做校验,而对面压根没有读懂你的代码。但是凑着凑着,唉,神奇般的怎么就跑通了呢,然后就开始源源不断地拉取数据。
|
||||
|
||||
回头对峙起来,爬虫方说:我哪知道那是加密啊,我还以为那是什么我没见过的压缩方式呢,我实力一般水平有限,只能瞎蒙,我还以为终于猜对了呢,你这不是陷害我吗!再说,就你刚才描述的那种加密方式,这也叫加密啊,别给技术人员丢脸了。这个双方律师一定会有争议的。
|
||||
|
||||
另外一点就是:如果爬虫定义为破坏计算机系统罪,那么反爬虫方的法务优势也过大了一点。他完全可以先公开,然后让你爬着爬着,哪一天忽然来个加密,反手就起诉你破坏计算机系统。这岂不是成了一个口袋罪,与寻衅滋事站在了同一个位置上。
|
||||
|
||||
这里我要说的是,法律是用来保护自己的,而不是用来陷害别人的。所以也许哪一天会出个司法解释:慎用破坏计算机系统罪解释爬虫行为。这个行业过于魔幻,虽然我这是一个无责任的预言,但是还真不排除这种可能性。
|
||||
|
||||
那么面对上面说的两个争议点,爬虫和反爬双方能做些什么呢?
|
||||
|
||||
爬虫:时刻监测对方站点公开程度,避免忽然被陷害为破解计算机系统罪。此外,尽可能隐藏自己,不给对方留下任何证据。
|
||||
|
||||
反爬虫:精准调整反爬虫措施,避免给对方律师反驳的理由。此外,尽可能精准定位对方,并找出合法的证据,避免无证据可用,有法不能依。
|
||||
|
||||
用户隐私
|
||||
|
||||
用户隐私也是近期才立法的。如果说,破坏计算机系统罪还有一定的争议,那么用户隐私爬虫则完全不值得同情。
|
||||
|
||||
相信大部分的人都有过用户隐私被泄露的痛苦,动不动一个电话过来:
|
||||
|
||||
|
||||
“你好,请问需要提升下学历吗?哦你北大毕业啊,那没问题了。”
|
||||
“请问小额贷款需要吗?什么你很有钱?那……那你需要投资理财吗?”
|
||||
|
||||
|
||||
骚扰还是其次,更严重的还会引发人身危险。因此,国家对于用户隐私泄露制定了非常严格的法规。爬虫抓取别的数据,可能还有一定的争辩意义。如果抓取用户隐私,那么基本上是直接Game Over。
|
||||
|
||||
因此,当你的需求是抓取用户信息的时候,请不要和产品经理客气,直接拒绝即可。这值得你主动放弃岗位。
|
||||
|
||||
道德约束
|
||||
|
||||
道德约束相对法律风险就麻烦了很多。当然道德问题容易存在争议,为了避免被抬杠,我也不细致分析应该怎么做,每个人都可以有自己的选择。
|
||||
|
||||
如果真的从纯道德角度来说,这个世界甚至不应该有爬虫。即使是搜索引擎,最开始也是在道德的灰色地带起来的。而商场如战场,大部分的人在思考问题的时候,往往权重最低的因素就是道德因素了。当然我知道,肯定有一些人会指责这段描述:“我怎么就把它当权重最低的因素了?”不过我打赌,他们转头又会在商场赚得盆满钵满。
|
||||
|
||||
你看,我们要做道德的人,又不能沦落为圣母(这个词居然现在成了贬义词,真的有点痛心),的确是一个很难的事情。我们只能像踩着钢丝一样走下去。而且大部分情况下,我们能保证不违法就已经竭尽全力了,能否再保证道德,完全是看个人的选择了。这没什么可指责的。
|
||||
|
||||
爬虫:站点压力
|
||||
|
||||
对于爬虫方来说,最大的职业道德莫过于降低对方站点压力。
|
||||
|
||||
原因很简单,如果你能抓1000条数据,你的老板一定会给你定2000条数据的KPI,或者OKR。无论哪一种方式,你都不得不多抓一些数据,哪怕伤害自己也在所不惜。但是这违反了我们的“低调原则”。爬虫和反爬,应该走向一个双赢的结局,而不应该是双输。因为内卷不创造价值,本身已经很输了,再往输了走,就更加残酷了。
|
||||
|
||||
至于降低压力的办法也有很多,基本上你自己架构网站的时候有多少种办法降低压力,那你就有多少种办法降低对方压力。最简单的,架构有削峰填谷,那你抓取就要均匀,避免造成突发压力。此外,在讲低调的时候,不断地提到数据规划的重要性,也是为了这个目的:降低站点压力。
|
||||
|
||||
反爬:用户体验
|
||||
|
||||
反爬虫方千万不要以为道德与自己无关。实际上,反爬虫方对爬虫可以残忍, 但是一定要注意:对用户不能残忍。
|
||||
|
||||
反爬的办法有很多,你一定能找到很多高准确率但是也高误伤率的办法,但是使用这些办法也一定要慎重。要知道,爬虫杀了一波还会再来一波,但是用户对你们的信任,杀过一次,就很可能再也不会存在了。这也就是前一讲不断强调我喜欢滑块的原因:并不是滑块有多优秀,而是与它竞争的都太烂了。
|
||||
|
||||
综合:KPI
|
||||
|
||||
KPI,说是道德,但是也不道德。这就是道德的悖论。
|
||||
|
||||
总体来说,反爬虫方要给爬虫一口饭吃,在拦截它的同时,也放一部分进来。这样既能麻痹对方,又能让对方活下去,避免人家背水一战和你拼命。同时,爬虫方如果能低调地抓取到数据了,那么最好也额外撞一下反爬虫,有意让他抓一点,免得他年底评3.25。万一他被裁员了,换个人来防你,你确定不会拦得更凶吗?所以说,适当假装被抓,就可以皆大欢喜,老板开心,程序员也开心。
|
||||
|
||||
说这样不道德的原因是,这样做本质上就是达成一致、心照不宣一起骗老板。虽然老板的需求本身就不道德,有点以毒攻毒的感觉了。但是并不能因为接了不好的任务,就用不好的方式来欺骗他。这样说其实也有点过于圣母的倾向了,但是如果站纯中立角度来考虑问题,也只能这么看。
|
||||
|
||||
小结
|
||||
|
||||
又到了结束时间,这里我们总结下,爬虫的主要法务风险在于版权法、破坏计算机系统罪以及用户隐私。三者是递进关系,越往后越严重。法务风险是生死线,是绝对没有商量的余地的。
|
||||
|
||||
而道德层次,则稍稍宽松一些,或者说仁者见仁智者见智一些。爬虫方主要在于不要给对方太大的压力,这个压力就是指服务器压力。反爬方也不要给对方太大压力,指的主要是考评。综合下来,双方都要为对方KPI着想,虽然是对手,毕竟是同行。
|
||||
|
||||
|
||||
|
||||
那么,截止到目前,博弈的基本方式以及如何在博弈中找到平衡点,都已经很清晰了。在接下来的09讲到12讲,我们就一起聚焦到博弈的具体方法上,专注于反爬虫的技术细节。希望我的经验可以帮助你赢得这场战争。
|
||||
|
||||
思考题
|
||||
|
||||
又到了愉快的思考题时间!
|
||||
|
||||
由于法务知识的特殊性,这些思考题我自己也很纠结,所以这次的思考题就相当于共同讨论吧。你可以任选一个,在留言区和我一起讨论。想知道具体答案,还是要咨询专业人士。再次强调,法律是一门严肃的学科!
|
||||
|
||||
|
||||
假设反爬虫方拿爬虫方没办法,一怒之下在数据里偷偷掺了点用户信息,爬虫方摇身一变成了抓取用户信息了。请问双方在法律上分别处于什么状态?
|
||||
假设最后开庭,爬虫方拿出证据证明自己抓的一直不是用户隐私,那么这个可以做为证据继续起诉爬虫破坏计算机系统罪吗?
|
||||
爬虫方发现用户隐私后,立刻起诉对方泄露用户隐私,有可能成功吗?
|
||||
|
||||
|
||||
期待你在评论区的分享,我会及时回复你。反爬无定式,我们一起探索。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
276
专栏/反爬虫兵法演绎20讲/09反爬虫概述(一):高收益的后端能做哪些基本的事情?.md
Normal file
276
专栏/反爬虫兵法演绎20讲/09反爬虫概述(一):高收益的后端能做哪些基本的事情?.md
Normal file
@ -0,0 +1,276 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
09 反爬虫概述(一):高收益的后端能做哪些基本的事情?
|
||||
你好,我是DS Hunter。从这一讲开始,我会给你讲一讲不同研发职能做反爬的方向和技巧。
|
||||
|
||||
一般来说,公司会将Web站点分为前端、后端两部分,也就是前后端分离。必要的时候,可能还会做BFF。后端做反爬,是一件自然而然的事情,很多公司的反爬虫都是后端开始做的。当后端力不从心之后,才开始给前端做。前端力不从心了呢?就开始由BFF做了。
|
||||
|
||||
所以在课程中,我们也同样按照这个逻辑,先从后端开始说起。我会给你介绍下后端进行规则过滤的基本方法,并带你进入正式的key生成与验证斗争中,希望你能在这个过程中,真正理解后端反爬虫的作用以及成本分析逻辑。另外在这节课的最后,我还针对爬虫的计算力进攻进行了拓展,如果你有精力,也可以随着文字一起思考。
|
||||
|
||||
现在,我们就从后端出手的原因开始说起吧。
|
||||
|
||||
后端出手的原因:服务器压力
|
||||
|
||||
我在上面提到了,后端做反爬是一件自然而然的事情。所谓的“自然”,其实是由于服务器(也就是后端)顶不住爬虫的压力才做的。后来慢慢有经验了,才开始做一些类似“提供假信息”、“没有反爬措施的反爬虫系统”这种奇奇怪怪的封杀操作。这个时候,后端出手的原因也慢慢不再仅限于减轻服务器压力,而是开始加入商业上的博弈了。
|
||||
|
||||
后端反爬虫的具体做法
|
||||
|
||||
首先你要知道,线上爬虫其实很多,不仅仅有竞对,还有一些练手的爬虫。这些爬虫特别可怕,它们往往极不专业,很容易把服务器打挂。这些爬虫,你可以尽情封杀。
|
||||
|
||||
而另一些竞对爬虫则完全不同,如果真的封杀了,即使胜利了,也会导致更多的问题。说是“皮洛士式的胜利”也不为过。因此两者要使用不同的策略“区别对待”,分开处理。这一讲,我们就主要针对竞对爬虫的骚扰给出具体的解决方案。
|
||||
|
||||
这里我为你提供了四种具体做法,分别是特征检测模块、key生成模块、验证模块和随机模块。它们像处于一个有输出又有辅助的团队一样,相互独立,又彼此协作,共同成为了反爬虫路上的有力助手。在实际应用中,我更推荐你综合使用。
|
||||
|
||||
特征检测模块
|
||||
|
||||
在05讲中,我提到了多种的特征检测,帮助你定位具体检测的内容。精准定位,才会事半功倍。这一讲,我们就来看看一些在后端进行的特征检测(例如HTTP级别检测中的HTTP Header),它们的具体实现方式是什么样的。这里的具体实现方式分为三种:在线检测,离线检测,混合检测。我们一个一个来看。
|
||||
|
||||
|
||||
在线检测
|
||||
|
||||
|
||||
在线检测,顾名思义,用户请求进来的时候,直接就检测特征,当场判定结果。就像现在的健康码一样,当场出码,当场判定,过期不看。
|
||||
|
||||
这里在线检测的做法,其实就是写个算法,针对近期的流量做样本,合并做一个集合。在集合中取特征平均值,最后拿当前流量做比较就可以了。如果后续单个流量过来后,特征不符合统计分布,那么这个流量就是有问题的。
|
||||
|
||||
不过这里会存在两个问题:样本本身会是爬虫吗?取平均值的复杂度会不会过高?
|
||||
|
||||
针对第一个问题,我们之前提到过,样本要从爬虫少的地方提取,例如订单页,进来就付钱。取付钱接口的流量,相对就纯净很多。如果对方想攻击这个样本,那代价可是太高了。
|
||||
|
||||
针对第二个问题,取平均值本身是一个O(n)复杂度的事情。因此,当流量高的时候,自然会变慢。不过,变慢的前提是,你使用的“近期的流量”,是最近一段时间的流量,例如最近一分钟。
|
||||
|
||||
如果反过来,你的流量池是一个先入先出的队列,那么其实复杂度就没那么麻烦了,因为流量数将是一个定值。而线上系统变慢的情况还是不可避免的。但是,系统性能问题对于很多职能部门来说是不可容忍的:要知道,其他团队费尽心思才节约出一点时间,被你一下子全耗光了,别人一定会和你有争议的。
|
||||
|
||||
针对性能问题,我们会有离线检测来解决。
|
||||
|
||||
|
||||
离线检测
|
||||
|
||||
|
||||
离线检测,顾名思义,就是把流量放到线下,抽时间慢慢算,算好了给线上用就可以了。通常,我们对流量规则的实时性要求并没有特别高的时候,就会采取这种方法。
|
||||
|
||||
这里我们提到了一个新的词,规则。这个词我们后续也会经常使用,也会和其它的词进行搭配,比如规则引擎。什么是规则?这里我们试着下个定义。
|
||||
|
||||
|
||||
规则(rule):-
|
||||
-
|
||||
使用任何技术手段,对线上请求特征按照指定的条件(condition)或方法(callback)进行检测验证,并执行指定操作的过程。在部分系统里,这个也被称为过滤器(filter)。
|
||||
|
||||
|
||||
回到离线检测的部分。其实,离线检测和在线检测的方法是一样的,但是操作上会有些区别。操作时,你可以把固定时间间隔(例如一分钟)的流量放到一个池里面,然后定期跑计算规则,例如上面提到的平均值,或者IP频次,都可以。接着再把规则推到规则引擎去,线上系统直接使用规则引擎产生的规则即可。
|
||||
|
||||
这里你应该可以看到,效率大大提升了,但是实时性会大幅下降。
|
||||
|
||||
回到我们这门课常用的一句话:小孩子才做选择,大人全都要。是的,我们还可以做混合检测。
|
||||
|
||||
|
||||
混合检测
|
||||
|
||||
|
||||
混合检测其实是针对不同的规则,使用不同的检测模式,并统一部署。
|
||||
|
||||
有的规则对实时性要求很高。例如,IP频次,阈值到达100,你就封杀。结果因为使用了离线规则,一分钟后才起作用,那一分钟内人家直接干上个一万次请求,这时候你封杀人家,人家直接走就可以了呀,一万次够用了呀。
|
||||
|
||||
有的规则对实时性要求不高,但是计算量非常大,那么就妥妥地走离线检测。例如HTTP Header,同一个爬虫上一分钟犯的错误下一分钟还会犯。这样的情况下,抓慢点也没关系,亡羊补牢嘛。而只要抓到了,对方又没办法立刻变更策略,他要改代码,反应更慢。因此可以走离线。
|
||||
|
||||
此外,离线策略不一定非得是一分钟,也可能是跑个一天,这种大规模策略甚至可以放在业务低谷期来操作,我们可以做一个在线离线混合部署,最大规模降低成本。
|
||||
|
||||
也就是说,白天,业务高峰,跑在线策略。晚上,业务低谷,跑离线Job,机器闲着也是闲着,低谷期利用起来反而提高了利用率,跑完第二天还是可以接着用。成本越低,从另一个角度来看也就是收益越大,后续和财务谈ROI也更有底气。
|
||||
|
||||
key生成
|
||||
|
||||
从这里开始,我们讨论的就是key的相关检测了。key生成可以认为是反爬虫的基本操作了,市面上几乎所有的反爬虫系统都逃不开这一套:下发加密key,客户端执行解密,然后上传解密后的key,服务端验证是否合法。虽然做法千差万别,但是原理都没什么创新。
|
||||
|
||||
这个做法和我们日常生活里面验证身份的流程非常相似,这相当于给每个人发一个员工卡,上班时要用员工卡验证身份。而我们主要的工作,就是验证员工刷的是不是发的那张卡。
|
||||
|
||||
你可能会疑惑,为什么验证模块不和key生成模块放在一起呢?其实,出于服务器压力的分配问题,生成key和验证key不一定在同一个集群实现。这样可以实现解耦,避免强依赖的产生,导致出问题的时候无法关闭系统,不得已进行熔断操作。因此,我们很可能需要一个独立的验证模块来进行key的验证操作。
|
||||
|
||||
那在key生成的这个版块,我们只讨论一个问题:如何生成一个key?
|
||||
|
||||
首先,生成一个随机数就可以了吗?如果生成随机数,那么必然要面对存储问题。不然在验证key的时候,你如何判断这个是自己生成的那个,而不是客户端乱编了一个呢?
|
||||
|
||||
因此,我们需要使用的,是一个伪随机的逻辑。也就是说,要有随机性,但是也要有规律。随机性是对爬虫来说的,有规律是对验证来说的。基于这样的操作方向,我们需要进行的就是 SKU与时间混合的操作了。
|
||||
|
||||
SKU(Stock Keeping Unit,最小存货单位),也就是我们常说的商品ID。我们前面论证过,反爬虫方会在指定时间内进行价格的变化,那么如何在不断变化的价格中添加一个伪随机的key生成逻辑呢?我一步步来说。
|
||||
|
||||
首先,一个比较简单的key生成办法是:
|
||||
|
||||
md5(sku+current_hour)
|
||||
|
||||
|
||||
这样,我们就实现了当前商品当前小时内key不变,那么验证模块也就可以做到针对指定的key。
|
||||
|
||||
你可能会觉得,一个商品key一直一样,是很容易被抓的。但实际上,这不一定会被抓,因为前端解密key会很复杂。其次,指定商品一小时又不变价,他没有重复抓的必要。
|
||||
|
||||
这里可能会出现的漏洞,反而是很容易被抓“规律”。对方多试几次,很可能猜出你的后端加密规则!怎么办呢?我们都知道,MD5是公开算法,那么其实防止被抓规律的做法就很简单了:加盐。
|
||||
|
||||
具体加什么呢?一个比较阴险的做法,是加检测规则。例如,加http头。这样,每个人就会变得不一样。这个时候我们的伪代码就变成了:
|
||||
|
||||
// fingerprint:通过用户特征,计算出一个无重复的指纹。
|
||||
// 用于给md5函数加盐
|
||||
md5(sku+current_hour+fingerprint(http-header))
|
||||
|
||||
|
||||
这样,每个用户的header不一样,那么每个人的key就不同。
|
||||
|
||||
你可能会问:但是,爬虫一般懒得改header,他实际上很可能还是每次拿到一样的key啊?
|
||||
|
||||
没问题,这个时候,我们上面提到的真随机就可以派上用场了。真随机虽然不好检测,但是他可以用来加盐。具体做法大概是:
|
||||
|
||||
var left = md5(sku+current_hour+fingerprint(http-header))// 32位
|
||||
var right = md5(random())// 取一个随机值,并md5掉,用于混淆key
|
||||
var result = xor(left, right)+right// 两个key异或作为新key的left,right不变。
|
||||
|
||||
|
||||
这里的XOR是一个全字段异或的循环。为什么要这样操作呢?因为32位的key就这样变成了64位,并且规律性极差。你验证key的时候呢,取前32位和后32位,再异或回来,就能拿到原来的left和right了。right是随机值,丢弃掉。left是key,验证即可。这样就实现了,对爬虫随机,对自己有规律。
|
||||
|
||||
验证模块
|
||||
|
||||
验证模块是反爬虫的核心,下发的key,就是为了传回来做验证。在验证模块,我们的核心就是:如何快速准确地验证key?
|
||||
|
||||
key验证其实就是key再次生成的过程。我们知道,下发key和验证key发生在同一session内,那么它们的上下文就是一致的,我们可以直接再生成一次key,与请求带来的key比对即可。
|
||||
|
||||
这时候你就会发现了,这种伪随机key的最大好处就是:无需存储,所以没有存储压力!因此效率极高!到这里,我们就解决了“快速又准确地验证”这个难题。
|
||||
|
||||
这里,我可以给你拓展一下。其实,有些拦截操作还可以放在生成key那里,而不是验证key这里。具体怎么做呢?举个封杀某个header的例子吧。如果某个HTTP Header有问题,那么你在生成key的时候,可以有意修改掉一位。也就是说,你可以假装不知道这个请求是来自爬虫的,然后直接生成一个错误的key给客户端。那么,回头这里在不受任何影响直接生成key的时候,之前生成的那个key是一定验证不过的。这样,对方还以为自己的key破解有问题。
|
||||
|
||||
那么,拦截操作放在生成key那里,和放在验证key这里,有什么区别吗?
|
||||
|
||||
区别很明显,生成key和验证key因为算法一致,所以可以放在两个集群。而放在生成key那里,是可以缓解验证key集群的压力的。要知道,虽然你生成key,也验证key,但是实际上很多低级爬虫是不带key直接打验证服务器的。因此,验证模块的压力天生比生成的地方大一些,所以,我们要减少操作,避免崩溃。而生成key的崩溃了,我们可以简单地关闭验证模块来实现熔断。而验证模块崩了……你确定你一定关得掉验证模块吗?它可崩了啊!
|
||||
|
||||
随机模块
|
||||
|
||||
随机模块,也就是随机筛选。它是验证模块的一部分,不过,“做随机筛选”这件事是一个可选项。所以这里给你单独讲解。
|
||||
|
||||
在随机模块,可能会出现两种做法。首先,随机跳过,其实就是在校验的时候,我们可能随机跳过一部分请求,不校验。第二种做法,随机封杀,也就是说我们也可能随机封杀一部分请求。至于冤枉真用户?冤枉就冤枉了。两种做法看起来都有些不可思议,但是它们还是有着实际意义的。我们一个个来看。
|
||||
|
||||
|
||||
随机跳过
|
||||
|
||||
|
||||
首先,随机跳过。随机跳过本身并不能拦截爬虫,但是它有一个战略意义,就是让爬虫方困惑,增加破解成本。
|
||||
|
||||
对于爬虫方来说,反爬虫方给出100%的假数据,和给出20%的假数据,其实是没什么区别的。哪怕只有5%的假数据,这一整批数据他都不敢用的,毕竟不知道哪些是假的。
|
||||
|
||||
这里我给你拓展一个情境,那就是降低假数据概率,会导致一个情况:爬虫方有可能在拿到真数据的那一瞬间,就觉得自己胜利了,然后代码直接上生产。这样生产上实际拿到的数据还是不准的。
|
||||
|
||||
这时候你会疑惑一件事情:那,我要是给太少假数据了,岂不是没什么意义?那我给多少假数据合适呢?
|
||||
|
||||
我个人的习惯是真数据占比数字通常设置为79.4%,其余的就是假数据了。
|
||||
|
||||
这么奇怪的数字是怎么定下来的?
|
||||
|
||||
通常来说,爬虫方会对自己的代码再三确认,也就是说,比较谨慎的爬虫工程师,试个三次发现没问题,也就被deadline给逼上线了,不会无休止地测下去的。而79.4%这个数字好就好在,连续三次真数据的概率,如果刚好是0.5,那就是79.4%的三次方,那么对方其实测试三次,有一半的概率是拿到真数据,就会容易误以为自己胜利了。而假数据的概率超过20%,也不低了。
|
||||
|
||||
所以这个数字非常合适。当然,这是在大规模勾心斗角的爬虫中使用的数据,实际上检测到是小爬虫的话,你可以不考虑随机跳过的事情,100%封杀也没问题。
|
||||
|
||||
|
||||
随机封杀
|
||||
|
||||
|
||||
随机封杀,依然是一个大型爬虫专用的技术,它的关键词只有一个,就是“低”,也就是随机封杀的概率设置会尽可能低一些。为什么呢?
|
||||
|
||||
首先,用户是会被误伤的。其次,你可能会说,整体概率设置低了之后,爬虫方被随机被检测到的概率也很低。
|
||||
|
||||
但是你要赌的是什么呢?是对方不小心抽检到了这个数据,并开始质疑爬取的数据有问题。而厉害的对手很可能实际爬的没啥问题,他又找不出证据来说明为什么这个数据不对,这很容易引发对方的产品经理和研发之间的争执,最终摩擦起火都有可能。
|
||||
|
||||
当然了,如果摩擦起火之类的事情没有发生,那……好像你也没损失什么对不对?所以,概率设置得低,也是可以的。
|
||||
|
||||
后端反爬虫的效果检测
|
||||
|
||||
完成了一系列的反爬虫措施之后,当然要复盘一下效果了。而反爬虫效果检测,一直以来都是个难题。因为你不可能直接去问爬虫:嘿兄弟,你抓到了多少假数据?就算你去问了,爬虫也得问:嘿,兄弟,真数据给我,我验证一下?
|
||||
|
||||
所以,我们只能通过一些办法,侧面估算出误伤率以及爬虫占比。
|
||||
|
||||
从技术角度来说,通常有两种方式,打点法和转化率不变法。前者用来检测误伤率,后者用来检测爬虫量。
|
||||
|
||||
所谓打点法,就是在有前后顺序的请求上,一个做反爬,一个不做反爬。举个例子,商品价格页面做反爬,商品付款页面不做反爬,毕竟你也不怕爬虫来给你付款。
|
||||
|
||||
这样,在价格页面检测到爬虫后,就写入一个Cookie,相当于给所有爬虫打一个标签。理论上说,普通用户是不可能有这个Cookie的。那么,我们在付款页面检测这个Cookie,能拿到它吗?显然是不应该拿到的,因为用户是无Cookie的。那么这里检测到多少Cookie,就证明有多少用户被误伤了。
|
||||
|
||||
而转化率不变法,则是另一个操作,我们首先定义一下转化率:订单量除以UV,就是UV的转化率。当然订单量可以先做用户去重,这个就看业务的要求了。这里我先假设,转化率只与网站的质量有关,与其他因素无关,或者至少关系很小。大多数情况下,商品在全天24小时内,转化率不变。
|
||||
|
||||
在这个假设下,就可以拉一个流量曲线,再拉一个订单曲线,加权一下试着让两者重合。但是这两者由于爬虫的存在一定是很难重合上的。你可以先想一下,你们的低谷期,也就是订单为0的时间,这个时候不管转化率是多少,UV都应该接近0对吧?那么,我们就可以判定,这部分的流量就是全爬虫。
|
||||
|
||||
但是扣除掉等量的流量后,订单曲线和流量曲线如果还是很难重合,那么这个不重合的原因,就是不稳定爬虫导致的。这个时候,你就可以一点一点扣流量了:慢慢估算出真实的转化率,进而估算出每个时间段的爬虫。当然,这种做法永远是估算,你不要指望精确计算出爬虫量。
|
||||
|
||||
根据上面的打点法和转化率不变法的做法指导,我们可以做离线检测和在线检测了。
|
||||
|
||||
实时在线检测:打点法
|
||||
|
||||
实时在线检测主要用于监控、熔断。而打点法是用于进行误伤检测的,也就是说,它能迅速地识别到用户被误伤、可以做自动熔断反爬虫的功能。因此,这里更推荐用打点法。
|
||||
|
||||
需要注意的是,由于是实时检测,对读取的实时性要求很高,就不能走离线库了,需要用在线库,比如常规的MySQL。不过,那服务器顶得住吗?
|
||||
|
||||
顶得住的。你可以回忆下打点法,实际上拦截打点,是在订单处拦截的,所以数据量是订单量乘以误伤率。这样一来,实际上没有多少数据。而如果真的出现了顶不住的情况,那就证明误伤太多了,可以直接先熔断掉反爬虫再说。
|
||||
|
||||
如果说做爬虫最重要的是低调,那做反爬最重要的就是:安全。不惜一切保证安全。
|
||||
|
||||
说得更直白一点就是:怂。
|
||||
|
||||
阶段离线检测:转化率不变法
|
||||
|
||||
其实,打点法和转化率不变法都是可以做离线检测的。但是这里主要推荐转化率不变法。
|
||||
|
||||
转化率不变,本质上是一个计算,这个计算需要全天的数据,因此全天数据都拿到之后再跑是没问题的。因此,计算不需要实时,也无需关注查询性能,最终走一次Hive查询即可。每天一次,按公司最低配置要求就行。此外,即使存储丢失了也不是什么大事,一切给成本让路。
|
||||
|
||||
至于计算时间,和上面特征检测部分的离线检测一样,是可以放在晚上的。同时,整个的效果检测也是可以使用在线离线混部的方式的。也就是说,你可以把统计功能和线上机器部署到一起,晚上用线上机器的剩余计算力进行离线检测。
|
||||
|
||||
小结
|
||||
|
||||
最后,我来给你做个总结。这节课,我们针对后端的反爬虫动作进行了详细的探讨。首先,后端因为天生忍受爬虫压力,主动进行了反爬虫的研发任务。那么针对爬虫进攻的目的与做法的不同,我们的应对策略也是不同的。
|
||||
|
||||
在中间的部分,我们一共提到了四种后端反爬虫的具体做法,它们彼此独立,但又相互配合。除了常规的特征检测我们一定要在后端做掉以外,还可以通过后端生成key并验证key来实现请求的身份校验。当然,一些勾心斗角的价格操作(即02讲中那些奇奇怪怪的价格迷惑方式)也可以在这里处理掉。而第四种反爬虫做法,“随机模块”,也是你的一个反爬备选项。
|
||||
|
||||
当然,别忘了在进行了那么多的反爬虫动作之后,后续的反爬虫效果检测也是后端义不容辞的责任之一。
|
||||
|
||||
这里,我也给你提供了一张这一讲的脑图来进行复习。针对四种动作的“独立又配合”的性质,我给每个动作增加了一个小的标签,希望能够帮助你理解它们之间微妙的关联。
|
||||
|
||||
|
||||
|
||||
下一讲,我们可以看下,前端这个反爬虫的主战场,是如何与爬虫正面刚的。
|
||||
|
||||
思考题
|
||||
|
||||
好了,又到了愉快的思考题时间!还是三选一的老规矩,你可以任选一个问题在留言区和我一起讨论。
|
||||
|
||||
|
||||
关于随机跳过爬虫的问题,会导致拦截率的下降,如何与老板解释这个事情呢?
|
||||
除了MD5伪随机的方式,你还能想到什么办法,实现不存储key?
|
||||
在线离线混合部署,你认为是应该部署到同一台机器上?还是应该用两个Docker共享资源?它们的优缺点分别是什么?
|
||||
|
||||
|
||||
期待你在评论区的分享,我会及时回复你。今天诗句的下方,也有关于计算力进攻的探讨,如果你有精力,也可以和我一起在评论区讨论。反爬无定式,我们一起探索。
|
||||
|
||||
|
||||
|
||||
扩展:难以破解的计算力进攻
|
||||
|
||||
爬虫方的计算力攻击是个很尴尬的事情,目前来讲,并且没有真正完美的防范措施。
|
||||
|
||||
我们都知道,反爬是需要消耗计算力的。虽然和爬虫相比,我们可以做到少消耗资源,但是还是不能做到不消耗资源。
|
||||
|
||||
举个例子,生成key的服务,虽然我们上面介绍的MD5伪随机,已经是优化过的方案了,最早是走存储key的,可以做到真随机。
|
||||
|
||||
但是,如果爬虫知道了这个逻辑,他拼命地访问生成key的接口生成key,访问之后也不验证,单纯地拼命去消耗。这样的进攻会导致大量的key被生成、存储,但是没有人消费,最终积压在存储系统里,压爆反爬虫系统。
|
||||
|
||||
也许你会继续问: 这样对爬虫又什么好处吗?
|
||||
|
||||
当然有,反爬虫系统挂了,结果就是会自动熔断,系统以无反爬的状态运行。就像每天调戏保安,保安累得全睡着了,小偷不就可以随便进去偷东西了吗?
|
||||
|
||||
所以,这也是我们采取MD5的伪随机key的主要原因。
|
||||
|
||||
除此之外,你可以压测一下自己的反爬系统,看一下哪里是系统瓶颈,任何一环被打挂了,爬虫都能肆意妄为,这是一个很可怕的事情。
|
||||
|
||||
也许你会说:我们是不是可以对这一切做一些防范?比如,拉取key的接口做些什么措施,让爬虫无法来乱搞事情?
|
||||
|
||||
嗯?有没有感觉这是个递归的死结?你说的是不是给反爬虫系统做一个反爬虫系统?那么这个给反爬虫系统做保护的反爬虫系统,又由谁来保护呢?
|
||||
|
||||
所以,我们可以做一些基本的防护,比如规则封锁。但是指望完全防护住,注定是一个不现实的想法,需要早早放弃。
|
||||
|
||||
|
||||
|
||||
|
169
专栏/反爬虫兵法演绎20讲/10反爬虫概述(二):无收益的前端是怎么进行key处理的呢?.md
Normal file
169
专栏/反爬虫兵法演绎20讲/10反爬虫概述(二):无收益的前端是怎么进行key处理的呢?.md
Normal file
@ -0,0 +1,169 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
10 反爬虫概述(二):无收益的前端是怎么进行key处理的呢?
|
||||
你好,我是DS Hunter。
|
||||
|
||||
上一讲,我们提到了高收益的后端为了保护自己,进行了大量的反爬支持。但是反爬的主战场,依然是前端。
|
||||
|
||||
众所周知,做反爬,对于前端来说是没什么收益的,因此动力会差很多。如何解决动力问题,我们会在进阶篇深入探讨。我们目前亟待明确的,是前端在帮助后端进行反爬的时候,具体能够做些什么。
|
||||
|
||||
在反爬虫工作里,前端主要的作用是key加密。除此之外,还有一些杂活,比如收集信息、埋点统计等等。最后我们会把这一切聚集到规则引擎中统一收口。今天我们就先来探讨前端反爬虫的主力部分——key的加密。至于其它的辅助以及收尾工作,我会在下节课跟你一起探讨。
|
||||
|
||||
在09讲中,我们已经明确过了,服务端的key是加密后下发的。那么客户端必然需要解密方法。不过,解密方法的基础框架是什么呢?除此之外,基础框架内有什么可以用到的代码保护方式呢?我们先从第一个问题开始分析。
|
||||
|
||||
放置方式:成对加解密
|
||||
|
||||
这里特意发明了一个新词,叫成对加解密,和“对称加解密”这种加密方式不是一件事。我们所熟知的对称加解密是一个加解密的方式,或者说过程,而成对加解密是一个存储方式。
|
||||
|
||||
加密这件事在服务端,也就是后端已经直接执行掉了,而解密操作是发到客户端让客户端去做的。通常来说,解密操作是如何进行的呢?
|
||||
|
||||
举个例子,服务端生成的key是10。那么如果我们进行如下一些简单的加密措施:
|
||||
|
||||
|
||||
|
||||
那么对应的解密方法自然就是所有操作的逆运算:
|
||||
|
||||
|
||||
|
||||
这样就可以得到原始的key了,是10。当然,这里的四则运算只是demo,我想聪明的你不至于学完了就真的在生产用加减乘除吧……不过,不论你用的是什么方法,在整个的运算中,我们的主要要求都是可逆和不丢精度这两点。
|
||||
|
||||
因此,我们在服务端生成key的时候,就需要同时确定加密解密的链路顺序,这样才能保证客户端按照顺序解密后得到正确的结果。
|
||||
|
||||
如图:
|
||||
|
||||
|
||||
|
||||
那么对应的解密流程就是:
|
||||
|
||||
|
||||
|
||||
为了方便客户端的解密,我们可以在服务端把加密方法和解密方法成对存储,“加密1”对应“解密1”,“加密2”对应“解密2”,以此类推。这就是成对加解密的核心了。而前端的解密方法,也是由服务端这样推送下来的。
|
||||
|
||||
解密方法从服务端推送下来之后,就意味着所有的题目也已经出完了。我们假设,现在你的服务端一共存储了100对加解密方法。你可以随机取出n对并通过洗牌算法确定一个随机的顺序,通过这个随机顺序生成的加密方法来对key进行加密。这样每个爬虫在破解的时候,就需要逆序阅读对应的解密方法,相当于面对了不同的代码。整个过程类似于题库抽题的原理,爬虫方无论破解多久,也不敢保证自己爆破了题库。所以就算爬虫方的代码上线了,他的心里也还是没底的。
|
||||
|
||||
是的,这很像开盲盒对不对?那么盲盒套路我们都知道,是存在限量款的。所以,你完全可以给个隐藏款,爆率极低,调试的时候很难撞到,但是竞对的生产在爬取的时候,一旦量变大了,就会撞上对不对?
|
||||
|
||||
盲盒的事情就先说到这里,我们回到客户端的解密上。服务端roll到了一堆的加密方法并且按顺序加密了,那么客户端就应该倒叙进行解密。是的,这是一个栈。在12讲我们会单独讲如何生成这段js代码。而客户端执行了对应的js,就可以把解密后的key拿到了。
|
||||
|
||||
当然,这样的破解难度对于竞对来说是很低的。这里虽然有一定的随机性,但是还不够。成对加解密是隐藏一切的基石。因此,我们后面会增加一些浏览器端的代码保护方式,提升破解难度。
|
||||
|
||||
代码保护方式:变量名混淆、eval和虚拟机
|
||||
|
||||
这里我为你提供了三种代码保护方式,按照复杂度排序,越往后越复杂。但是在使用的时候,我们全部都会用到。
|
||||
|
||||
变量名混淆
|
||||
|
||||
变量名混淆是最低一层的加密,也是必备的加密。
|
||||
|
||||
我们通常会使用一些js的minifier工具来进行变量名加密,但是,实际上这个并不算加密,因为从名字来看,minifier是minify加er的变形,也就是说它本质上是在做minify——缩短变量名长度。诚然,缩短变量名也会导致调试体验差,但是这对于爬虫来说是远远不够的。
|
||||
|
||||
想象一下:我们工作中,最可怕的,是变量名短吗?其实并不是,很多人编码习惯不好,变量名都是abcd之类的,我们日常生活中不也调试得不亦乐乎吗?这对爬虫根本也不是事。
|
||||
|
||||
那么我们最怕的是什么呢?其实最怕的反倒是视觉上容易混淆,比如变量名过长,又很近似。举个例子,下面有两个变量名:
|
||||
|
||||
|
||||
|
||||
你能一眼就看出来这不是一个变量名吗? 这个难度就比单纯的短变量名难度大多了。
|
||||
|
||||
因此,我们的变量名要进行混淆,降低可读性。
|
||||
|
||||
在早年,这个操作只能通过模版替换的方式来做,例如将js写到模版中,我们在12讲中说到engine混淆的时候会详细介绍。随着AST技术的发展,这个操作慢慢变得容易了,而且定制化也更强了,感兴趣的话也可以查一下webpack的AST技术。当然,模版还是不可替代的,因为模版无需解析语法树,因此效率非常高。
|
||||
|
||||
最后,你一定会问:如果我是爬虫方,面对变量名加密我怎么办?
|
||||
|
||||
答案其实很简单,我们刚刚是不是提到了js的minifer工具缩短的变量名反倒可读性高了一些?是的,你可以在拉取到js之后,自己minify一次,虽然这样比源码可读性降低了很多,但是比起混淆后的变量名,可读性反倒高了不少。这也算是稍稍扳回一城了。
|
||||
|
||||
eval
|
||||
|
||||
eval是js最臭名昭著的功能,所以对于反爬虫来说几乎是必备的。即使有些使用了虚拟机,也会使用eval来运行虚拟机。
|
||||
|
||||
eval的问题在于,它会将字符串进行处理,然后送入eval执行。那么无论是阅读还是调试体验都很糟糕。所以我们在engine里面会大量使用eval。那么针对这两点,爬虫的对策是什么?怎么才能反制爬虫的对策呢?
|
||||
|
||||
第一,阅读。eval难以阅读主要是因为不能找到实际执行的代码。但是如果爬虫方换个思路,这个问题就好解决了。我们看下面的例子:
|
||||
|
||||
eval = console.log
|
||||
eval('1+1');
|
||||
|
||||
|
||||
你可以找个console运行一下试试。是不是输出了1+1?这样,代码就可读了。不过又出现了代码本身不会运行的问题。这个问题,对爬虫方来说并不是一件难事:备份eval,调用console.log,然后运行备份的eval就可以了,js基本操作。
|
||||
|
||||
这样,所有的方法都会运行前先输出,就可以拿到可阅读的代码了。
|
||||
|
||||
之后,就到了反爬虫方再次反针对的环节了。反爬虫方可以判定eval的toString,或者重写console.log,调用一个无害的eval,触发无限递归,而爬虫方则相应的需要重写eval的toString,以及安全处理递归结束条件。再接下来,反爬方可以再重写Function的toString方法来进行检测,或者直接备份eval的symbol,等等。
|
||||
|
||||
这里的攻防方式就不一一细说了,比拼的就是谁js能力更强。
|
||||
|
||||
第二,调试体验。
|
||||
|
||||
eval一个很大的黑点就是不方便调试,因为他是一行,不是多行,没法打断点进去。这一点爬虫方可能怎么处理呢?
|
||||
|
||||
其实还是一样的办法。我们都知道,Chrome的调试工具碰到debugger会自动断下来。我们刚刚注入了eval,实现了先console再eval。那么,其实爬虫方还可以再进一步,在拿到字符串之后,在字符串的前面拼一个debugger进去,再送进eval。这样,eval的代码会首先被中断。爬虫方也就实现了对eval做调试。这个就是爬虫方针对eval做调试的一个小技巧。
|
||||
|
||||
那么,我们作为反爬虫方是不是束手无策了呢?毕竟看起来这个是无解的,没办法阻止他注入进去啊。是的,在没有办法阻止的情况下,我们的选择就是:让他注入进去,然后在后面坑他。
|
||||
|
||||
最普遍的一个做法就是让eval里面的代码大量检测运行时间。单步调试的代码与直接运行的代码,最大的不同就是运行时间不同。做了这个检测之后,爬虫方就会发现很多代码可能越调试越不对劲。因为,反爬虫方可能已经把运行时间这个条件放到key解密里面了。
|
||||
|
||||
举个例子,key的某一位可以用一个固定的整数除以运行时间并取整,这样相当于判定运行时间的阈值,然后用数学方法展开一下,不要直接取时间,而是把一堆时间作为参数传入进去,最终的数学化简形式是卡时间阈值即可。我们在中学学过很多多项式化简的办法,这里作为反爬方,你只要反过来操作,变成“化繁”即可。
|
||||
|
||||
虚拟机
|
||||
|
||||
虚拟机和eval的思路是一样的。与eval不同的是,虚拟机技术能够有效避免代码被直接截取,并且可以自定义指令集,而指令集本身的名称又是可以被混淆的。
|
||||
|
||||
所谓的虚拟机,指的就是使用js实现解释器的功能,来解释服务端下发的代码。所以有些地方也会叫解释器,在反爬虫领域这指的是一个东西。
|
||||
|
||||
常用的解释器有两种,一种是类Lisp解释器,一种是类汇编解释器。当然,两者各有优缺点,你可以根据情况任意选择。
|
||||
|
||||
Lisp解释器的优点是服务端编译的时候速度很快,因为Lisp代码直接可以转成语法树。而缺点是编写很难,对方首次阅读可能会迷惑,而一旦理解,后续的破解难度就大大降低了。自己的编写时间和对方的破解时间相比,耗费太多了。
|
||||
|
||||
至于类汇编解释器,编写很简单,你可以使用类C语言来进行编写,然后服务端进行一次编译即可。缺点是编译本身耗时比较严重,并且还要写一个复杂的编译器。优点就是可读性大大降低,对爬虫方的困扰最大。
|
||||
|
||||
也许你会问:我不可以直接上WebAssembly这种简单又快速的方式吗?
|
||||
|
||||
答案是,可以,但是很难。原因之一是,WebAssembly过于标准,已经开始有一些逆向工具了。原因之二是,WebAssembly的兼容性还不是很好。所以也许未来会用的上,但截止到现在还不是一个最优选择。
|
||||
|
||||
实现方式:自定义Node.js的engine
|
||||
|
||||
说实话,为了迷惑爬虫方,上面所有的操作都很混乱。
|
||||
|
||||
虽然我们说,混乱对于反爬虫不是件坏事。但是,过度混乱也会导致调试体验的缺失。因此,我们需要服务端针对爬虫和规则,使用两套不同的阅读方式,服务端看到的应该是清晰明了的代码,而客户端看到的应该是混淆后的代码。这就是自定义engine要做的事情。
|
||||
|
||||
但是或许你意识到了一点:似乎这种事情后端做不了或者代价太大,前端因为暴露给客户又不适合做。那么这部分灰色地带怎么办呢。
|
||||
|
||||
是的,一切没人做的事情都会沦落倒让BFF去处理,在12讲我们讲BFF的时候会着重讲Node.js的engine的具体实现方式。这里,我们就先提一下这么做的必要性。
|
||||
|
||||
小结
|
||||
|
||||
这一讲,我们主要说的是前端反爬虫动作中的key加密部分。
|
||||
|
||||
首先,放置方式上,推荐你使用成对加解密的方式,这会提升系统随机性,为爬虫方解密增加一定的难度。
|
||||
|
||||
而代码保护的部分,我给你提供了三种方式,分别是变量名混淆、eval和虚拟机。
|
||||
|
||||
变量名混淆,主要是让你变成一个脸盲,也就是降低了代码可读性;而eval和虚拟机则是用于把代码搅浑,非常像炉石里的卡牌“尤格-萨隆”,在调试上让人获得困惑而又意想不到的体验。当然,这部分的保护有的时候也会让你觉得混乱。那么为了避免在迷惑爬虫方的时候把自己搞晕了,最后我也给你提到了自定义Node.js的engine这个实现方式的必要性。之后我们也会在12讲中进行详细的讲解。
|
||||
|
||||
这里我要强调的是,key加密本身是为了增加调试复杂度,而不是为了让对方找不到key,不要小瞧自己的对手,以为对方连找都找不到。另一方面,你也不用过于高估对手,他们也只是普通的人类,并非无所不能的超人,千万不要妄自菲薄。
|
||||
|
||||
至此,反爬虫最大的核心:key加密相关,就告一段落了。但是为了让系统更加完善稳定,我们依然需要一些非关键模块来辅助。在下一讲里,我们会详细介绍这些看起来对拦截爬虫没有太大贡献,但是又必不可少的部分。
|
||||
|
||||
此外,虽然成对加解密提供了一个不错的框架,但是还需要实际的内容来增强加密效果,一些隐藏的检测套路也是必要的。针对key加密的这些具体实现套路,我们还会在下一讲后面的加餐中详细解读,你也可以期待一下。
|
||||
|
||||
思考题
|
||||
|
||||
好了,又到了愉快的思考题时间。还是三选一的老规矩,你可以任选一个问题在留言区和我一起讨论。
|
||||
|
||||
|
||||
所有的加解密都是执行js,那么如果对方使用浏览器直接运行js,是否意味着所有的加解密都形同虚设? 如果不是,那原因是什么?
|
||||
成对加解密本身就存在拦截概率了,因为对方可能匹配到熟悉的题目,也可能匹配不到。那么,我们如果有意放过爬虫,要计算条件概率吗? 如何计算呢?
|
||||
成对加解密roll出来之后要做一次洗牌,如果不做会有什么问题吗?
|
||||
|
||||
|
||||
期待你在评论区的分享,我会及时回复你。反爬无定式,我们一起探索。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
172
专栏/反爬虫兵法演绎20讲/11反爬虫概述(三):前端反爬虫是怎么做信息收集的?.md
Normal file
172
专栏/反爬虫兵法演绎20讲/11反爬虫概述(三):前端反爬虫是怎么做信息收集的?.md
Normal file
@ -0,0 +1,172 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
11 反爬虫概述(三):前端反爬虫是怎么做信息收集的?
|
||||
你好,我是DS Hunter。
|
||||
|
||||
上一讲,我们已经了解了前端反爬虫中最主要的动作,key的加密,但是除了这件事,前端还可以完成更多的细节来辅助整个反爬虫动作。
|
||||
|
||||
例如信息收集,它们虽然不会直接完成“拦截”的动作,看起来也没有什么贡献,但是对于工程师的生存以及“拦截”动作本身的指导和优化来说,却有着不小的辅助功能。最后,我们会把key的加密、信息收集这一切都聚集到规则引擎中统一收口。
|
||||
|
||||
这一讲,我们就把目光聚集在信息收集以及规则引擎这两大辅助部分,完成前端反爬虫的主要工作。
|
||||
|
||||
信息收集
|
||||
|
||||
我在01讲中,就强调过信息一直是战争的核心,而信息收集是反爬虫的重中之重。公司有爬虫的需求,是希望在信息战中取得胜利,进而赢得商业的战争。而反爬虫方“收集信息”需求的产生,是由于工程师们想在反爬虫这场战争中打赢。
|
||||
|
||||
那么,到底要收集什么信息、怎么收集信息呢?后续我们又要怎么利用这些信息呢?我们按照反爬虫的动作顺序,先从信息预收集的部分开始说起。
|
||||
|
||||
信息预收集
|
||||
|
||||
在信息预收集模块,我们需要收集用户特征用于分析,而收集这些信息的方法,都可以认为是收集模块。当然,因为用户特征信息会被送到服务端进行分析检测,所以这里我们收集了哪些数据,应该是一个秘密,尽可能让爬虫方不知道才好。这和后面我们提到的“埋点统计分析”中的普通埋点是不同的。普通埋点,不怕爬虫方知道。
|
||||
|
||||
我们在《05|通用且基本的检测规则》里面说到的浏览器特征以及业务特征,其实都是前端的用户特征检测点。这里,我们主要聚焦在技术方面的浏览器特征分析。
|
||||
|
||||
浏览器特征,核心其实就是DOM指纹。我们都知道,DOM是一棵树,所以每个节点都可以通过XPath来访问到。同时,还有一部分对象放在了BOM上面,也就是通过window来直接访问。那么具体的访问方式是什么呢?我来帮你回顾一下。这里我们先规定一下,虽然浏览器BOM和浏览器DOM是两个东西,但是访问方式都差不多,在下面同时出现的时候,我们统称DOM了。虽然这样在学术上不正确,但是其实并不影响我们交流。
|
||||
|
||||
window是我们整个DOM对象的根节点,我们从这里出发,理论上可以到达DOM对象的任何一个节点。理论上说,我们也可以用Xpath来访问任意一个DOM节点。部分BOM对象即使不可达,我们也可以仿照XPath给BOM做一个类似的定位符,来标记访问信息。这样,我们从window出发,就可以遍历所有的对象了。
|
||||
|
||||
但是要注意的是,整个树是存在循环引用的,我们为了避免递归调用死循环,必须进行重复节点检测。这个具体做法就不demo了,检测重复节点可以说是经典面试题了,属于基操。
|
||||
|
||||
当然,我们不但可以通过上述的过程拉取整个window对象的信息,还可以进一步进行特征提取,例如取window对象的MD5——当然记得加盐,直接取MD5很容易被猜出来。
|
||||
|
||||
我们还可以指定部分的XPath,然后让这部分节点聚合在一起成为一个对象,在浏览器端进行特征提取。这样我们就可以拿到一个用户指纹了。这个指纹可能防冲突并不好,但是伪造难度也并不低。
|
||||
|
||||
我们之所以这么费事,非要提取一个指纹出来,而不是直接把信息上报,有以下几个原因:
|
||||
|
||||
|
||||
被破解几率低:直接上报很容易被抓,而且因为是明文的,对方一旦知道了逻辑,伪造难度就下降了。
|
||||
|
||||
保密程度高:指纹是加盐的,因此相同的信息,其实上报的key是不一样的。但是服务端知道原始key是什么,虽然MD5不可逆,但是可以通过已有的key进行再运算。至于盐的上报,可以夹杂在MD5结果里。不一定是insert,也可以是replace,因为少验证几位没什么大事。
|
||||
|
||||
速度快、压力小:获取指纹之后,传输数据量会大大降低。这样一方面能提升速度,一方面能降低服务器压力。
|
||||
|
||||
|
||||
误伤统计收集
|
||||
|
||||
误伤统计收集则与普通信息不同。如果说信息预收集,信息来源是用户产生的,后面的埋点信息是反爬系统产生的,那么误伤统计则是一个中间地带。因此,信息预收集需要强加密,埋点统计需要弱加密,而误伤统计则落于两者之间,可以随意选一个加密强度。当然了,这里的所有强、中、弱都是相对而言的,每一个部分的信息都至关重要。
|
||||
|
||||
我们在09讲提到的误伤统计理论中讲过一个“打点法”,也就是客户端每次访问写入一个Cookie,然后在订单之类的页面进行拦截。这一讲的误伤统计收集,同样使用这个方法。不过这一讲我们会就它的加密强度来讨论。由于拦截的过程中是直接读取Cookie的,那么加密主要就是放在写Cookie的地方了。
|
||||
|
||||
低级别的加密,是在Cookie里加入用户信息。再升级就可以增加不可逆加密,以服务端有办法鉴别有效性为标准。注意,我们提到不可逆加密的时候,有的朋友经常认为,不可逆加密就是不可逆的,所以客户端肯定不能用,但其实这是错误的想法。
|
||||
|
||||
如果在服务端验证时,我们的需求是解密出来的,那不可逆加密当然很难使用。如果我们只是鉴定它是否有效,或者已知入参是有限的,那么就可以使用不可逆加密了。
|
||||
|
||||
误伤统计收集与埋点不同,这个不会有高并发——如果有高并发岂不是你的误伤已经血流成河了。因此不用担心高并发无法处理的事情。
|
||||
|
||||
不过,如果出于谨慎考虑,也可以做一个熔断:当系统承接不了网络流量时,直接断掉误伤统计,同时熔断掉反爬需求即可。此外,还可以做成更谨慎的:反爬虫默认是断掉的,误伤统计系统定期给爬虫系统充值时间,这样一旦误伤统计系统跪了,反爬虫系统会自动回到默认值,也就是关闭状态。
|
||||
|
||||
埋点统计分析
|
||||
|
||||
如前面所说,埋点信息是非关键信息,因此可以不用特别强的加密。可能你会问:埋点统计是弱加密,那么,无加密不行吗?
|
||||
|
||||
答案是,埋点统计可能也会被抓取,也就是爬虫可能爬取埋点,来影响你的统计和决策。不过,由于要得到这个效果的过程是很漫长的,所以大部分爬虫也不会死磕埋点。URL本身不可能被加密,所以加密的就只有报文了。当然,弱加密只是相对而言,如果你的对手真的死磕你的埋点,你也可以提升加密等级,这个不能认死理。
|
||||
|
||||
那我们就来看看,埋点信息埋什么呢?这里主要分这么几类:
|
||||
|
||||
第一类,常规用户访问数据;-
|
||||
第二类,爬虫访问数据,包括爬虫类型,来源,数量,等等;-
|
||||
第三类,部分测试策略的线上效果收集。这个在13讲会详细说明;
|
||||
|
||||
有了这些数据之后,我们以后做效果检测,或者说,制作ROI报表就容易了很多。严格来说,埋点统计算是BI的一部分,虽然只是出了几个报表。
|
||||
|
||||
实际上,这类报表的汇报意义远远大于实际意义。我在前面说过,我们的系统做了实时的熔断、实时的监控,因此埋点通常只是一些统计数据,用来衡量业务指标的。
|
||||
|
||||
但是要注意,汇报也是工作的一部分。在进阶篇的时候我们会提到相关技巧。
|
||||
|
||||
例如,所有项目都要汇报ROI,反爬也不例外。没有ROI支撑的项目,光靠理想是活不下去的。而ROI的来源,就是这些埋点数据。
|
||||
|
||||
|
||||
埋点统计的痛点
|
||||
|
||||
|
||||
排除掉加密信息这个点之后,埋点信息有几个最大的痛点:并发压力,数据存储压力以及读取速度。
|
||||
|
||||
因为通常来说,这三样同时实现,几乎是不现实的。因此如果必须舍弃一样的话,我们会选择舍弃读取速度。因为如果能砍掉产品经理提出的“实时查看爬虫状态”这种无意义的需求的话,我们就可以完成这一切了。为什么说这个需求是无意义的呢?因为实时爬虫状态对于做出决策没有任何价值。有爬虫,系统拦截即可;无爬虫,系统运行即可。看得到,看不到,对公司没有任何影响。
|
||||
|
||||
这个主要的影响反倒是在技术侧,技术如果发现误伤较高,系统又没有自动熔断,那么需要手动熔断。当然,这个在误伤统计收集里面就做掉了。而误伤统计本身又没有高并发问题,相当于砍掉了并发压力,来实现需求。
|
||||
|
||||
最后,怎么砍掉这个需求呢?砍,也是有技巧的,你凭空砍掉产品经理一个需求,严重影响他的KPI,这是他难以接受的,也必然会与你发生争议。而你给他换个需求,就像上面一样,把埋点监控换成误伤统计监控,他能给老板交差了,也就自然不会和你死磕。
|
||||
|
||||
|
||||
埋点统计的实现方式
|
||||
|
||||
|
||||
因此我们的实现方式就很好理解了:前端使用大量Server换取网络链接数,同时聚合数据,避免冲击后端收集模块。后端使用常规的高写入速度、低读取速度的存储方式来承接即可。大公司通常有成熟的系统,但是小公司往往没有这个模块,需要自己来实现。
|
||||
|
||||
读取数据的时候,因为是高写入速度、低读取速度,我们的读取速度用来换高并发和写入速度了,那就意味着不可能实时查看。而上面我们已经和产品砍掉了实时查看的需求,那么我们的查看方式就只有每日报表这一种了。实际上,每日一次的报表足够使用了,如果真的有比较实时的要求,撑死也就是一个小时,再高就没有实际意义了。
|
||||
|
||||
低读取速度的存储,应对一小时一次的读取,也是没有任何压力的。这个完全不用担心。
|
||||
|
||||
规则引擎
|
||||
|
||||
综合上一讲说到的key的加密以及这一讲的信息收集、埋点统计分析,你可能意识到了一个问题:我们线上需要大量的变更,而变更就要发布,发布就有流程。但是爬虫不等人,等你变更发布完可能一天过去了,爬虫都走人了。所以,我们需要一个能够实时变更生产规则的系统。这个系统,我们就称为它规则引擎。
|
||||
|
||||
那么在反爬虫这个case里,规则引擎有三个主要构成部分,分别是信息收集模块、规则判断模块以及规则执行模块。其中,规则判断一般是在服务端或者BFF实现的,而信息收集和规则执行都会在前端执行。因此我们主要来看这两点。
|
||||
|
||||
首先看信息收集模块的设计。
|
||||
|
||||
严格来说,信息收集模块是流程的起点,因此对于状态机而言它没有前置状态。
|
||||
|
||||
如前面所说,客户端收集的信息,会在客户端进行加密,然后传输过来,那么就可能是可逆加密与不可逆加密两种情况。因此,这里可能会有解密,也就是说会使用到对称加密架构,但也可能没有解密却有验证模块,这就会使用到不可逆加密了,不过这样做的缺点就是可能会丢失细节。
|
||||
|
||||
此外,规则执行模块,这里依然取决于你面临的状况。
|
||||
|
||||
有的系统,针对反爬虫,是无脑拦截的,那么前端无需做什么事情,针对服务的拦截响应做一个友好的兼容处理即可。但是有的系统设计,比较重前端,会进行很多操作,比如前面提到的Cookie等等。这个时候,规则引擎不再是状态机,这里是纯粹的rule。客户端只要写rule的解释逻辑即可。
|
||||
|
||||
这里需要注意的是,服务端如果增加了rule,可能导致客户端不兼容,需要考虑热更新的情况。例如,服务端增加了rule,CDN也发布了,但是客户已经几天没刷过页面了,用的还是三天前的js代码。这时候需要考虑做客户端版本容差,单独拉取rule规则执行。
|
||||
|
||||
最后,针对规则引擎部分,我们可以做个总结。其实面对“不等人”的爬虫,规则引擎存在的主要作用有四点:
|
||||
|
||||
第一,降低发布时间,提升响应速度。-
|
||||
第二,降低研发成本,避免每次都写代码变更。-
|
||||
第三,提升灵活性,更敏捷的对爬虫做出反应。-
|
||||
最后,基于规则而不是基于代码片段特性,可以降低出错的概率。
|
||||
|
||||
那么到这里,前端,这个反爬虫的主战场,能够做的事情就已经介绍完了。
|
||||
|
||||
小结
|
||||
|
||||
最后,我来给你做个总结吧。这一讲,我们讲解了前端的辅助工作,信息收集以及规则引擎。
|
||||
|
||||
信息预收集本质上相当于游戏里面的插眼,帮助你有更好的视野来进行决策。但是我们都知道,不能把眼镜插在太明显的地方,否则很容易被人排掉,这就是加密的意义所在。而完成预收集之后,就是我们在上一讲一直讨论的key加解密以及混淆的过程了。
|
||||
|
||||
接着,在反爬虫动作完成后,不论是出于对效果的检测还是对自己的保护,我们都会进行误伤统计以及埋点统计的分析.。由于这个数据会用于复盘,对自己的决策十分重要,因此如果被爬虫知道了,他们一定会爬这个埋点统计接口来干扰你。所以,这个加密程度也可以根据情况适当调高一些。
|
||||
|
||||
最后,规则引擎帮助我们快速响应变化,避免贻误战机。
|
||||
|
||||
以上,前端反爬虫的所有动作,就算完成了。在文字的下方,我也为你准备了一张前端反爬虫的完成动作图,希望帮助你理解这两讲的关系。
|
||||
|
||||
|
||||
|
||||
思考题
|
||||
|
||||
好了,又到了愉快的思考题时间。还是三选一的老规矩,你可以任选一个问题在留言区和我一起讨论。
|
||||
|
||||
|
||||
规则引擎本质上跳了生产发布,而制定生产发布流程是为了降低线上变更风险。那么,如果测试质疑你在引入风险越过测试权限,如何回应呢?
|
||||
理论上说信息收集是越多越好的,但是过多了又会对系统造成较大的压力。那么如何评估需要收集哪些数据呢?
|
||||
收集的数据里不能包含用户隐私数据, 否则可能有法务风险,尤其是跨国项目。 那么, 如何保证自己收集的数据不会不小心包含用户隐私呢?
|
||||
|
||||
|
||||
期待你在评论区的分享,我会及时回复你。今天诗句的下方,也有关于规则引擎的实现方式——状态机的探讨,如果你有精力,也可以和我一起在评论区讨论。反爬无定式,我们一起探索。
|
||||
|
||||
|
||||
|
||||
规则引擎的实现方式:状态机
|
||||
|
||||
有些课程可能会用状态机这个词,其实规则引擎和状态机基本是一个意思。确切来说,大部分规则引擎是用状态机实现的。没做过的人可能觉得状态机这个词有点高大上,但是说穿了,状态机也不是什么神秘的东西。
|
||||
|
||||
现在正好是年初,也许你正在刷题准备面试,那么你一定会做到DP相关的题目,所有题解都会和你说:DP的核心是找到状态转移方程。注意这个词:状态转移。这个词虽然是讲解DP的,但却非常清晰地描述了状态机的核心:状态,以及转移。状态,state,名词;转移,也就是action。你的系统能支持这两个事情基本足够了。
|
||||
|
||||
简单地说,你的系统存在各种节点(state),在每个state下,根据不同的条件,可以进入另一个状态。也就是action。
|
||||
|
||||
有了状态机,就可以实现任意的流程图。这是规则引擎的重要作用。实际上,我们写的很多代码,本质上只是在写流程,例如流量进来,进行规则判定,根据判定结果,进行不同的处理。看起来是代码逻辑,但是抽象一下,这就是流程。看起来是流程,但是再抽象一下,就是状态机。因此有了状态机,就可以任意实现流程变更,而不需要发布了。因此,能大大节约时间,提升灵活性,降低出错概率。
|
||||
|
||||
状态机可能在服务端执行,也可能在BFF执行,这取决于公司的架构。当然,要尽量适应公司架构,而不是去改变架构,因为反爬并非一个高ROI项目,不具备这样的实力。如果公司没有BFF,那就老老实实在服务端做就可以了。
|
||||
|
||||
|
||||
|
||||
|
305
专栏/反爬虫兵法演绎20讲/12反爬虫概述(四):前后端都不合适的时候如何进行处理?.md
Normal file
305
专栏/反爬虫兵法演绎20讲/12反爬虫概述(四):前后端都不合适的时候如何进行处理?.md
Normal file
@ -0,0 +1,305 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
12 反爬虫概述(四):前后端都不合适的时候如何进行处理?
|
||||
你好,我是DS Hunter。
|
||||
|
||||
上一讲,我们谈到了无收益的前端是如何为反爬提供基础保障支持的。但是你应该是知道的,前端没有什么秘密可言。那么,那部分前端不能做的,后端不好做的,我们放在哪里处理呢?
|
||||
|
||||
是的,最终还是BFF扛下了所有。BFF天生就是为了这些事情而生的。
|
||||
|
||||
在当前的浪潮下,大家似乎将BFF与Node.js划了等号,事实上并非如此。BFF:Backend For Frontend,服务于前端的后端,仅仅是一种设计思路,只不过Node.js在当前环境下是最优解而已。实际上,很多公司都会有一个API层来进行服务转发,这一层就相当于BFF层,它未必是Node.js站点。
|
||||
|
||||
这一讲,我们就来看一下BFF的主要功能以及实现方式。在学习的过程中,我也希望你能理解BFF存在的真正价值。我们先从BFF形成的第一步:选型,开始了解吧。
|
||||
|
||||
BFF选型
|
||||
|
||||
关于BFF选型,理论上我们可以使用任何语言。但是实际上90%以上的公司,最终会选择Node.js。
|
||||
|
||||
Node.js:Express
|
||||
|
||||
Node.js可以承载常规http请求,并且因为与前端使用相同的编程语言:JavaScript,因此能很方便的让前端人员兼职掉BFF工作。这是常规公司选型的理由之一。对于反爬来说,我们有更进一步的选型原因:
|
||||
|
||||
|
||||
我们之前提到的加解密是成对出现的,客户端解密,BFF加密,出于方便测试的理由,使用JavaScript做为BFF语言,会十分方便。
|
||||
|
||||
反爬虫系统是一个高并发的非关键系统,其余语言需要额外引入支持,Node.js默认是异步的,天生为高并发而生。
|
||||
|
||||
JavaScript代码处理可能涉及AST转换, Node.js有足够多的工具可以支持。
|
||||
|
||||
|
||||
基于这些理由,Node.js几乎成了唯一解。但是,万事不是绝对的。对于部分公司来说,实在不能选择Node.js的时候,也可以被迫使用别的技术栈。
|
||||
|
||||
被迫选择其余技术栈的理由千差万别,但通常是历史原因或基建支持不足。但是,现实世界的架构也常常不是最优解。我这里的建议就是:妥协吧,编码不方便,可以通过增加人力来解决,这不是无解的问题。
|
||||
|
||||
主要功能:中转以及聚合
|
||||
|
||||
BFF的功能,往往是聚焦于网络请求的中转以及聚合。中转很简单,就是前端服务请求过来,BFF承接了请求,然后处理后转发给后端。而聚合,则是多个请求被合并,一次性请求后端,降低后端的QPS。别人用BFF,往往只是用于中转和聚合,而我们享受了BFF的好处,拿来做反爬。那么这里,我们就来讨论一下中转以及聚合部分的机器配置以及相应的反爬操作。
|
||||
|
||||
从BFF机器配置来看,我们为了承载高并发,就要增加资源来承载。但是增加哪方面的资源?是机器数,还是增加配置?这个取决于场景。
|
||||
|
||||
机器配置:网络负载分类
|
||||
|
||||
我们经常说高并发高负载,但是实际上业务上存在两种不同的负载方式:一种是请求量多,也就是链接数高。另一种是流量大,或者资源消耗多,也就是每秒的byte数多,或者需要的业务逻辑多。这两者的处理方式是不同的。当然也有业务是两者都多,这就没有什么取巧办法了。
|
||||
|
||||
针对链接数高,其实可以通过增加机器数来实现。简单的说,比如你使用1C2G的机器,顶住了网络流量。这个时候,链接数忽然增加到8倍,你是增加至8台1C2G的机器,还是替换成一台8C16G的机器呢?其实两者成本是一致的,但是我们还是会选择8台机器,因为更多的网卡意味着更多的负载。
|
||||
|
||||
但是是不是永远这样选择呢?也不一定。我们可以看一下第二种情况:流量大、资源消耗多。这种情况下,可能内存大的“一台8C16G”的机器就是首选了。
|
||||
|
||||
当然,事情还有反转的可能,如果系统对实时性要求很高,你可以承受频繁GC,但是不能承受长时间GC,那么可能大内存又不是首选了。这个在选型的时候要慎重考虑。
|
||||
|
||||
如果非要有一个结论的话,那么其实反爬虫系统大部分是对实时性有要求,所以低配置多机器数通常是首选。但是这并非绝对的,还是要看具体的需求来慎重选择。
|
||||
|
||||
具体操作:key与随机值
|
||||
|
||||
有了合适的机器,我们就可以考虑具体操作的问题了。我们从反爬验证的核心问题“key的生成”开始说起。
|
||||
|
||||
|
||||
key生成相关
|
||||
|
||||
|
||||
我们在09讲提到过,key生成逻辑并不复杂,并且无需存储,因此可以直接在BFF生成,不需要动用后端生成再用BFF转发。而且加密本身是一个计算密集型的需求,不是IO密集型,所以这个对CPU的消耗还是比较可观的。
|
||||
|
||||
但是,考虑到反爬是一个低ROI的项目,成本节约是重中之重。所以,我们来分析一下目前面临的问题:Node.js天生是为单CPU设计的,而Cluster本身只是充分利用了多核,并没有什么额外的优化。所以对于Docker部署的公司来说,可以把机器分散成多个一核的实例,这样可以充分降低成本。
|
||||
|
||||
这里有两个理由。第一,与其用不靠谱的Cluster来实现多核优化,还不如用成熟的Docker技术来隔离,反正总核数不变。第二,核数少的话,配置Docker的人可以使用一些边角料来凑,成本能大大降低。例如公司的k8s人员分配了一堆高配机器之后,还剩余一些机器没办法分配出去,由于我们的需求是单核,因此无论剩余什么边角料,都可以使用上,这个成本能低很多。
|
||||
|
||||
此外,考虑到BFF是一个集群,那么发布过程中,需要考虑key兼容的情况。
|
||||
|
||||
例如发布了50%的机器,那么50%机器用了新版的key生成与校验逻辑,另外50%还使用的是旧版,这里就会存在发布常见的交叉问题。要么发布过程中停掉反爬,要么在新校验逻辑里要兼容上一版。停掉反爬代价会比较大,而且很难进行线上观察测试。
|
||||
|
||||
因此我们的验证模块通常会对上一版做兼容。要知道,key生成并非一个频繁变更的需求,所以必要时可以通过多一次发布来解决这个问题。也就是一次发key的生成方式, 一次发key的验证方式。
|
||||
|
||||
|
||||
key验证相关
|
||||
|
||||
|
||||
key验证方法在09已经讲过了,这里不再赘述。今天我们主要论述的,是针对刚刚提到key验证中“多一次发布”的问题产生的相对应的key验证问题。
|
||||
|
||||
我们先看一下key验证的版本问题是怎么产生的。假设我们的key生成使用的是v1版本,验证使用的也是v1版本。那么,我们要将他们都变更为v2版本。由于发布途中的n台机器,只有1台发布完成了,那么如果用户请求key的时候访问了v2版本生成的key,然后取v1版本去验证key,毫无悬念,这个验证是不可能通过的。那么这个时候我们就需要进行线上版本兼容处理。
|
||||
|
||||
首先,发布的新版本应该支持所有前置版本的key生成以及验证逻辑,并且支持配置。例如,我们刚刚发布途中,1台机器支持v2的key生成与验证,n-1台支持v1的生成与验证,那么我们的配置应该是:生成key配置使用v1,验证key配置也使用v1。全部发布完毕之前,实际上线上一直使用的是v1版本。全部发布完毕之后,我们可以将一台机器的key生成调整为v2,而验证key的配置设置为同时支持v1与v2。
|
||||
|
||||
这样,线上部分用户使用v2版本的key,大部分用户使用v1的key。慢慢地,就可以逐渐灰度切换为v2版本key了。然后全部切换完毕,v1版本key消失,此时验证key版本设置为v2。我们就可以进行灰度的切换了。
|
||||
|
||||
整个过程会缓慢执行,同时,要时刻监控我们前面提到的误伤统计报表。这个报表是实时的,所以可以用来做发布监控,这也是他存在的最大意义。但是这里要注意一个细节:我们误伤检测的理论,是从价格页面带Cookie到订单页面,检测Cookie,假设没有Cookie,就认为没问题。这个在平时没有问题,但是在发布时要考虑下用户操作延时这点。
|
||||
|
||||
简单的说,用户从价格页到订单页是有一个延迟的,任何一个用户访问了价格,都要通过几分钟各种比较,才会真正下单,根据经验一般是5到15分钟不等(不过这个并非定值,每个公司应该不一样,可以在Cookie上加上时间戳,自己线上测试下符合自己业务的时间段),因此灰度变更的时间间隔不应该小于这个时间差,否则可能导致命名误伤了用户,但是误伤检测还没到,发布的时候误以为策略是安全的,最终因为变更过快,引发生产事故。
|
||||
|
||||
|
||||
随机值处理
|
||||
|
||||
|
||||
从刚刚的发布相关论述中,你会发现,我们通过集群实现了一个随机。实际上,由于集群本身是随机访问的,这里相当于有了一个天生的随机模块。所以我们可以使用集群本身直接做随机。这句话你可能不太理解,没关系,我们还是通过一个例子来讲解具体的操作方式。
|
||||
|
||||
举个例子,我们在09讲中提到过的随机放过。假设你想随机放过50%的爬虫,那么我们并不需要编写随机模块,对每次请求进行roll操作。实际上,通过集群进来的访问已经随机过了,他们被随机并且平均分配到了集群的每一台机器上。你只需要针对50%的机器,配置上“对于任何验证key的请求,不进行验证,直接判定为key正确”,就可以实现50%的随机放过了。
|
||||
|
||||
这样不仅降低了代码复杂度,避免出现随机不准的问题,还提升了效率。属于集群使用的小技巧了。当然,这种小技巧除了反爬,似乎也没有别的业务用得到了。
|
||||
|
||||
这里可以给你补充一点,那就是如果你需要比较特殊的随机值,例如你有10台机器,你需要的概率却是55%,这个需要变更5.5台机器,很难做到,你可以通过变更Nginx的weight来实现,详情可以参阅Nginx的官方文档。不过这样会导致负载不均衡,因此建议是用工整的随机值。如果不工整,可以向上向下取值到一个合适的值。
|
||||
|
||||
实现方式:自定义Node.js的engine
|
||||
|
||||
实际上,我们可以通过定制Express的Engine,创造一个新的扩展名来避免大量的切片,直接实现BFF中转以及聚合的复杂操作。
|
||||
|
||||
Express的Engine定制方法
|
||||
|
||||
我们都知道,Express支持自定义Engine。默认情况下,框架提供了一个非常好用的Engine。但是问题就是,他太好用了,一点也不混乱。而我们做反爬,就是要做混乱,让爬虫方摸不到头脑。因此,定制Engine是一个势在必行的事情。
|
||||
|
||||
关于Express如何编写自己的 Engine,可以查阅官方文档。我们这里主要讨论,哪些方面我们要变更。
|
||||
|
||||
|
||||
engine混淆
|
||||
|
||||
|
||||
Engine的混淆主要包括:变量名混淆,eval博弈,AST转换以及虚拟机。
|
||||
|
||||
这里,我主要用变量名混淆给你举例。至于其余的混淆方式大同小异,都是定制Engine,只是复杂度会提升不少。所以,我们先用稍简单些的变量名混淆理解基本原理。
|
||||
|
||||
我们假设,原来是如下的代码:
|
||||
|
||||
var a = 3;
|
||||
var b = 4;
|
||||
console.log(a-b);
|
||||
|
||||
|
||||
但是,我们希望给爬虫方展示的是这样的代码:
|
||||
|
||||
var $asbasdfewf = 3;
|
||||
var $asbasdfevf = 4;
|
||||
console.log($asbasdfewf - $asbasdfevf);
|
||||
|
||||
|
||||
明显可以看得出,虽然只有三行的demo,但是下文的阅读难度比上文复杂了不少。
|
||||
|
||||
但是我们不能容忍自己在写代码的时候,书写下面的代码。恶心的代码是给爬虫看的,不是给自己看的。那么我们如何处理呢?
|
||||
|
||||
我们可以定义一个engine。假设定制完毕后,我们的engine扩展名是as:代表anti-spider, 那么也许你的index.as文件可能看起来类似这样:
|
||||
|
||||
var $a = 3;
|
||||
var $b = 4;
|
||||
console.log($a-$b);
|
||||
|
||||
|
||||
然后,你的engine可能定制类似这样的代码:
|
||||
|
||||
// 遍历模版, 获取所有的变量名。
|
||||
// 可能是正则, 可能是AST, 看你喜欢, 以及实现难度
|
||||
// 设置到variables里。
|
||||
var variables = getAllVariables();
|
||||
// 根据所有的变量, 创建一个字典, 实现旧变量名与新变量名的一对一mapping。
|
||||
// 新变量名可以尽可能长, 并尽可能视觉上相似。 例如混用v和w, 1和l之类的。
|
||||
// 为了避免数字开头, 可以使用通用的开头, 例如$
|
||||
var dict = createVariableDictionary(variables);
|
||||
// 批量替换查找到的所有变量名。
|
||||
// 老规矩, 正则或者AST
|
||||
replaceAll(page, dict);
|
||||
|
||||
|
||||
|
||||
这样,我们就可以看到干净整洁的代码,而那些恶心的代码,就让爬虫一点点看去吧。-
|
||||
如果上面的代码看着迷惑,没关系,这说明你缺乏的是express定制engine的知识,而不是缺乏反爬虫知识。你先去跟着官网demo定制一个简单的engine看下流程,再回来看就能明白我们要干什么了。
|
||||
|
||||
其余的都是用类似的思路去做即可。定制engine虽然是个很非主流的功能,甚至很多人都觉得Express支持这个东西简直匪夷所思。但是对于反爬虫来说,这简直是神器。
|
||||
|
||||
|
||||
engine效率
|
||||
|
||||
|
||||
定制engine最需要注意的就是效率。
|
||||
|
||||
我们为了方便,很可能大量使用正则表达式对整个模版进行字符串扫描。这个复杂度至少是O(n)的。而我们又需要频繁扫描,加上不断的局部调整,可能导致CPU过高。众所周知,JavaScript的字符串操作性能堪忧。
|
||||
|
||||
因此,这里可以进行一些必要的提速操作。在迫不得已的情况下,甚至可以用其他语言来实现char数组操作,就像编译原理课上的作业一样,尽可能在较少的全字符串扫描中完成任务。这可能会很耗开发资源,但是绝对是值得的。还记得咱们在09讲中提到过的几乎无解的计算力进攻嘛?这样的改变可以在一定程度上缓解这样几近疯狂的进攻。
|
||||
|
||||
也就是说,你消耗的资源不能过高,否则将产生资源的不对等,爬虫消耗的资源远远低于你,你就会陷入被动。而如果你提升了效率,消耗的资源并不高,那么你就可以相对放心很多。
|
||||
|
||||
|
||||
engine切片
|
||||
|
||||
|
||||
切片主要是针对一些浏览器特征检测的。
|
||||
|
||||
我们假设你要检测location.href是否存在某个字符串(你的URL包含一个关键字,那么这里location.href就应该包含这个关键字),那么一定不要直接写:如果不包含就如何如何。这样被调试出来的概率太高了,对方只要查找一下if,就知道所有的判定在哪里了。那么这个代码应该怎么写呢?
|
||||
|
||||
如果你的某一步加密操作是+3,那么你的代码可以这样写:
|
||||
|
||||
var offset = 3*(+!!(location.href.indexOf(keyword)+1)
|
||||
|
||||
|
||||
|
||||
代码逻辑大概是:-
|
||||
-
|
||||
如果存在keyword,那么+1之后将得到一个大于0的数字。这个数字取反为false,再取反为true,再加个加号就是1了。然后用3来乘这个数字,就得到了正常的offset。-
|
||||
-
|
||||
如果没有找到,那么它是-1,-1+1得到0,两次取反为false,再用加号转为Number,是0,3*0还是0,这个offset就是0了。-
|
||||
-
|
||||
如果offset错了,那么会导致什么结果呢?会导致key解密错误,最终验证的时候,验证失败。-
|
||||
-
|
||||
但是,整个过程没有任何一个if,是不能直接查找搜索得到结果的。
|
||||
|
||||
|
||||
那么这个代码我们是直接写到解密里面吗?不是的,我们代码里会放3*1,1就是一个切片,会被替换成这段js判定,在不同条件下运行出不同的结果。
|
||||
|
||||
那么替换的动作,就要由Engine来执行了。同时,这个替换是随机的,也就是不同的切片与不同的切片代码来互相替换,实现代码的随机性。我们知道,随机出现的代码是最影响调试的。
|
||||
|
||||
当然,这个切片只是个思路,核心在于消除if判定,而不是全篇都是这样操作,要想各种办法来变通。如果千篇一律,对方只要搜索”+!!“这种关键字就可以找到你的切片了。万幸,js有大量的特性(bad parts),可以供我们试用。
|
||||
|
||||
Engine下的成对加解密
|
||||
|
||||
我们在10讲中提到了解密方法是逆排序的,那么这里就可以顺便看下做法了。简单的说,既然是逆序,那就是后进先出,也就是一个简单的栈操作。思路确定后,那么问题就简单了。
|
||||
|
||||
大体来说,代码如下:
|
||||
|
||||
// 首先我们从题库roll出来几各加解密的pair
|
||||
// 然后把他们临时保存一下
|
||||
var methods = rollMethods();
|
||||
// 我们设定一个
|
||||
var methodStack = [];
|
||||
// 这里要对methods进行遍历
|
||||
// 针对key进行加密, 每加密一次, 就在methodStack进行一次push操作
|
||||
// methods的每一个item应该是一个加解密pair, 加密方法当场用掉,
|
||||
// 解密方法是一个字符串, 留在栈里备用
|
||||
methods.forEach...
|
||||
|
||||
while(methodStack.length !== 0){
|
||||
// 这里则需要不断的popmethodStack了。
|
||||
// 然后推给engine, 让engine按顺序拼接解密方法
|
||||
// engine拿到解密方法, 进行字符串拼接, 切片注入
|
||||
// 以及其余的混淆, 然后加入通用模版, 得到浏览器端最终运行的js代码
|
||||
}
|
||||
|
||||
|
||||
这样,我们的解密method无需与加密method进行mapping,因为加密方法当场用掉了,解密方法拼接到js中了,两者都消费完了。所以不需要再mapping了。浏览器端解密完毕,就直接得到key。如果得不到,那就是解密失败,会被验证模块拦截掉。
|
||||
|
||||
附加价值:BFF集成与解耦
|
||||
|
||||
目前为止,BFF的反爬任务就基本上完成了。但是我们创建BFF不仅仅是替后端做脏活累活的,还需要有更多的价值。我们先从反爬的初心开始讲起。
|
||||
|
||||
后端保护
|
||||
|
||||
反爬虫的初心其实是防止后端收到大流量冲击。现在看来这反倒成了最低级别的需求了。不过我们还是不忘初心,看下BFF是如何保护后端的。
|
||||
|
||||
我们知道,真正能冲击后端的爬虫,其实反倒不是那些竞对爬虫,而是毕业生爬虫,他们在毕业季拼命爬取数据, 用来做毕业设计,写论文。而且他们没什么技巧,就是死命干。所以简单的规则封杀就可以操作掉。
|
||||
|
||||
这类封杀, 如果在SLB层不方便做,在BFF层可以轻易实现,本质就是一个规则过滤——而我们已经有规则引擎了。因此,触发规则之后,直接设置state为结束,流量就会被忽略掉。后端压力也就得到了降低。 而BFF本身也不用担心,因为在选型时选择了Node.js,应对高并发是天赋,受到的冲击极为有限。
|
||||
|
||||
当然,有些公司的BFF,我们提到过不是Node.js……因为一些特殊原因……这种还是死磕SLB去做规则吧。
|
||||
|
||||
前端熔断
|
||||
|
||||
除了保护后端,BFF也可以轻易做到前端的熔断。
|
||||
|
||||
我们的反爬验证,无非就是key的生成和key的验证,那么最彻底的熔断当然是不生成key也不验证key。但是有时候线上问题紧急,多个开关操作起来,会互相干扰。
|
||||
|
||||
所以,有时候也可以只操作验证key开关,简单的说,就是无论key错得多离谱,我们的规则引擎都默认设置为通过。
|
||||
|
||||
我们前面提到过随机放过的操作,可以在集群直接操作。实际上,你把概率设置为100%,所有集群都放过,那么也就等于熔断了。快速熔断,关键时刻可以救命,一定要做好。
|
||||
|
||||
超时处理
|
||||
|
||||
超时处理与熔断其实差不多,那么具体的实现逻辑是怎样的呢?
|
||||
|
||||
首先,生成key的时候,不能让用户等太久。如果超时了,那么就可以迅速生成一个指定的key,让他先走掉。固定key很难通过验证的,因此这个报警一定要快,因为误伤可能已经产生了。由于我们的误伤操作通常是操作价格,并不是拦截,因此会给予你一定的时间来处理。
|
||||
|
||||
此外,验证key也需要做超时处理。假设一个key验证较长时间还没验证完毕,那么不管哪里逻辑有问题,规则引擎直接给出“验证通过”的结果即可。一定要记住:反爬是一个非关键的业务,抓不到爬虫不可耻,引发生产问题才可耻。
|
||||
|
||||
此外还可以设置一些自动熔断的规则。注意,如果这些规则被爬虫抓到,他可能有意触发。所以,还是那句话:具体问题,具体分析。这个需要权衡以及尽可能隐蔽,不要被抓到规律。
|
||||
|
||||
小结
|
||||
|
||||
好了,最后我来给你总结一下。
|
||||
|
||||
今天这一讲,我们了解了BFF在反爬虫动作中的一系列问题。从选型开始,到实现反爬虫的详细动作,以及实现反爬虫功能的详细方式都做了详细的讲解。最后,我们也补充了BFF在集成和解耦上面的附加价值。详细的内容我也给你准备了一张脑图,你可以对照着来复习。
|
||||
|
||||
|
||||
|
||||
但是,这里我更想和你强调几个这一讲的重点,也是BFF在反爬虫这件事上最关键的几点:
|
||||
|
||||
|
||||
自定义Engine:BFF通过自定义Engine,来实现key的生成以及验证;
|
||||
通过集群设置随机值:使用weight定义机器权重,实现加权分流,并能过控制机器开关实现随机;
|
||||
BFF小技巧:通过自定义随机值来设置熔断、通过设置不验证实现熔断、通过超时处理来提升用户体验。
|
||||
|
||||
|
||||
那么,到这里为止,我们的理论课就告一段落。下一讲,我会带你从头到尾走一遍反爬虫的过程,认真观察这个战场的每个角落。
|
||||
|
||||
思考题
|
||||
|
||||
又到了愉快的思考题时间。 老规矩,你可以任选一个问题和我讨论。
|
||||
|
||||
|
||||
你们的公司出于各种原因,BFF没有选择Node.js技术栈。那么,你是硬着头皮在这种技术栈做反爬呢,还是想办法让BFF转Node.js呢?如果你认为不可能成功,那么理由是什么呢?
|
||||
Express的官方自定义Engine的demo里面,会频繁读文件。虽然Node.js是异步的,但是也顶不住没完没了的读硬盘啊。如何提升性能呢?
|
||||
集群实现随机,你精心配置,终于实现了79.4%。然后机器扩容,随机值又变了。那么,如何处理这个问题呢?
|
||||
|
||||
|
||||
期待你在评论区的分享,我会及时回复你。反爬无定式,我们一起探索。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
213
专栏/反爬虫兵法演绎20讲/13反爬虫基础理论:这是唯一一节严肃的纯理论课.md
Normal file
213
专栏/反爬虫兵法演绎20讲/13反爬虫基础理论:这是唯一一节严肃的纯理论课.md
Normal file
@ -0,0 +1,213 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
13 反爬虫基础理论:这是唯一一节严肃的纯理论课
|
||||
你好,我是DS Hunter。
|
||||
|
||||
前面12讲,我们讲完了反爬虫的所有操作,但是你可能会觉得,这样一攻一防的讲解在应用的时候会存在割裂感,实际工作中,还是摸不透反爬虫的整个流程。
|
||||
|
||||
那么今天,我就带你完整地走一遍反爬虫流程,从信息收集开始,到对爬虫的预估、线上测试,对工作需求的分析,最后,也会告诉你在流程中存在的风险点。
|
||||
|
||||
希望你能够通过今天的课程,理解那些反爬虫里严肃的纯理论知识。甚至,你可以把今天的课程当作反爬的标准流程手册。当然,我更希望你能通过今天的总结,了解反爬虫到底反的是什么。是爬虫,还是商业竞争?
|
||||
|
||||
在课程开始之前,我推荐你点开这一讲的音频,可以说,和课程的风格是完全的AB两面,至于如何不同,就等你点开来听了。
|
||||
|
||||
爬虫反爬虫基础理论
|
||||
|
||||
首先,我们回顾一下爬虫反爬虫的基础理论。我在上一讲提到过,当你不知道采用什么样的手段反爬的时候,回归初心,往往能够帮助你出奇制胜。
|
||||
|
||||
有的时候,你的反爬可能真的是因为竞对,也可能这就是一个因为技术界轮子太多,不得不另辟蹊径、完成目标的一个选择。你可以想想:
|
||||
|
||||
|
||||
一个阴霾的晚上,伸手不见五指,你和你的Leader,在一家小龙虾店聊工作。-
|
||||
-
|
||||
你的领导剥着小龙虾,对你说:“又一个双月要过去了,我们什么轮子也没造,下个月的目标恐怕不好写啊。”-
|
||||
-
|
||||
你思考了一下,和领导说:“领导,不如我们另辟蹊径,选一个非主流的方向,我们造个反爬虫的轮子如何?爬虫就是大家说的抓取啊,嚣张点,起个TCP链接直接干到对方服务器上,把数据都拉下来就行了,反爬虫就是,别人拉我们数据,我们就干他,让他敢这么嚣张。”
|
||||
|
||||
|
||||
那么,接下来我们在向上对齐的时候就需要有一个看起来官方一点的、正式的定义。我们来复习一下。
|
||||
|
||||
|
||||
爬虫:使用任何技术手段,批量获取网站信息的一种方式。关键在于批量。
|
||||
反爬虫:使用任何技术手段,阻止别人批量获取自己网站信息的一种方式。关键也在于批量。
|
||||
误伤:在反爬虫的过程中,错误地将普通用户识别为爬虫。误伤率高的反爬虫策略,效果再好也不能用。
|
||||
拦截:成功地阻止爬虫访问。这里会有拦截率的概念。通常来说,拦截率越高的反爬虫策略,误伤的可能性就越高。因此需要做个权衡。
|
||||
资源:机器成本与人力成本的总和。
|
||||
|
||||
|
||||
是的,这些定义完善又好理解。换句话说,我们常说的反爬虫要做的就是基于分布式平台下的数据加密保护。而且,在反爬虫开始前,我们一定要明确,那就是爬虫和反爬虫从来不计较一次两次的请求得失,甚至有意会放过对方来达到一些迷惑效果。
|
||||
|
||||
爬虫与反爬虫的博弈,是一种针对批量数据进行斗智斗勇的游戏,其中反爬虫需要在尽可能保持高拦截与低误伤率的要求下进行。这种博弈以资源消耗为战争手段,以商业优势为最终目标。
|
||||
|
||||
反爬虫信息收集与埋点理论
|
||||
|
||||
在明确了我们的最终目标之后,实际上,我们要做的第一件事就是收集信息了。信息收集是反爬虫的基石,完成了这一步,才能开始后续的所有操作。
|
||||
|
||||
反爬虫信息收集,指的是通过前端辅助,或者通过http请求信息,获取用户信息,用于后续分析判定的一种行为。该信息可能直接被加密上传,也可能被提取特征后上传。
|
||||
|
||||
反爬虫信息收集分类
|
||||
|
||||
这时候的你,已经明白信息收集的意义了。接下来咱们就来走一遍信息收集的过程。我们都知道,前后端都可以收集信息,那到底收集什么信息呢?
|
||||
|
||||
这里,我将反爬虫信息收集的类型分为三类:前端辅助信息、HTTP请求信息收集以及两者辅助同时收集。
|
||||
|
||||
针对第一类,我们主要的收集手段是使用js代码,提取浏览器特征或者业务特征。具体操作方式包括Canvas指纹以及DOM指纹,或者定制化特征提取。
|
||||
|
||||
针对第二类HTTP请求信息,我们可以通过分析HTTP Header信息来进行规则提取,并经由规则引擎分析,进行处理。
|
||||
|
||||
那么最后一类,可能相对复杂一些。我们需要通过查找js特征与HTTP Header的关联关系,并针对这种关系进行分析。例如客户端的location.href与Ajax的referrer,应该有匹配关系。这些关系都可以成为监测点。
|
||||
|
||||
反爬虫埋点分类
|
||||
|
||||
看起来,我们的信息收集已经完整、可行了。不过只收集信息,不能产生信息反哺回系统,似乎也不够闭环,也会出现被质疑的情况。那么不论出于什么样的目的,是打破质疑还是验证反爬效果,我们都需要收集埋点信息让整个反爬形成闭环。
|
||||
|
||||
反爬虫埋点,其实就是由反爬虫系统产生,可以用于验证反爬虫系统效果的数据。我们通常将这里的数据分为三类:
|
||||
|
||||
第一类,经由反爬虫系统分析后得出的“是否为爬虫”标记。-
|
||||
第二类,爬虫的特征,如类型,来源,数量,等等。-
|
||||
第三类,测试策略的线上检测效果数据。
|
||||
|
||||
当然,根据埋点收集方式,埋点又可以分为前端埋点与后端埋点,前端埋点由前端进行收集,后端埋点由后端独立进行收集。
|
||||
|
||||
通常来说,“是否为爬虫”标记,在后端可以独立进行收集,尽可能不要过前端,因为前端没有秘密,过前端等于告诉爬虫自己是否中招。而第二类爬虫特征的采集,不关注采集途径。不过如果来自前端,则需要适当加密。测试策略线上检测效果,我们一会谈到“反爬虫线上策略测试理论”的时候,会详细展开。
|
||||
|
||||
爬虫占比预估理论
|
||||
|
||||
接下来我们面对的问题,就是给拦截的成果定性定量了。你要知道,反爬基本是在明处的,而爬虫在暗处,如果我们也不知道自己拦截了多少爬虫,这样看起来一拍脑袋就决定了的规划送上去,要直接被拍死的就是自己了。
|
||||
|
||||
所以,我们需要一个可以定量衡量的指标。
|
||||
|
||||
反爬虫的衡量指标,主要在于拦截率以及误伤率。这两点都需要预估线上爬虫量,才能进行估算。这里,给你提供两个公式。
|
||||
|
||||
拦截率=拦截掉的爬虫/线上爬虫总数。
|
||||
|
||||
拦截掉的爬虫等于:拦截爬虫量-误伤量。
|
||||
|
||||
其中,误伤量可以通过误伤检测来计算。在这一讲最后“反爬虫误伤监测方法”会展开说明,而
|
||||
|
||||
线上爬虫总数需要通过爬虫占比来预估。
|
||||
|
||||
爬虫占比=爬虫量/总访问量
|
||||
|
||||
事实上,这个比例是持续变更的,因此不是一个固定值。所以,在工作交流中,我们也可以用“爬虫量”来代替“爬虫占比”。这里,我也会给你提供两个计算爬虫量的方法。
|
||||
|
||||
基本公理:转化率不变原则
|
||||
|
||||
第一个方法,利用的是转化率不变的原则。
|
||||
|
||||
我们都知道,转化率=用户下单量/总UV。而转化率不变,其实是由于商品转化率取决于商品品质,用户画像等恒定不变的特征。那么,在这些恒定特征不变的情况下,我们可以认定,转化率在单日内不发生改变。
|
||||
|
||||
因此,我们可以得出一个推论:订单=访问量*转化率。因此,访问量=订单/转化率。如果转化率不变,那么订单曲线经过一个合适的乘法加权,订单曲线应该与流量曲线重合。如果两者不重合,那么差值就是爬虫量。
|
||||
|
||||
推论:爬虫流量周期理论
|
||||
|
||||
第二个方法,是从我们做爬虫的时候会“周期性的用JOB去抓取数据”这件事中提炼出来的方法。你会发现,这样周期性的抓取,会导致流量上存在周期性的爬虫流量。
|
||||
|
||||
用一句话来概括爬虫流量周期理论的话,那就是,如果订单曲线加权后与流量曲线做差,得到的曲线依然有周期性的差值,那么这个差值就是周期性的爬虫。可以直接刨除。
|
||||
|
||||
上述讲到的两个理论,虽然不能精准算出爬虫的占比,但是经过一些预估以及计算,当加权订单曲线可以与流量曲线重合时,就可以认为爬虫已经几乎被排除光了。那么,排除掉的那些流量,就是预估的当天爬虫量。
|
||||
|
||||
最后,我也给你提供一个取巧的方案:反爬虫的效果,取决于排除掉爬虫后的流量曲线,与加权订单的重合度。重合度越高,效果越好。这样,我们也可以不计算爬虫量,直接评估反爬虫效果。
|
||||
|
||||
反爬虫测试理论
|
||||
|
||||
在信息收集、占比预估的部分准备结束之后,我们就可以准备测试了。反爬虫策略直接上线风险极高,同时,我们还要联动测试团队,不能给他们拖后腿的理由。
|
||||
|
||||
线下测试理论
|
||||
|
||||
我们都知道,反爬虫的代码有两部分,一部分是策略代码,一部分是框架代码。策略代码千变万化,难以穷尽,线上场景又十分复杂,因此,不适合线下测试。而框架代码不同,它本身是不变的,因此可以在线下进行测试,完善后再上线,降低上线风险。
|
||||
|
||||
所以,反爬虫线下测试,其实就是在上线前,使用测试环境,对反爬虫不变的框架代码,例如engine、规则引擎等等,进行详尽的测试,保证研发质量,降低上线风险。
|
||||
|
||||
线上测试理论
|
||||
|
||||
那么,需要线上测试的策略代码呢?碰到测试环境无法模拟详尽的情况,是不是需要进行线上测试?但是,线上测试本身又存在风险,因此我们需要寻找安全的线上测试方法。
|
||||
|
||||
线上策略测试理论
|
||||
|
||||
通常,反爬虫的策略提出时,他的安全性是存疑的。在线上运行一段时间后,如果还没出问题,那么可以认为对用户无伤害。但是如果存在问题,发现的时候,伤害已经造成,不能挽回。因此,我们可以借鉴青霉素皮试的方案,开启小流量尝试对用户进行伤害,这样可以在伤害最小的时候得出策略安全与否的结论。
|
||||
|
||||
然而,小流量的伤害依然可能是不可控的。我们可以再借鉴下疫苗的思路,进行假装拦截,看是否有问题。如果没问题,就让策略上线,成为“抗体”。
|
||||
|
||||
具体做法有四个步骤。首先,针对价格请求,除了线上策略外,我们可以额外增加测试策略A。接着,测试策略A本身如果鉴定请求为爬虫,不进行拦截,写入Cookie证明这是爬虫。但是注意要与线上的Cookie错开,避免无法拆分。再之后,我们可以在误伤检测看板观察误伤情况。由于这是测试策略,可以长时间观察,证明是否有害。最后,观察结束后可以将策略标记为“无害”,并下线测试策略。后续随时可以真正上线。
|
||||
|
||||
从刚才的四步中,你应该也可以明白了,反爬线上策略测试,指的是对线上流量进行模拟拦截,通过长时间观察,验证策略安全性的一种测试方法。这样,我们也就算找到了安全的线上测试方法。
|
||||
|
||||
线上熔断测试理论
|
||||
|
||||
最后,万一反爬虫真的出事了,我们也可以选择熔断。这个熔断的测试,其实就是:针对反爬虫的框架代码进行彻底关闭以及自动关闭功能的测试。我们的目标,永远是保护生产环境。
|
||||
|
||||
我们永远要记得,熔断并不是什么丢人的事情。反爬虫是一个低ROI的非关键需求,又容易出事。熔断,其实是属于牺牲自己,保护生产。
|
||||
|
||||
不过这里要注意的是,熔断本身也可能会引发新的故障,那就会导致额外的追责,不利于进一步发展反爬虫团队。新故障的解决方案,我们会在《14讲|低耦合》中详细讲解。
|
||||
|
||||
反爬虫立项分析理论
|
||||
|
||||
完成了信息收集、定量分析以及测试之后,我们就可以准备立项了。这里,我们通常会针对反爬虫低收益、高风险的特殊情况逐一分析。
|
||||
|
||||
需求与收益
|
||||
|
||||
反爬虫的需求分析,有极强的技术倾向,普通产品经常力不从心,甚至可能会拖后腿。因此,我更推荐由技术转行的反爬虫产品经理,而不是直接招聘。
|
||||
|
||||
反爬虫的需求分析,包括一次性需求分析以及持续性需求分析。一次性需求分析,通常定制化程度较高,可能产品突发奇想要做点什么,就成了反爬组的任务之一了。而持续性需求分析,包括爬虫进化追踪、数据变更、埋点检测、竞对监测等等,属于基础的监测。
|
||||
|
||||
至于收益分析,算下ROI就可以了。但是要注意,反爬虫是低收益项目,因此收益分析很关键。所以,如果真的需要分析收益,我们可以从信息保护,商业优势,竞对压制以及竞对爬虫资源消耗等方面切入。这些别人眼里的偏门,才是我们的价值所在。
|
||||
|
||||
反爬虫风险
|
||||
|
||||
立项的问题解决之后,我们就要考虑风险控制了。如果说反爬虫的收益分析主要用于项目组能生存下来,那么反爬虫的风险控制主要就是让自己能够不死。
|
||||
|
||||
反爬虫的风险点通常在于伤害用户体验、降低系统稳定性以及商誉PR风险等等。
|
||||
|
||||
针对伤害用户体验以及降低系统稳定性两点,我们都可以认为是系统问题。这里,我们通常有五种解决方法。
|
||||
|
||||
首先,我们可以增加小流量测试时间,因为小流量意味着小的伤害,可以用较长的时间,逐渐在不损伤用户的前提下发现问题,避免造成大的事故。同时,我们还可以使用静默测试,也就是只检测不拦截,类似战争演习,不真正造成损伤但是达到练兵的效果。第三点,我们也可以针对VIP用户,增加白名单机制。毕竟误伤了谁都不能误伤我们的VIP用户。那么针对短期、重要用户,我们也可以增加快速洗白逻辑,这也是我们的第四个方法。最后,我们甚至可以再增加快速熔断机制以及快速关闭机制,选择暂时放弃反爬。
|
||||
|
||||
至于商誉PR的风险,我们要么甩锅给技术、要么甩锅给竞对。当然了,推来推去也不是件什么得意的事,最关键的还是要增加全面日志,避免发生问题难以重现。
|
||||
|
||||
最后,如果真出了大问题,那应该就是大量误伤了用户,也就是将线上用户错误地识别成了爬虫。那么,怎么才能发现出了误伤的问题呢?我们通常选择在用户访问流的上游进行反爬测试,并针对爬虫进行标记,然后在下游进行标记检测的方法来检测误伤。理论上说,因为标记的都是爬虫,因此下游不可能读取到标记,一旦读取到,就是反爬虫误伤。
|
||||
|
||||
而出现了误伤之后,我们也可以增加静默测试时间来补救。在静默测试规则转为正式规则的时候,也一定要进行长时间的观察,同时要设置快速回退机制,保证在发布有问题的时候,能够退回到没发之前的状态。
|
||||
|
||||
小结
|
||||
|
||||
现在,我们已经走完了整个反爬流程。我在这里也给你准备了一张反爬虫流程图。在你不知道要采取什么样的措施或动作的时候,希望它可以给你提示。
|
||||
|
||||
|
||||
|
||||
在开始反爬之前,我们做的就是明确反爬的目的,注意,我们不是一味地拦截,我们也没有机器人洁癖。反爬虫要做的核心,是找到那些ROI不高的账号。
|
||||
|
||||
所以在前期,我们需要收集不少的信息作为后续动作的参考。同时,我们也需要去评估整个反爬虫的效果。效果的重点不在于数量,而在于商业上的胜利。在反爬虫系统正式上线前,我们也需要通过一系列的线上、线下测试。最后,基于反爬的特殊性,我们更需要明确这项工作的收益点,同时将风险降到最低。
|
||||
|
||||
思考题
|
||||
|
||||
作为理论与实践案例篇的最后一讲,今天的思考题还是有些不同的。
|
||||
|
||||
不知道你还能不能想起来在这一讲开始的时候我给你描述的情境。想象一下,如果这上面的所有理论梳理,都是你在给领导讲述下个月的可行动作呢?现在,你的领导应该已经忍不住哈哈大笑了吧——好像自己下个双月的所有规划已经写好,可以划水了。
|
||||
|
||||
这个时候,你们所在的小龙虾摊位的老板也走过来,又上了一盘小龙虾,忍不住问道,“二位是做互联网的吧?今天是不是谈了什么非常开心的事情?”
|
||||
|
||||
也许,你会不由得大惊,问道:“老板你怎么知道的,你偷听了我们的全部谈话么?这个规划我们还没写,你可不能透露出去啊,不然没准明天就成别人的规划了,”
|
||||
|
||||
老板笑了笑:“放心吧,没怎么听,只是感觉你们刚开始愁眉苦脸,不说人话,我就感觉你们应该是做互联网的。然后谈着谈着慢慢开始正常讲话了,谈开心了,就忍不住暴露本性说起了人话,我在这修罗城也卖了三十多年的小龙虾了,不说人话的互联网人都会堕落到这里来,只要说上几句人话,就能逃脱苦海,回归正常生活,然而我这生意是越做越红火,流量也是越来越大,我在小龙虾里也对配料进行了AB测试,看起来你们吃的这个版本的配方,是效果最好的啊!你们抬头看看,今天的月色美不美。”
|
||||
|
||||
你忍不住抬起头来,看了看天上的圆月,忍不住一阵头晕,忽然感觉空间扭曲,时间混乱,一眨眼,自己居然拿着手机在听极客时间,耳边又传出了熟悉的声音:
|
||||
|
||||
“你好,我是DS Hunter,刚刚就是理论课的全部内容,真的十分枯燥,希望你没有听睡着。下面是愉快的思考题时间:”
|
||||
|
||||
|
||||
吃小龙虾时的雾霾天,反映了你的什么心理活动?
|
||||
伸手不见五指的夜晚,却能看到圆月,作者想通过这样强烈的反差表达什么思想?
|
||||
小龙虾的配料进行AB测试,需要进行AA校验吗?
|
||||
|
||||
|
||||
期待你的不正经回复,我会在评论区与你们愉快地进行更不正经的互动。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
203
专栏/反爬虫兵法演绎20讲/14低耦合:如何快速下线反爬虫系统?.md
Normal file
203
专栏/反爬虫兵法演绎20讲/14低耦合:如何快速下线反爬虫系统?.md
Normal file
@ -0,0 +1,203 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
14 低耦合:如何快速下线反爬虫系统?
|
||||
你好,我是DS Hunter,反爬虫专家。又见面了。
|
||||
|
||||
前面我们已经详细讲完了反爬虫几乎全部的理论基础,现在我们进入实战看看如何应对真正的爬虫。
|
||||
|
||||
由于前面进行了大量的烧脑学习,相信你已经有些疲惫了,我们实战首先找一个轻松的话题:如何快速下线反爬虫系统?
|
||||
|
||||
反爬虫需求分析
|
||||
|
||||
有同学可能会说:老师你是不是讲错了,我们是来学习如何上线一个反爬虫系统的,为什么这里你说的是下线?
|
||||
|
||||
没错,这里我们要讨论的就是如何下线反爬虫系统。原因其实很简单,你可以先想一想,反爬虫需求是永远存在的吗?
|
||||
|
||||
很明显,不是的。反爬虫需求来源于爬虫,而爬虫来源于竞对,你有竞对,才有反爬虫需求。
|
||||
|
||||
但是,竞对是永远存在的吗?并不是,竞对随时可能消失,甚至被收购。到时候,你的反爬系统将成为系统的累赘,等你离职之后,永远也没有人能把他剥离出去,永远影响着公司的业务。此外,当你变更了规则之后,新的规则如果不适用之前的代码,这些代码还删得掉吗?
|
||||
|
||||
因此,降低反爬虫系统的入侵性,减少与业务代码的耦合,是反爬虫代码的重中之重。而如果你只知道如何上线,不知道如何下线,那么你的反爬虫项目很可能走不远,后人也无法接手。
|
||||
|
||||
既然现在确定了反爬虫系统需要随时被摘除,那么它的设计就可以主要考虑如下两种方式:依赖注入和代理。我们看一个常规的网络请求:
|
||||
|
||||
|
||||
|
||||
可以看到,我们在右侧直接加了一个规则引擎的模块,用于进行反爬虫的校验。那么,如果这个模块需要随时可以被下掉,他就要做成弱依赖。
|
||||
|
||||
例如,和反爬SDK耦合,作为一个依赖注入到应用层与业务层之间。通过这样的熔断方式,甚至可以秒级下线反爬虫——你只需要无脑下线规则引擎即可。然后再慢慢摘除后遗症(规则引擎我会在接下来的第15课给你详细讲解)。
|
||||
|
||||
而如果是和SLB耦合,那么就是走代理,让代理托管请求,随时取消代理逻辑即可。
|
||||
|
||||
下面我会详细说一下依赖注入系统的设计模式。至于代理模式,就先不展开说了。因为这个就是把所有逻辑做在SLB,你可以自己试着去实现。这两者没有明确的优劣之分,只是不同人有不同的习惯而已。
|
||||
|
||||
实现方式:依赖注入
|
||||
|
||||
依赖注入设计的大致思路是什么呢?
|
||||
|
||||
首先,你要确定你的系统是什么语言的,然后在里面做一个SDK。接着,再创建一个任意语言的规则引擎,来进行规则检测。最后将两者连接,让SDK调用自己的规则引擎。如果规则引擎不返回任何判定结果,那么直接按不是爬虫处理。
|
||||
|
||||
确定了设计思路之后,咱们就看一下具体的模块设计吧。
|
||||
|
||||
我们假设你的站点是Node.js的。(因为前文提到过,一般都是BFF扛下了所有,而大部分的BFF都是Node.js。) 因此同理,下面整个讲的都是Web反爬虫,而不是App。不过,你也可以想一想类似的实现方式。
|
||||
|
||||
我们的SDK分为以下部分:
|
||||
|
||||
|
||||
|
||||
这三个模块一旦建立,我们依赖注入模式的反爬虫SDK系统也就算完成了。下面,我们逐个讨论一下每个模块的建立方式。
|
||||
|
||||
数据采集模块
|
||||
|
||||
我们先来看数据采集模块。这个数据采集模块就是我们常用的埋点模块,主要用来采集线上用户信息,便于后续做用户特征分析。
|
||||
|
||||
考虑到线上主服务系统压力问题,数据采集通常不放在主服务器上。一定要时刻记住这一点: 反爬虫虽然是很重要的一个系统,但是,它不是核心系统,它挂了就挂了,千万不能影响用户正常使用主流程。
|
||||
|
||||
因此,一般数据采集会单独建站点来进行采集。这个站点对性能、稳定性各方面都没有什么要求,只要能跑就行。也就是说,在申请资源的时候,不需要申请昂贵的高可用性资源,只需要用最平凡的机器即可,这样可以最大程度地降低成本。成本是反爬虫的一个核心概念,绝对不能忘记,否则很容易失去老板的支持。
|
||||
|
||||
好了,既然明确了数据采集模块的核心,接下来我就说说这个核心面临的两大压力吧。采集系统的压力通常来自两块,网络并发和存储压力。我们要在低成本下完成这两样。
|
||||
|
||||
为什么这个低优先级的东西会产生高并发?
|
||||
|
||||
我们都知道,用户请求页面,请求是有限的。但是如果要进行用户信息统计,这个需求很容易膨胀,到最后根本不知道自己要统计多少信息,最终的结果就是并发非常高。所以,即使你的主系统不是高并发的,这个采集系统也可能被迫成为一个高并发的系统。
|
||||
|
||||
高并发系统已经成为八股文问题了,甚至连校招生都了如指掌了,这里就不赘述了。但是要注意的是,我们一直在强调成本。高并发有很多为了保证稳定性而付出的高成本,这些都可以舍去。我们要用稳定性换成本。
|
||||
|
||||
而对于存储压力这个问题,可以求助公司日志系统的人,他们有专业的处理方式,毕竟这个时代,大数据已经不再是一个遥不可及的技术了。还是一样的道理,提需求的时候,首先要强调,我们对可靠性没有要求,只要最后能查就行,无需实时,无需可靠,这些都可以舍去,可用就行,否则你的ROI很容易算不过来。
|
||||
|
||||
所以你会发现,高并发和大数据,两大难题都摆在你面前的时候,千万不要自己去硬着头皮处理,一定要学会使用其余团队的资源,让专业的人替你来处理这些琐事。你的核心竞争力应该是和爬虫对抗。
|
||||
|
||||
最终你就得到了一个:可熔断,非关键,支持高并发,高存储,低成本的集群。
|
||||
|
||||
你可能会说:这不科学啊,我什么都要,结果还什么都得到了,这似乎违背我们做软件的经验。
|
||||
|
||||
没错,并不是没有失去什么。仔细回忆下前面的设计,你就会发现,我们失去的是:稳定性。也就是说,这个系统在集合了所有的优点之后,还能低成本,主要就是用稳定性换的。不过回头想想,我们刚刚达成了共识——反爬不是一个核心功能,那么就好理解了,这样的代价绝对是超值的。
|
||||
|
||||
规则模块
|
||||
|
||||
接下来就看规则模块吧。规则模块的逻辑来源于规则引擎。这里我们主要讨论接入问题。至于低耦合的问题,我们则通过快速下线来实现。
|
||||
|
||||
|
||||
定位的影响
|
||||
|
||||
|
||||
不过在此之前,你还要额外考虑一个定位问题:你在公司的定位,也就是权限,是什么样子的。是只有反爬归你、业务需要和你合作接入反爬,还是业务也归你?这两种情况,接入方向会截然不同。
|
||||
|
||||
如果你是反爬方也是业务方,那就是自己开发、自己接入,没有沟通成本,无需跨团队沟通、说服别人,压力会小很多。
|
||||
|
||||
而只有反爬虫归你的时候,对于业务方来说,接入反爬,是一个纯成本消耗,没有任何收益。前面我们提到过,反爬不等于安全。接入安全,对于业务方来说,是稳赚的,即使安全最终没有起作用,也有人帮他背锅了,业务会开开心心地接入。 但是反爬不一样,很多公司的反爬组并不承诺拦截所有爬虫,甚至还会勾结业务方放过一些爬虫来达到战略目的(前面提到的随机放过)。
|
||||
|
||||
举个简单的例子,你在一个地方部署警察,维持治安,这个地方会很开心的配合。但是如果你部署的是一个特种部队,或者间谍机构,每天神出鬼没,地方也看不出他们在干嘛,甚至可能还要出成本养护,没准出事了,出于保密需求还要提防为这个特种部队背锅,那么其他人一定会怀疑你的。因此,这个行为对于业务方来说就是一个无收益的行为了,他们必然全力阻挠。
|
||||
|
||||
所以,如果你本身就是业务方负责人,你可以用行政压力直接命令下去。但是如果你只是反爬组负责人,那么你需要做的就是降低业务方的接入成本,不要耗光他们的耐心,否则他们会给出各种不接入反爬的借口。
|
||||
|
||||
|
||||
注入的接入方式
|
||||
|
||||
|
||||
一个最简单的降低成本的方式,就是SDK处使用注入的方式来进行接入,对业务方无感。举个例子,业务方引入一个Maven包,或者npm包,之后就什么也不用做了,这样是理想状况。实际上这可能吗?这并不现实。我们看下前面几讲提过的反爬链路。
|
||||
|
||||
第一,用户发起关键服务请求;第二,拦截该请求,转发一个规则引擎的请求,进行规则校验;第三,规则引擎生成token,带到关键服务请求去,关键服务请求会进行验证,并给出处理。
|
||||
|
||||
这个流程走下来你会发现处处有“拦截”,到处都有改代码, 那么如何能无感的进行这个操作呢?
|
||||
|
||||
我的建议是,可以考虑如何拦截用户在客户端发起的请求。
|
||||
|
||||
我们知道,客户端请求无非就是走Ajax,自下而上一共有这么几层: XMLHttpRequest,fetch,封装Ajax请求的库,比如jQuery、axios,或者各种框架等等。拦截越靠上层,越不容易出问题,但是范围越小。同理,拦截越靠底层,越容易出问题,但是漏网之鱼越少。
|
||||
|
||||
我们以难度最高的最底层XMLHttpRequest为例。
|
||||
|
||||
XMLHttpRequest最终会走send方法,那么只需重写XMLHttpRequest.prototype.send即可。
|
||||
|
||||
整体的思路是:用户要请求的服务地址,经过检测,发现在关键地址列表里,那么在prototype里直接拦截掉,改为调用规则引擎,同时存下原有的URL。接下来,在规则引擎得到必要的token之后,再调用原有的服务,带token过去即可。(token验证在下一个验证模块会讲。)
|
||||
|
||||
这样,我们就实现了拦截关键服务,并且可以定制化——毕竟send方法归你了,你可以随时添加删除你的filter。
|
||||
|
||||
大概代码逻辑如下:
|
||||
|
||||
const send = XMLHttpRequest.prototype.send;
|
||||
const open = XMLHttpRequest.prototype.open;
|
||||
XMLHttpRequest.prototype.send = function(...args){
|
||||
try{
|
||||
// 对白名单进行处理。
|
||||
// 注意递归调用规避
|
||||
}
|
||||
finally{
|
||||
// 这里要避免报错,所以也可以备份原有的args, 避免这里已经被修改。
|
||||
send.call(this, ...args);
|
||||
}
|
||||
}
|
||||
XMLHttpRequest.prototype.open = function(...args){
|
||||
try{
|
||||
// 对白名单进行处理。
|
||||
// 注意递归调用规避
|
||||
}
|
||||
finally{
|
||||
// 这里要避免报错,所以也可以备份原有的args, 避免这里已经被修改。
|
||||
oepn.call(this, ...args);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
相信你也看出来了,这样做的优缺点都是非常明显的。缺点显而易见,你动了最底层的XHR逻辑, 出问题的概率是最大的。 但是优点也十分明确, 只要是使用XHR的库,都被处理了。
|
||||
|
||||
而且,回到我开头说的:这个办法是不是下线最快的?当然是。如果你们的竞对被收购了,你只需要在filter里面去掉对应的服务地址,就下线了对应的反爬。如果你们收购了所有的竞争对手垄断了市场——当然垄断是不对的,不过这个不在我们的讨论范围内——这个时候,你只需要移除自己的JS-SDK,所有的XHR没人拦截,自然就回归了正常。因此这个代价是值得的。
|
||||
|
||||
但是这里还有一个问题,那就是,反爬是一个非关键功能,如果不小心报错了,你动的又是XHR逻辑本身,是不是就意味着整个系统崩溃了?这明显是不能接受的。
|
||||
|
||||
因此,你的js代码必须非常严格,只要异常一旦出现,就直接切断自己,不要影响主流程。要知道,反爬是随时可以被放弃的,但是主流程不行,主流程是业务核心,是公司的命脉。反爬今天做不了可以明天,明天不行可以后天,总有成功的时候。反爬系统逼急了就自杀,并不是什么丢人的事情。
|
||||
|
||||
验证模块
|
||||
|
||||
最后这个模块是验证模块。验证模块就是整个反爬的核心了。前面做了这么多的准备工作,就是为了最后的验证。 这里,我们同样采用快速下线的方法来实现低耦合。
|
||||
|
||||
这里我还是要提出相同的问题:你是公司的业务方负责人,还是单纯只负责反爬本身?
|
||||
|
||||
爬虫验证是误伤的最大来源,如果一个普通用户被误伤了,那么90%以上的概率是验证模块出了问题。最终这个责任是定在业务负责人身上的——甚至有的公司反爬组都是保密组,压根在定责系统里查不到。也就是说,业务方有义务,但是没有权利,这个心理落差是任何人都不能承受的。
|
||||
|
||||
所以如果你自己就是业务方,自己作死自己承担,没有人会说什么。如果是自己作死、业务承担,那么业务压力会很大,他们迟早会站在你的对立面。那么,为了降低这样的误伤,我们可能在验证时采取一些特殊措施。这些措施在你误伤了用户的情况下,还可以勉强挽回一些损失。
|
||||
|
||||
例如,尽可能不拦截用户,而是给予虚假的价格。此外,有意放掉一部分用户,降低误伤概率。你可能会想:放掉用户也会放掉爬虫,这不是为了刷KPI而作弊吗? 非也非也,一定要记住一句话:反爬从来就不是安全,也不是风控。
|
||||
|
||||
试想一下这样的场景:假设你只拦截90%的爬虫,那么爬虫工程师有9成的概率刷不到你的反爬请求,他在调试的时候就会自信满满,误以为自己没有命中反爬虫。可是等他的爬虫真的上了线之后,他的系统一定有10%的概率拿到有问题的数据。那么,他的业务方一定不能容忍这种行为。只要有一条数据是错的,被抽到,整批数据业务方都不敢用。
|
||||
|
||||
那么他有多大的概率发现自己中反爬了呢?很遗憾,最大值也就只有10%。这意味着9成的情况下,他会被你玩的团团转。 那么,如果你放掉99%的爬虫呢?他将只有1%的概率发现自己实际上中爬虫了。这个比直接拦截更加恐怖,而且误伤率降低很多。
|
||||
|
||||
同时,这种放过爬虫的行为,还可以延伸出多种放过方式,例如根据IP、区域,以及一些用户维度,设置不同的放过比例,可以玩的花样非常多。
|
||||
|
||||
实现方式:代理
|
||||
|
||||
这样,三个模块就都讲完了。我们回头看一下,这三个模块构成了你的反爬SDK, 使用方式其实是一种依赖注入的思想。系统并不包含反爬代码,但是我们的SDK通过外部调用的方式把他们都接入了进去。 那么回到开头,除了依赖注入,我们还提了一种方式叫代理对不对?
|
||||
|
||||
这里的代理,其实就是你前端的SLB直接做代理。与依赖注入的做法一样,你也需要一个系统来做一切。但是在SLB一层,会封装价格请求,拦截处理成你的请求。这样做的好处也是一样, 如果有一天发现反爬系统不需要了,那么你只要下线SLB上的功能即可。 两种方式都可以,取决于在你的公司内, 哪个更容易部署。 篇幅限制就不展开了。
|
||||
|
||||
小结
|
||||
|
||||
好了,至今为止,如何低耦合地接入一个反爬系统我们就讲完了。
|
||||
|
||||
这一讲我们主要讲了如何使用依赖注入的方式来将反爬系统注入到系统中去,实现快速的下线。依赖注入的系统分为三个模块,数据采集模块、规则模块以及验证模块。当然,数据模块天生就不耦合,而在规则和验证模块,我们选择用快速下线的方式来降低耦合。最后,你也可以自己想想代理这个方式的实现过程。
|
||||
|
||||
我想,你应该脑子里就只记住了一个词:下线,或者说低耦合。 因为我们不断地在强调这个事情。如果说记得更多,那应该还记住了一个词:成本。低耦合和成本,是反爬虫的重中之重。 哪怕是牺牲拦截率,也在所不惜。这点一定要时刻记在心里。
|
||||
|
||||
那么,我们接入的系统,是如何识别爬虫的呢?我们很快进入下一讲:规则引擎。
|
||||
|
||||
思考题
|
||||
|
||||
最后的最后,又到了愉快的思考题时间。还是老规矩,三选一。
|
||||
|
||||
|
||||
如果在线上,你拦截了你的老板,你的老板大发雷霆,这个时候需要你迅速给出解决方案,根据今天的知识思考一下,你会如何处理呢?
|
||||
为什么说数据收集是天生无耦合的?他不在系统中吗?
|
||||
虽然我在文章中说了,依赖注入和代理这两者,是没有明确的优劣之分的,但是,真要比较起来,他们的优缺点分别是什么呢?
|
||||
|
||||
|
||||
可以把想法写在评论区,让我看看你的奇思妙想。 反爬无定势,也许我也可以在评论区学习到更多的思路!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
243
专栏/反爬虫兵法演绎20讲/15规则引擎:如何快速响应突发的爬虫需求?.md
Normal file
243
专栏/反爬虫兵法演绎20讲/15规则引擎:如何快速响应突发的爬虫需求?.md
Normal file
@ -0,0 +1,243 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
15 规则引擎:如何快速响应突发的爬虫需求?
|
||||
你好,我是DS Hunter,反爬虫专家,又见面了。
|
||||
|
||||
我们前面很多地方都提到了规则引擎。这里再重申一下规则的定义:
|
||||
|
||||
|
||||
规则(rule):使用任何技术手段,对线上请求特征按照指定的条件(condition)或方法(callback)进行检测验证,并执行指定操作的过程。在部分系统里,这个也被称为过滤器(filter)。
|
||||
|
||||
|
||||
如果说低耦合是为了保护你不死,那么规则引擎就是你的战斗利器,相当于将军的兵器,来鉴别爬虫。严格来说,整个反爬系统所有的操作,最终都是各种形态的规则引擎。
|
||||
|
||||
这里我们把规则引擎分为后端和前端两部分来讨论。为了使论述更佳清晰易懂,这里我们将BFF的规则引擎认为是前端的部分。
|
||||
|
||||
此外,做好规则引擎之后,还是需要用上一章的低耦合的办法去接入的,你也可以根据上一讲的内容自行组合。
|
||||
|
||||
那么,我们就直接进入规则引擎的讲解,关注它本身的架构。
|
||||
|
||||
规则引擎:架构分析
|
||||
|
||||
从结构上来说,前后端是各有一套规则引擎的。其中,前端的和BFF紧密结合,我们可以放一起讨论。
|
||||
|
||||
|
||||
|
||||
你可以从图里看到,无论是前端还是后端,大致流程都是收集信息,配置规则,对应的模块进行处理,然后根据规则进行指定的操作。这个过程我们可以认为是数据驱动,也可以认为是规则驱动。当然,正是因为规则驱动,所以才有了规则引擎这样的名字。
|
||||
|
||||
在发现了前后端的相似性之后,你可能会有一个疑问:既然前后端都需要规则配置,那么这个是否可以抽象出一个配置模块,同时对前后端进行配置呢?
|
||||
|
||||
答案是可以的,但是要看你的业务权限到什么范围。理论上说,一个配置系统同时配置前后端,能减少配置压力。但是,如果对应的系统不在你权限范围内,就意味着你可以随意变更别人模块的权限,通常推行压力会大很多。而且这不是什么技术问题,而是一个办公室政治问题。不同的团队可能会有不同的难度。这个没有标准答案。
|
||||
|
||||
规则引擎:后端
|
||||
|
||||
实际上,很多公司都有做反爬虫的系统,但是它们看起来很高大上,实际效果却一般。原因就是他们只做了这个规则引擎,并没有深入下去。这样的现象,恰恰也说明了规则引擎的基础性以及重要性。
|
||||
|
||||
按照我们前面的介绍,后端通常是做请求校验的,也就是对HTTP请求进行规则校验。我们再来复习一下前一张的流程图:
|
||||
|
||||
|
||||
|
||||
可以看到,规则引擎是独立于应用层而存在的。那也就意味着要么SLB调用规则引擎,要么反爬SDK调用规则引擎。这同时也意味着规则引擎的独立性极强,可以随时被熔断。
|
||||
|
||||
记住这个观点,然后我们逐个模块来看。
|
||||
|
||||
信息收集模块
|
||||
|
||||
第一个模块就是信息收集模块。
|
||||
|
||||
根据我们前一讲低耦合的说法,规则引擎是由反爬SDK来调用的,而不是耦合在系统内部。那么,规则引擎应该是个独立系统。这意味着,他不可能拿到请求的上下文,因此不可能直接分析HTTP Header。而我们就需要把HTTP Header都带过去。
|
||||
|
||||
给另一个系统带参数过去,方法很简单,就是调用时序列化当前HTTP Header,然后作为调用参数传给对方即可。这里传参本身没什么难度。不过,需要权衡的是,日志在哪里记录?是调用方,还是规则引擎?
|
||||
|
||||
原则上来说,我建议放在规则引擎。虽然放在调用方记录会更加稳妥、不丢日志,但是出于以下考虑,还是放规则引擎方比较合适:
|
||||
|
||||
1. 放在调用方, 会增加接入难度:
|
||||
|
||||
日志如果集成在调用方,要么是给业务方一个接口,要么是集成在SDK里面。无论是哪一种情况,都增加了出错的可能性,并且出错了都难以调试——因为这是跨团队代码。
|
||||
|
||||
因此,出于简单考虑,应该尽可能减少SDK的调用成本。最好就一句话:结果=调用反爬(),然后代码结束。
|
||||
|
||||
2. 放在调用方,会增加对业务系统的耦合:
|
||||
|
||||
上一讲详细解释了的低耦合的思维方式。
|
||||
|
||||
3. 放在调用方,会增加调用方的压力。
|
||||
|
||||
因此,我们的规则引擎应该自带日志模块。
|
||||
|
||||
日志的问题讨论结束了,我们回到正题。后端规则引擎基本上就是收集HTTP Header了,而HTTP协议本身是一个文本协议,因此Header本身也是文本,这也降低了我们序列化的成本。因此,暂时无需考虑序列化对系统造成的压力。但是,依然要对HTTP Header做限制,避免对方恶意攻击header的count,消耗序列化成本,把反爬虫系统拖熔断。
|
||||
|
||||
规则引擎接收到请求参数,就可以对Header的内容进行规则判定了。这里因为还要做反序列化,而HTTP本身又有大量的encode和decode操作,因此一定要小心处理,不然很容易埋bug,类似忘记调用encode、调用decode次数错误等等都有可能出现。而encode和decode类型的bug,一旦出现,都是概率型bug,不是必现型bug,调试会极难。同样的道理,log记录也要注意这个问题。
|
||||
|
||||
规则校验模块
|
||||
|
||||
后端的规则校验模块本质上是一个策略模式。
|
||||
|
||||
策略模式简单来说就是对策略进行解耦。事实上,大部分设计模式都逃不掉“解耦”这个概念。而规则,也就是Rule,本质上也可以认为是一个策略。因为根据指定的规则,我们可以进行判定,输出结果。这本身也算一种策略。
|
||||
|
||||
我们看这样的伪代码:
|
||||
|
||||
interface IContext;
|
||||
interface IRuleResult;
|
||||
interface IRule{
|
||||
IRuleResult Check(IContext context);
|
||||
}
|
||||
// 其中一个实现类
|
||||
public HttpHeaderEncodingRule : IRule{
|
||||
IRuleResult Check(IContext context){
|
||||
// 检测encoding是否正确
|
||||
return new ....
|
||||
}
|
||||
}
|
||||
public HttpHeaderCookieRule:IRule{
|
||||
IRuleResult Check(IContext context){
|
||||
// 检测cookie是否正确
|
||||
return new...
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
类似这样的规则还有很多。 如果单独判定一条,那就是策略模式。如果一起判定呢?你可能会忽然说:老师,不对,这就成了职责链模式了!你这模式好乱啊!
|
||||
|
||||
是的,但是你有没有想过,你创建这些Rule的时候,还要使用抽象工厂呢?实际上设计模式通常都是组合使用的,只要实现了高内聚低耦合,用了什么设计模式并不重要。
|
||||
|
||||
看,不但系统架构要低耦合,设计代码也是一样的!
|
||||
|
||||
规则判定结果输出
|
||||
|
||||
规则引擎判定完结果之后,是不是可以直接输出给前端,给出判定结果,然后给出对应的处理呢?
|
||||
|
||||
不是的。你直接给前端,告诉用户:你是爬虫,你完了,我这里肯定要搞你,我打算这么搞你。以下省略代码3000行……
|
||||
|
||||
你当爬虫傻么?他一看:什么,我被搞了,不行我去调试一下,兄弟们先不爬了。
|
||||
|
||||
所以,爬虫需要低调,难道反爬虫就不需要吗?
|
||||
|
||||
那么,我们的处理就应该是静默处理。也就是说,爬虫默默拿到处理后的数据就可以了,不要在前端进行任何的判定。只要有判定,那么就容易分析出反爬虫的结果。这是反爬虫的大忌。例如你要调整价格,那么直接把价格在后端(或者BFF)拉高然后吐给前端即可。
|
||||
|
||||
如果你默默给了个提价比例给前端,让前端自己去提价……好吧,我只能说你们的前端也太好欺负了。
|
||||
|
||||
规则引擎:前端
|
||||
|
||||
前端部分主要是规则引擎的辅助。我们来看下具体的辅助打法。
|
||||
|
||||
pre:信息收集。
|
||||
|
||||
整个处理的最前置就是信息收集。我们前面讲过,一个主要的前端收集点就是DOM指纹。所以,我们把重点放在这里。
|
||||
|
||||
所谓的DOM指纹,我们也提过,实际上是DOM和BOM的混合。但是都是在window上拉取的(因为document也在window上,可以用window.document来访问),所以用window做根节点拉取即可。你要是想叫BOM指纹也可以。
|
||||
|
||||
我们可以使用这样的字符串来描述定位符:
|
||||
|
||||
/navigator/geolocation/toString
|
||||
代表执行window.navigator.geolocation.toString()
|
||||
这个是早年phantomjs的一个重要监测点。
|
||||
/document/body/div(3)/input[value]
|
||||
代表获取body元素的第三个div里面的input元素,并取出value
|
||||
这里顺便提一下这里的input是一个file类型的,你可以提前设置一个value进去。我们都知道,在浏览器安全规则下,这个value的设置是不可能成功的。但是,模拟DOM的库,有成功的可能性。所以我们要检测的是value设置失败,也就是依然为空才行。
|
||||
|
||||
|
||||
这类代码可以写出很多。格式应该由你自己定义,上面只是demo。但是要注意一点:你打算明文下发这段字符串吗?
|
||||
|
||||
当然不可能,这不是给爬虫送上门让他怀疑并分析吗。
|
||||
|
||||
我们应该下发的反而是加密结果,越复杂越好,甚至可以是一个树。js调试的时候,因为有console.table的存在,是不太怕长数据的,他怕的是多层级的数据。一个js实现的单链表,能直接绕晕调试工具;而一颗满二叉树,能大幅提升调试难度。那么,如果你的对象存在循环引用呢?console.table会如何处理?你可以线下试试。
|
||||
|
||||
ing:信息处理
|
||||
|
||||
信息处理部分主要是BFF的预处理。
|
||||
|
||||
我们前面提到过,BFF可以做中转和聚合。这里就体现了聚合的一点。
|
||||
|
||||
首先,多个数据可以聚合成单个请求给后端,降低后端压力。其次,多个字段可以合并去重,降低报文的大小,减少后端的压力。最后,BFF可以针对部分Rule直接进行处理,无需进入后端,这样也减少了低级爬虫对后端的冲击。
|
||||
|
||||
我们以IP拦截为例。
|
||||
|
||||
IP拦截规则可以是固定IP拦截,可以是段拦截。这里的核心就是要降低复杂度。
|
||||
|
||||
我们都知道,如果根据规则一个一个去匹配,那么一定是可以检测完所有的IP的。但是这样做复杂度会大大提升。例如,你有200个IP段的规则,那么就要进行200次校验。这样随着规则的上升,复杂度就会不断提升。那么,如何让复杂度稳定在一个常数级别呢?
|
||||
|
||||
这里我们做一个简单的例子。例如,你的规则有以下几个:
|
||||
|
||||
# 固定IP黑名单
|
||||
192.168.3.1
|
||||
192.168.3.7
|
||||
# IP 段
|
||||
192.168.4.*
|
||||
192.168.5.*
|
||||
192.168.8.*
|
||||
|
||||
|
||||
如果按照常规的做法,这里应该是,对固定IP进行一个循环,然后逐个判定。然后再对IP段进行range区间的判定,合在一起之后得出“是否落入IP黑名单”的结论。
|
||||
|
||||
你会发现,这里是五条规则,那么至少要判定5次。如果你有n个规则,那么就要判定n次。也就是,随着规则的上升,判定速度会越来越慢。那么我们如何提升一下速度呢?
|
||||
|
||||
我们经过观察,就会发现,是不是开头不是192.168的,就根本不用判断了?我们肉眼一看就知道。那么根据前缀,直接就可以排除掉一堆啊。
|
||||
|
||||
这让你想起了什么数据结构呢?是的,这是一个前缀树。
|
||||
|
||||
我们把这几条规则汇总一下,就可以得到如下的样子:
|
||||
|
||||
{
|
||||
"192":{
|
||||
"168":{
|
||||
"3":{
|
||||
"1":true,
|
||||
"7":true
|
||||
},
|
||||
"4":true,
|
||||
"5":true,
|
||||
"8":true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
在BFF里面,一旦你有了这棵树,那么一个IP进去,判定方式就很容易了。
|
||||
|
||||
这里我们还是举例来说明。现在,我们手里来了一个IP:192.168.3.6
|
||||
|
||||
那么首先查找192,结果为true吗?不为true,是一个object,那么用这个object继续找168,结果是true吗?不是true,是一个object。那么继续找,3,是true吗?不是true,依然是object。下一个是6了。object取6,是true吗?不是true,是undefined,等价于true。那么运行结果为false,这个IP不在黑名单。
|
||||
|
||||
从头到尾,我们只进行了四次判定。而且,后续无论这个黑名单多大,我们的判定都是4次,也就是我们的算法复杂度是O(4),常数级别,那也就是O(1),因此极为可控。
|
||||
|
||||
当然,这只是个demo。事实上,你还可以把IP转化为二进制,然后进行32次二叉树的查找,直接得出结果,也是没有问题的。甚至IP段是用子网掩码实现的,这个直接就与树的深度挂钩,思路和上面例子的思路都是一样的。
|
||||
|
||||
二进制的好处是,很多子网并不是工整的分割到8的倍数,因此可能会有一些很稀奇古怪的IP段,例如192.168.3.5/22这类奇葩的数字。你可以自己展开下,看看这个树是不是忽然变得复杂了起来。但是二叉树就直接避免了这个问题。
|
||||
|
||||
这个例子的总体思路是什么呢?是我们要时刻记住,反爬就是要降低系统压力的,因此要时刻考虑效率问题,不能爬虫没拦到,把自己给累死了。
|
||||
|
||||
post:前端处理
|
||||
|
||||
前端处理相对就容易一些。实际上,大部分的作假,我们都是做在接口上了,也就是直接假装正经地给前端返回了正常但是不正确的数据。但是前端还是有一些小的动作可以做。
|
||||
|
||||
例如,如果你需要强制登录,那么可能接口返回就是一个未验证,不给数据的状态。这个时候就需要前端做一些兼容处理,例如跳转登录或者弹登录框,这类需要前端做兼容处理。当然,这个是前端基操了,只要能想得到,我相信你一定做得到。
|
||||
|
||||
小结
|
||||
|
||||
好了,这节课,我们着重研究了规则引擎的具体实现方式。实际上,线上的规则引擎会十分复杂。复杂并非难度大,复杂与难,一直是两件不同的事情。因此,我们这里的几个例子,只是给你提供了思路,后续可以按照这个思路自己去探索属于自己的规则引擎实现。
|
||||
|
||||
但是,你会发现,所有的反爬最终都逃不脱后端的信息收集,校验,以及规则判定输出。其中规则校验又牵扯到了低耦合的事情。同时,前端也根据时机,会进行信息收集,信息处理,以及前端兼容处理。其中,重点是降低消耗,不要在反爬的过程中消耗无谓的资源。这样,我们才能够更安全地进行操作。
|
||||
|
||||
要时刻记住:保住项目组,让项目组活下去,才有胜利的希望。如果无法存活,那么笑到最后的,就是你的对手。
|
||||
|
||||
思考题
|
||||
|
||||
好了,又到了愉快的思考题时间。还是老规矩,三选一。
|
||||
|
||||
|
||||
32层二叉树虽然在广度上变小了,但是层数变多了。它的效率真的会更高吗?会不会看起来很美好实际上并不如字符串的IP判定?你的判定依据是什么?
|
||||
前端信息收集不能直接下发xPath,避免被爬虫抓。那么你有什么办法来处理这个问题呢?
|
||||
规则校验模块部分,我们说,可能同时使用策略模式,职责链,以及抽象工厂。那么你认为还可能有什么设计模式会混入其中呢?
|
||||
|
||||
|
||||
可以把想法写在评论区,让我看看你的奇思妙想。 反爬无定势,也许我也可以在评论区学习到更多的思路!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
240
专栏/反爬虫兵法演绎20讲/16验证爬虫:我到底要不要百分百投入?.md
Normal file
240
专栏/反爬虫兵法演绎20讲/16验证爬虫:我到底要不要百分百投入?.md
Normal file
@ -0,0 +1,240 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
16 验证爬虫:我到底要不要百分百投入?
|
||||
你好,我是DS Hunter,反爬虫专家,又见面了。
|
||||
|
||||
前面,我们讲了反爬虫的前置操作,例如快速下线的保命技巧,key生成的相关知识。那么这一讲,我们就谈谈反爬虫最终的核心诉求:验证爬虫。
|
||||
|
||||
实际上,在上一讲的规则引擎里面,我们已经对爬虫做了一些验证操作。但是,那里的验证只是简单的规则校验,还属于比较初级的校验。高级校验就要考虑得更多一些。
|
||||
|
||||
两者之间有什么不同呢?我们可以试试用不同的英文单词来区分两者。上一讲的验证,更多是validate,而这一讲,则更多是test or confirm。也就是说,这一讲的验证,并非单纯的校验客观上是否符合某种规定,更多的是检测、确认主观上是否是我们想要的。
|
||||
|
||||
那我们直接从规则组合的部分开始吧。
|
||||
|
||||
规则组合
|
||||
|
||||
相信现在的你已经知道了,规则引擎是由多个规则构成的。而这些规则较为通用,并不是针对指定场景的。因此,针对不同的场景,我们可以对规则进行组合使用。这里,我们要讨论的就是组合过程中需要注意的地方。
|
||||
|
||||
例如,价格页面可能会存在对商品ID的判定,但是通用促销页面则可能是判定用户属性,他们使用的规则会有所不同。价格页面用A和B的组合,促销页面用B和C的组合。这就像游戏中,每个装备都有自己的属性以及作用。而不同的玩家根据自己的需要,会对装备进行组合,寻找更匹配自己的“套装”。
|
||||
|
||||
规则整合
|
||||
|
||||
上一讲我们提到了规则判定本来是策略模式,但是如果是多条一起判定,就可能成了职责链模式。其实那个时候就已经开始使用这种整合思想了。
|
||||
|
||||
职责链就相当于把职责串联成一个链条,让规则顺着链条走下去,最后走出结果。
|
||||
|
||||
我们抄一下上一讲的代码:
|
||||
|
||||
interface IContext;
|
||||
interface IRuleResult;
|
||||
interface IRule{
|
||||
IRuleResult Check(IContext context);
|
||||
}
|
||||
|
||||
|
||||
具体实现我们就不摘抄了。我们假设你为当前的场景配置了四个不同的规则,分别是Rule1,Rule2,Rule3,Rule4,那么你的判定代码应该是类似这样的:
|
||||
|
||||
[Rule1,Rule2,Rule3,Rule4].reduce((prev,rule)=>{
|
||||
var result = rule.Check(context);
|
||||
// 如有其余逻辑可以在这里处理
|
||||
return prev || result;
|
||||
},false)
|
||||
|
||||
|
||||
通用的判定规则只需要这类简单的代码组合、链式判定即可。注意,这里存在一个问题,如果规则本身有依赖,那么如何处理呢?
|
||||
|
||||
可能这里你会困惑:规则依赖是什么?
|
||||
|
||||
我来举个例子。假设你现在身上有两个装备,一个描述是:受到攻击,减少伤害5点。另一个是:受到攻击,减少伤害50%。
|
||||
|
||||
那么这个时候你收到了100点伤害,真正打到身上的伤害是多少呢?有下面两种情况:
|
||||
|
||||
|
||||
|
||||
你会发现,很多算法是依赖顺序的,顺序不同就会得到不同的结果。
|
||||
|
||||
而职责链要如何解决这个问题呢?我们可以把这个问题分成数据传递和判定顺序两部分来看。
|
||||
|
||||
针对第一个问题,context是顺着职责链一路下去的。因此当数据在context上传递的时候,至少数据传递问题我们解决了。而判定顺序,应该是后台配置的。我们读取配置的时候,要顺便读取配置顺序。
|
||||
|
||||
可能你会说:我按照写入顺序来做判定不就好了吗。先做的放前面,后做的放后面。
|
||||
|
||||
这里存在两个可能改变顺序的地方,一个是数据库,一个是序列化。
|
||||
|
||||
我们都知道,规则配置无论如何指定顺序,最终肯定是放在数据库里的,而数据库是基于集合的。如果你依赖写入顺序,很快就会发现,由于数据库默认不保证顺序,你拿出来的数据有时候是基于写入顺序的,有时候不是。因此你一定会指定order by。这个时候,我们就需要一个字段来帮我们做排序。因此,排序字段是必备的。
|
||||
|
||||
此外,服务端在序列化的时候,因为很多序列化器也不保证数组顺序,为了避免这种不可预知的问题,我们通常会指定顺序。使用的时候,自己再排一次序,避免发生顺序错乱。
|
||||
|
||||
最后,顺序可能经常存在调整。为了调整DB方便,我们也需要指定order字段,方便调整书序。这样,规则整合的问题才能真正得到解决。
|
||||
|
||||
规则翻译
|
||||
|
||||
规则翻译的主要原因是,我们前端传过来的规则经常会存在加密的情况。
|
||||
|
||||
当系统中存在BFF的时候,我们通常把解密模块放在BFF中。第一个原因是BFF比较前置,可以降低后续的服务压力。第二个是BFF大部分是JavaScript做的,而前端也是JavaScript做的加密,这里会比较方便。
|
||||
|
||||
如果前端代码是JavaScript加密的,BFF用JavaScript解密,那么又回到了我们成对加解密的思路。因此,存储的时候依然是采用成对加解密的思路即可。这里你也可以参考第10讲的内容。
|
||||
|
||||
规则打分
|
||||
|
||||
虽然大部分情况下规则可以做成布尔类型,要么通过,要么不通过,但是有的时候,例如真人判定的规则里,我们还加入了打分的概念。也就是说,有些规则即使不通过,也可能不拦截,这要取决于其余规则的得分。这个时候,我们就需要对规则进行加权计算,也就是打分。
|
||||
|
||||
不过,单个规则的分数是难以制定的,大部分情况下我们是根据线上的情况进行逐步调整的。例如,根据规则误伤的人数,计算分值。一般说来,误伤越低,分数越高。误伤越高,分数越低。
|
||||
|
||||
规则分数计算
|
||||
|
||||
规则分数计算与职责链的不同在于,职责链是串行调用,规则分数是并行调用。当然,现实情况中可能是两者共用,例如多个规则并行,每个规则内部有子规则,子规则是串行。不论怎么使用,我们都只需要将分数直接相加,就可以得出总分数,然后再划分阈值进行判定即可。
|
||||
|
||||
如果是串行,那么在reduce的过程中可以通过reduce的initvalue串下去,也可以通过context做为全局变量传递下去。initvalue的传递,定义域被限定在了当前reduce内,也就是隔离性比较好。如果用context,可以实现跨规则的记分,灵活性很强,但是隔离性较差,影响调试。
|
||||
|
||||
但是,我们依然需要对每个规则增加一个权重,这样可以实现更灵活的打分。
|
||||
|
||||
可能你会觉得奇怪:老师,我们已经给不同规则定出不同的分数了,为什么还要给出个权重呢?如果一个规则是10分,权重为1,这和“给5分,权重为2”,没有区别啊?
|
||||
|
||||
是的,针对单个规则在单个场景下的使用,是没有区别的。但是我们的规则如果跨场景呢?
|
||||
|
||||
例如校验Cookie,可能是一个10分的规则。但是对于订单规则,他希望自己把这个规则提升得更重要一些。这时候如果他把规则提升到20分,但是其余的规则使用方不同意,他们依然想用10分呢?
|
||||
|
||||
这个时候有两种做法,一种是覆盖分数,也就是自己重新定义一个分数“20”,不用默认的10分。还一种是保持10分不变,增加一个2的权重。
|
||||
|
||||
大部分情况下,我们会选择第二种方法,因为这个在视觉上更直观,计算也更加方便。你一看到权重2,就知道这个规则的重要性翻倍了。但是,如果使用重定义分数的办法,等你查找哪个规则导致分数不对的时候,发现满篇都是各种分数,还要查看原始分数才知道当时是调高了还是调低了。这会严重拖慢调整策略的速度。
|
||||
|
||||
规则分数阈值问题
|
||||
|
||||
规则分数的阈值就是一个判断,这个没有任何技术含量。
|
||||
|
||||
但是,这里需要注意的是:当误伤了用户,用户来投诉的时候,你如何知道当时用户得分多少,阈值多少,如何被误伤呢?
|
||||
|
||||
这里就再次遇到了日志问题。
|
||||
|
||||
再强调一次:只要存储成本顶得住,反爬记再多的日志都不嫌多。考虑到阈值变更其实是一个很低频的事情,因此其实并不需要完整记下来当前阈值,记录时间等等完整信息,我们可以只记录ID,后续用ID去串联。
|
||||
|
||||
例如,阈值变更,在配置系统是有历史的,那么只需要记录当前的版本号即可。此外,用户当前分数,也不一定非要记录,尤其是记录分数可能会导致记录分数计算过程。这个时候可以记录当前规则信息——规则配置系统也应该是有版本号的。有了所有的匹配之后,那么在排障的时候,可以重算分数。这样就避开了存储问题,时间换空间。
|
||||
|
||||
按规则随机跳过
|
||||
|
||||
我们前面提到过,随机跳过有两种,一种是计算概率,一种是按照集群weight来设置。我们先看直接计算概率的办法。
|
||||
|
||||
按概率跳过
|
||||
|
||||
按概率跳过,首先要明确需求:是按总人数计算概率,还是在爬虫里计算概率?
|
||||
|
||||
通常我们说“跳过”的时候,都是在爬虫里计算。而随机误伤的时候,则是在总人数里随机。
|
||||
|
||||
为什么这么说呢?一方面,我们谈“跳过”,指的是明明它是爬虫,我们依然要放过它。因此,这个操作应该是“爬虫中”进行。另一方面,我们谈“随机误伤”,指的是不管是不是普通用户,我们都要误伤一下。因此,这个操作应该是在“总用户”进行。
|
||||
|
||||
有了这两个分析之后,我们就能发现,跳过是在爬虫上操作,也就是要先判定,再根据判定结果来进行操作。而随机误伤,不用关心反爬状态,因此不需要判定是否是爬虫,可以在前置做短路操作。
|
||||
|
||||
需求明确后, 后续就简单了。 大概代码如下:
|
||||
|
||||
var alive = 0.791; // 通用跳过概率
|
||||
var death = 0.0001;// 通用随机误伤概率
|
||||
if(Math.random() < deadth){
|
||||
reutrn false;// 无脑误伤用户,不再判定
|
||||
}
|
||||
// 上面是前置操作,如果进入,已经直接return,无需再判定爬虫
|
||||
var result = Rules.check(context);// 假定判断结果在result里面。true为爬虫。
|
||||
// 下面是后置操作,如果进入,则判定是否随机跳过,不跳过则正常走,跳过就认为是正常用户
|
||||
if(result && Math.random() > threshold){
|
||||
// 超出随机跳过范围
|
||||
returne false; // 的确是爬虫
|
||||
}
|
||||
else{
|
||||
reutrn true;// 是普通用户。也可以直接短路操作!(result && (Math.random > threshold))
|
||||
}
|
||||
|
||||
|
||||
这样,通过前置和后置的两种方式,就避免了频繁计算概率,并且符合需求。
|
||||
|
||||
集群weight跳过
|
||||
|
||||
集群weight跳过,在前文提到过。因为集群本身在Nginx上做了随机,因此其实只需要关闭部分机器的验证功能,就等效于部分跳过。
|
||||
|
||||
前面我提过一个问题:对于一些不工整的随机概率,我们用什么方法来设置weight比较合适呢?
|
||||
|
||||
你可能还记得79.4%这个诡异的数字,但其实这个问题是有陷阱的。正确的思路是:集群weight只能做为快速变更的辅助,不建议用于常规功能。因为机器数是整数,只能实现一些工整的概率。如果要实现不工整的概率,例如79.4%这种,必然会导致调整weight的负载不均衡。
|
||||
|
||||
因此,调整weight,有意负载不均衡,来实现随机跳过,一般是在来不及发布的时候使用的权宜之计,并非主力做法,你也不必过于依赖79.4这个数字。必要的时候,你可以向上或者向下取一个工整的值。
|
||||
|
||||
补充:按规则跳过
|
||||
|
||||
按规则跳过的操作相对少见,一般要么是单纯是想把水搅浑,要么就是测试规则与正式规则混合部署,希望能够直接在战场演习。这类需求虽然不建议接,但是一旦有了,我们也有办法处理。具体方案有两个:
|
||||
|
||||
第一种方案,context设置全局变量传参出来。
|
||||
|
||||
因为context是唯一一个贯穿整个链路的变量,因此如果某个规则需要变更结果,只能通过这个方式通知其余人。这里面context相当于一个总线,我们在总线上进行广播,其余规则收到广播后,可以正常跑,然后结尾再判定context的信号进行强制改判定。
|
||||
|
||||
这样代码比较简单,但是效率较低,因为rule全跑了。当然,你也可以选择在context总线上有了信号之后所有Rule直接熔断跳过不判定,这样的好处是效率高,缺点是代码变复杂。不过如果基类实现这个通用功能,能稍好一些。
|
||||
|
||||
第二种方案,记分。
|
||||
|
||||
简单的说就是给出评分的时候,不直接给出总分,而是分别给出各个位置的分数。然后结尾再判定的时候,如果跳过规则的分数已经给出了指定值,那么直接强制不判定分数,或者强制降分到0,能跳过所有的阈值。你也可以把它想成一票否决权的感觉。
|
||||
|
||||
概率的动态调整
|
||||
|
||||
在上面讲解过那么多的“随机”之后,你会发现,无论是随机跳过还是随机误伤,都有可能根据情况实时调整。因此,它还需要有一个配置系统。
|
||||
|
||||
随机跳过的配置系统就是一个简单的Config系统,DB用于持久化存储数据,缓存用于提升读取速度,后台配置页面的create和update用于刷新缓存,定期用Job也刷缓存兜底,基本上就可以了。需要注意的是,前面我们提到过版本号的问题,因此需要特别注意存储版本号。
|
||||
|
||||
数据库表demo如下:-
|
||||
|
||||
|
||||
例如随机误伤的阈值就可以指定一个name,子表存储一个阈值即可。
|
||||
|
||||
操作历史表示意:-
|
||||
|
||||
|
||||
此外,配置系统与规则系统很可能是部署在同一个DB上的,如果DB挂了,会直接存在单点故障。因此,需要有更强力的熔断措施。例如,验证服务器全部拉出,或者SLB断流,直接不提供验证服务,在SDK上设置超时熔断,直接断掉全部反爬虫系统。
|
||||
|
||||
最后,为了防止用户误操作,需要提供操作的上下限。例如随机误伤是极低概率,如果不小心设置为0.5,那就是直接误伤一半用户,妥妥的生产事故。因此需要限定为只允许使用小于一定上限的数字。甚至,可以考虑界面上只支持选择,不能自定义。
|
||||
|
||||
规则白名单
|
||||
|
||||
规则白名单与规则跳过十分接近。只不过,这类规则通常是通用规则,因此可以直接做前置判定,避免运行其余规则,消耗资源。
|
||||
|
||||
指定区域白名单(IP,GPS)
|
||||
|
||||
反爬虫系统经常碰到这种恼火的事情:有合作伙伴要与自己合作,API来不及开发,或者API数据有问题,所以合作伙伴要走爬虫。虽然很恼火,但是也没什么办法,不得不做。这个时候,我们就可能会根据IP进行前置的白名单洗白。
|
||||
|
||||
此外还有一个办法更简单,那就是直接新建一个集群,不部署反爬虫,但是参数需要指定key才能访问。合作伙伴使用指定的key来拉取数据即可。key一旦存在泄密,就需要更换。这样,还可以降低系统压力,避免合作伙伴与线上用户争抢资源。
|
||||
|
||||
这里我也给你补充一个主要针对APP爬虫的“GPS白名单”。APP爬虫针对指定的地理围栏可以拉黑,也可以洗白,根据业务需要可以灵活处理。
|
||||
|
||||
由于大部分反爬白名单需求实际上在国内(真是一个悲伤的经验),不会牵扯到北极圈之类的地方,因此也可以用经纬度偏移这种更简单的方式,无需计算公里数。在国内,大部分情况下经纬度画出来的矩形还是很接近矩形的。
|
||||
|
||||
指定用户白名单
|
||||
|
||||
指定用户的白名单则是UID判定。注意这类需求需要前置解决,不能后置,避免修改判定失败,同时前置也能提升效率。最后,白名单用户通常都是VIP用户,例如CEO,股东等等,因此操作过一次之后,最好存储下来。一般说来,你下次还会碰到他。
|
||||
|
||||
小结
|
||||
|
||||
好了,关于验证爬虫,我们就谈到这里。
|
||||
|
||||
这一讲,我们主要看了所有的规则判定方式以及规则的打分方式。
|
||||
|
||||
这些规则可以组合使用,同时,为了加密的需求,我们也提到了如何进行规则翻译这件事。而规则的打分,包括如何制定分数,计算分数,以及如何配置阈值等等。相对于改变规则的分数,调整分数权重会显得更加直观,计算也更便捷 。当然,在验证爬虫的过程中,我们有时也需要按规则随机跳过。最后,我们还讨论了各类白名单跳过的两种做法——指定区域和指定用户。
|
||||
|
||||
|
||||
|
||||
总体来说,前置的判定通常用于拉黑,而后置的判定通常用于洗白。当然这并非绝对的,如与实际需求冲突,还是要仔细分析。
|
||||
|
||||
思考题
|
||||
|
||||
最后的最后,又到了愉快的思考题时间。还是老规矩,三选一。
|
||||
|
||||
|
||||
后置判定可以用于拉黑吗?优缺点分别是什么呢?
|
||||
集群weight会导致复杂不均衡问题因此一般用于应急。那么,如果我们的机器本身就申请配置不均衡能解决这个问题吗?会导致什么新问题吗?
|
||||
产品经理如果提了个需求:在某GPS点,拉黑半径五公里的用户。这个需求是画圆,需要进行计算了,不能无脑判定经纬度了。如何让性能提升呢?
|
||||
|
||||
|
||||
可以把想法写在评论区,让我看看你的奇思妙想。 反爬无定势,也许我也可以在评论区学习到更多的思路!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
248
专栏/反爬虫兵法演绎20讲/17招聘篇:如何写一个合适的JD?.md
Normal file
248
专栏/反爬虫兵法演绎20讲/17招聘篇:如何写一个合适的JD?.md
Normal file
@ -0,0 +1,248 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
17 招聘篇:如何写一个合适的JD?
|
||||
你好,我是DS Hunter,反爬虫专家,又见面了。
|
||||
|
||||
我在开篇词里说过,学完前两章的你,单兵作战的能力已经达到了极致。那么现在,我们就一起开始从单兵作战到团战的跨越。或者,你也可以理解为我们要实现从技术到管理团队的跃迁,开启反爬虫团队作战的新模式。
|
||||
|
||||
反爬虫搭建团队,第一件事就是招人。而招人的第一件事,就是编写一个合格的JD。
|
||||
|
||||
如果你曾经做过管理,你可能会说:这个我熟,JD如何如何写,能够写得精准,给应聘者更好的感受,寻找到匹配的人才。
|
||||
|
||||
你的经验是非常正确的。但是我们来看这样一个故事:
|
||||
|
||||
|
||||
一个冷风嗖嗖的春天,一个朋友找到我:“哥,帮个忙,我们被竞对爬的不行了,他们技术太牛逼了,我们检测了各种框架都被绕掉了,你有办法帮我们看下他们的规律不?我把日志权限开给你。”-
|
||||
-
|
||||
我说:“是你们的XX竞对吗?”-
|
||||
-
|
||||
“是的。”-
|
||||
-
|
||||
“稍等我十分钟。”-
|
||||
-
|
||||
十分钟后,我给了他们一份文档,里面详细写了对方使用了什么技术,后端什么样子,破解用的什么,人员组成是什么样的。-
|
||||
-
|
||||
朋友大惊:“你这太强了,怎么做到的,我日志里都找不出这么全的信息!”-
|
||||
-
|
||||
我立刻甩给他一份JD——他们的竞对正在招聘爬虫工程师,长长列出了各种需求,甚至根据薪资情况还能推出对方能招到什么样的人。-
|
||||
-
|
||||
朋友不屑地说:“切,我还以为多厉害呢。”
|
||||
|
||||
|
||||
你看,反爬就是这么憋屈,你的每一个操作都像一个魔术,一旦揭秘了,对方就会觉得:哦,不过如此。
|
||||
|
||||
然而过了不到一周:
|
||||
|
||||
|
||||
“哥,我们这面反爬团队也搭了半年了,至今也找不到什么人啊。你看有没有办法帮我看看?”-
|
||||
-
|
||||
我又甩出一份JD给他。这是他们自己在网上发布招聘的JD,基本啥都是面议。我说:“你写这么点谁知道你们要干啥啊,这有人应聘就出鬼了。”-
|
||||
-
|
||||
“你说得对”,朋友恍然大悟,说,“我马上去改改JD,这谁写的JD,太业余了。我得把我们的要求全写出来,比如我们需要……咦等等,是不是……”-
|
||||
-
|
||||
朋友忽然好像又想起了什么。他翻出之前我发给他的竞对JD,陷入了沉思……
|
||||
|
||||
|
||||
看吧,现在你还觉得JD好写么?
|
||||
|
||||
现在各个厂的JD其实很混乱,小厂么写得详细无比,因为他希望你入职就能直接干活。大厂嘛,JD跟写着玩似的,根本不在乎你之前做没做过,因为他有培训机制,只需要优秀的人才即可。
|
||||
|
||||
爬虫和反爬虫领域,也有类似的问题,只不过小厂通常没有反爬虫,因此少了一种情况。所以我们要写的JD有三种:大厂爬虫,大厂反爬虫,小厂爬虫。后续我们会分开讨论。我们先看下JD的通用规则。
|
||||
|
||||
JD通用规则
|
||||
|
||||
JD是候选人接触公司的第一窗口,它的好坏直接决定了应聘者对你的第一印象。一般说来,JD的要求是:内容丰富、精准、简洁。
|
||||
|
||||
具体内容主要包括:
|
||||
|
||||
|
||||
岗位工作内容,职责,汇报线(可选)
|
||||
任职必备资格
|
||||
技能以及经验要求
|
||||
薪资结构区间
|
||||
|
||||
|
||||
其中第二点,慢慢在淡化。由于学历歧视的问题,越来越多的公司开始在JD里去掉学历要求。同理,还有年龄要求,性别要求等等。当然,这些要求可能并未去除,只是变成了潜规则。慢慢的,似乎就没什么必备资格可言了。因为随便写点什么都可能引发PR问题,那还不如不写。
|
||||
|
||||
JD的初始写作者通常是技术人员,然后HR做审核。有些技术人员可能觉得HR审核的时候没有改什么,但是实际上HR的修改通常比较核心。例如你有学历要求,他帮你去掉了,一定不要和他争。不要担心找来的人不符合要求,要知道,第一,你们是有面试的;第二,JD通常分内外版本,外部版本是给候选人看的,内部版本才是用来筛选的,这是常规操作——你的反爬信息收集不还分爬虫可见版本和内部解密版本吗?
|
||||
|
||||
大厂JD潜规则
|
||||
|
||||
大厂的JD跟玩似的。
|
||||
|
||||
这真不是黑大厂,你去看看线上JD就会发现小厂写得还挺详细的,大厂的JD就跟随便写着玩似的,甚至有HR坦诚清晰地和你说:不用看JD,那就是随便写的。很多初次面试大厂的人都对此很不习惯。
|
||||
|
||||
其实大厂的HR也很为难,JD写太详细了,容易被人挑毛病。不如写得含含糊糊的,之后万一想拒了你,也可以说不符合要求。如果写详细了,容易被人杠:你这么多要求,我全符合,你凭啥说我不符合要求。但是少写点,解释起来就可以天马行空了。
|
||||
|
||||
举个例子:要求Vue熟练。
|
||||
|
||||
你Vue特别厉害,怎么考也考不倒,但是另一个候选人接了offer,必须拒绝你,就很难找理由。但是如果JD写:要求Web主流框架熟练。Vue你考不倒还有React吧?不行问jQuery,总有办法的。
|
||||
|
||||
出于这种潜规则,你的JD本身也要符合这样的要求。此外,记不记得我们前面的故事里,JD太详细,会被别人直接抓出技术栈?所以,这也是出于行业的特殊性,不得不这么干啊!
|
||||
|
||||
小厂JD潜规则
|
||||
|
||||
小厂的潜规则则刚好相反。
|
||||
|
||||
小厂自由奔放很多,不用考虑那么多PR相关的事情,极端的特别小的厂,逼急了甚至都敢倒闭。可是,针对人员要求,他们的要求则极为精准,恨不得连你之前用哪个框架都有限制,巴不得天下候选人都是为自己量身定制的。
|
||||
|
||||
此外,小厂对大厂候选人有时候迷之崇拜,有时候又坚决不用——当然,大部分情况下是因为薪资接不住。
|
||||
|
||||
爬虫反爬虫JD分类讨论
|
||||
|
||||
了解了大厂和小厂的潜规则之后,我们JD的改进方向就有了。我们按照大厂和小厂的爬虫、反爬虫细分下,分别来看。
|
||||
|
||||
大厂反爬虫
|
||||
|
||||
首先第一个,大厂的反爬虫。
|
||||
|
||||
大厂的优势是,只要应聘者聪明,一切皆可培训。那么大厂写JD这件事其实就很简单了。这个时候,他有两个选择:
|
||||
|
||||
|
||||
JD直接要求招反爬虫的人
|
||||
自己不写JD,在安全和前端的求职者里面去捞人
|
||||
|
||||
|
||||
首先第一个,自己写JD招人。秉承着大厂一切含糊处理的精神,这里举一个反爬虫的例子:
|
||||
|
||||
|
||||
了解前端反爬虫对抗,有实际对抗经验
|
||||
|
||||
|
||||
这里并没有说用什么办法对抗,也没有说我们希望如何对抗。是重规则引擎,还是重前端加密?实际上,都是可以的。
|
||||
|
||||
事实上,这类JD只是用于初步筛选一下应聘者的技术栈点在了哪里。从前面所有课程我们可以看到,反爬虫的天赋技能学习,主要是点前端的,但是顺便也要点一部分后端。因此两部分都是有要求的。
|
||||
|
||||
那么,在上面这句话的要求下,其实还需要再补充一句:
|
||||
|
||||
“针对数据库访问,缓存以及日志系统有自己的见解”
|
||||
|
||||
为什么一定要提自己的见解?
|
||||
|
||||
因为后续HR在拒绝面试人的时候,如果面试人不依不饶非要给个说法,HR还可以在“自己的见解”上面发挥空间。当然,这只是用于兜底的,大部分候选人都很忙,同时在面好多家,没有时间和HR扯。不要妄自尊大觉得自己同时面了很多求职者,就觉得自己牛了。实际上,求职者也同时在面多家。这是一个多对多的关系。
|
||||
|
||||
最后关于薪资。大厂薪资其实相对是比较透明的,没有太多的议价空间,大家也不是很在乎。最终,大家还是以面试结果定级为准。
|
||||
|
||||
大厂爬虫
|
||||
|
||||
好,终于到了大厂爬虫这个十分尴尬的分支了。
|
||||
|
||||
十分讽刺的是,大厂通常不对外承认自己有爬虫团队——虽然为了避免热度,也不特意去否认。不过,他们确实也在招聘平台上放出了大量的爬虫工程师岗位。目前有的大厂已经在注意这类岗位带来的PR风险并尽量避免了,而有的大厂却依然不当回事,直接挂着职位。
|
||||
|
||||
其实,正确的做法应该是在反爬虫的JD里顺便招爬虫工程师。不过,那样效率太低了,大部分情况下,大厂还是在直接招聘。所以我们还是来看一下这种情况下的JD。
|
||||
|
||||
举个例子。随手找到一个JD,就不列举公司名称了。它是这么写的:
|
||||
|
||||
|
||||
五年以上爬虫工作经验,精通Java开发-
|
||||
丰富的电商数据爬取经验-
|
||||
熟悉各类反爬虫策略,并有丰富的反反爬虫实战经验
|
||||
|
||||
|
||||
这段JD直接告诉了全世界:他们在电商领域有个竞对,并且他们在爬竞对数据。
|
||||
|
||||
那么如何修正这个问题呢?
|
||||
|
||||
很简单,第二条直接删掉即可。这样即使你在招爬虫工程师,别人也不知道你要爬谁。你完全可以说:我们有个合作伙伴,因为API来不及开发了,不得不用爬虫来做。虽然大家都知道你在撒谎,你也知道大家都知道你在撒谎,可是你就是可以继续撒谎,能怎么样呢?
|
||||
|
||||
何况,电商爬虫属于通用爬虫,电商本身并没有什么与众不同的地方。这一条完全是多此一举。
|
||||
|
||||
除此之外,这个JD还能分析出什么?
|
||||
|
||||
是的,他们使用的爬虫框架是Java。没错,不是Python,不是Node,是Java,这个非主流的爬虫语言。
|
||||
|
||||
一旦锁定了语言,那么他使用了什么框架,范围就缩小了很多。你可以逐步检测特征,慢慢就能检测到他用的是什么框架了。如果不说是什么语言,全世界所有的框架一个一个试,你要试很久了。
|
||||
|
||||
那么如何修正这个问题呢?
|
||||
|
||||
有两个办法,一个依然是删掉,另一个是,有意指定一个错误的语言来误导对方。
|
||||
|
||||
所以呢,你可能会问我,会不会他们实际上使用的并不是Java呢?这个问题提的非常赞,虽然我也不能保证什么,不过,只能说,试试检测Java,并不亏哦!
|
||||
|
||||
我们再来看一个正面例子:
|
||||
|
||||
|
||||
负责爬虫系统的核心技术研发,支持海量数据采集分析,实现业务赋能。-
|
||||
负责互联网资源特征挖掘,包括页面特征,价值,变化趋势等等-
|
||||
设计各种策略与算法,提升爬虫系统资源收录与更新效果。
|
||||
|
||||
|
||||
你看,这个JD和上面的JD比起来,就更“大厂”了一些,不但啥细节也没透露,还说了一大堆没用的废话。换言之,不说人话,这正是大厂在PR压力下的生存之道。
|
||||
|
||||
小厂爬虫
|
||||
|
||||
小厂的爬虫就嚣张跋扈了很多。
|
||||
|
||||
我们刚刚提到JD提爬虫会引发风险。注意,这里的风险大部分不是法务风险,仅仅是PR风险而已。要知道,走法务流程,证据是十分重要的。你不能说我发布了一个JD说要招爬虫工程师,那就证明我已经有爬虫团队了对吧?更不能说我已经在爬竞对了。因此,小厂的JD你可以尽可能精确要求候选人需要什么技能。
|
||||
|
||||
还是举个例子:
|
||||
|
||||
|
||||
一年以上爬虫相关经验,Python优先-
|
||||
_(实际上他们就是在用_Python)*-
|
||||
-
|
||||
熟悉各种抓取技术,熟练使用正则表达式从各网页中提取信息-
|
||||
(他们真的在用正则!因为正则真的很快!)-
|
||||
-
|
||||
了解JS逆向以及App逆向-
|
||||
(说明他们同时抓竞对两个版本,很可能还存在跨平台比价)-
|
||||
-
|
||||
对用户增长理念认同者优先。
|
||||
|
||||
|
||||
这个JD我们可以得出结论:他们在用Python抓取竞对,同时抓取JS和APP,而且很可能存在跨平台对比。同时,因为使用的是正则,要么他们爬虫水平特别棒,要么竞对反爬特别不给力。
|
||||
|
||||
但是需要修改吗?不需要!
|
||||
|
||||
小厂怕啥啊,逼急了敢倒闭的主,你拿个JD去起诉人家,法官都要笑话你啊。
|
||||
|
||||
这样精准的描述可以快速拿到合适的人选。虽然反爬虫方搜一下你的JD就知道你的玩法了,但是一般说来,他也没什么办法啊,不然也不会沦落到用正则就能直接提取出网页信息的地步。如果爬虫能被逼到起浏览器抓取,那怎么着JD得要求xPath能力吧?或者其余选择器。
|
||||
|
||||
不过如果想再优化一下,也是可以的。你可以多加点信息,然后面试的时候再筛一下人。例如,你可以说熟悉Python,Java,XXX……等等语言的优先。即使这些语言你不用,大不了简历筛选不通过嘛。就算简历筛选过了,还有面试呢,一面就能拦住,不要虚。
|
||||
|
||||
加餐:小厂反爬虫
|
||||
|
||||
这个加餐加得我非常纠结。
|
||||
|
||||
因为原则上来说,小厂很少做反爬虫。能玩得起反爬虫的,基本上都成为大厂了,至少是垂直领域的老大。所以,小厂反爬虫……真的在这个世界上存在吗?
|
||||
|
||||
但是很多小厂找我寻求过技术支持。因此可见,他们虽然玩不起,但是还是存在这个需求的。
|
||||
|
||||
但是小厂的反爬虫真的出不起成本。因此我的建议是,不如干脆让爬虫leader兼职反爬虫,带一个人顺手做做就好了。反爬本来就是一个烧钱的项目,ROI又极低,小厂,尤其是创业公司,本来现金就非常宝贵,干嘛非要砸这个钱呢?
|
||||
|
||||
因此,需要在爬虫的JD里面加一句:“能同时实现反爬虫需求”。这就足够了。
|
||||
|
||||
自驱
|
||||
|
||||
自驱这个词已经被一些大厂玩的快成为贬义词了。但是,这个词本身的含义是很正面的。假设你是一个爬虫或者反爬虫的 Leader,在你主动出击寻找对应的人才的时候,完全可以因人设岗。这个情况下,你就不需要写JD了。因此,你也就不用为这个问题苦恼了。
|
||||
|
||||
嗯,是的,我曾经去面试过一个反爬虫的岗位。他们的JD,写的是:前端开发工程师……
|
||||
|
||||
小结
|
||||
|
||||
这一节,我们主要探讨了大厂与小厂,爬虫与反爬虫,所有情况下的JD写法。
|
||||
|
||||
由于大厂对PR风险考虑更高,小厂对人员精准、降低用人不匹配问题的要求更高,因此大家各有各的写法。大厂更偏向于通用描述,小厂更偏向于详细要求每一个细节。
|
||||
|
||||
总体来说,反爬虫JD可以写得细致,而爬虫JD则要考虑法务风险,尽可能不要提“破解”,更要尽量做到不暴露自己的技术栈与框架,这是几个基本原则。
|
||||
|
||||
思考题
|
||||
|
||||
好了,又到了愉快的思考题时间。还是老规矩,三选一。
|
||||
|
||||
|
||||
一个公司,发了一个JD,要求应聘者同时做过爬虫和反爬虫,你认为他们实际上想招哪一个?
|
||||
你和HR说要招一个爬虫工程师,HR直接去网上搜了个JD。这样最坏可能引发什么问题?
|
||||
如果真的用JD做证据起诉对方爬虫团队,居然还赢了,那么你觉得最大的可能性是爬虫团队犯了什么错误?
|
||||
|
||||
|
||||
期待你在评论区的分享,我会及时回复你。反爬无定式,我们一起探索。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
183
专栏/反爬虫兵法演绎20讲/18如何搞定老板(上):如何编造虚无缥缈的OKR?.md
Normal file
183
专栏/反爬虫兵法演绎20讲/18如何搞定老板(上):如何编造虚无缥缈的OKR?.md
Normal file
@ -0,0 +1,183 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
18 如何搞定老板(上):如何编造虚无缥缈的OKR?
|
||||
你好,我是DS Hunter。
|
||||
|
||||
众所周知,每个项目创建的时候,都要频繁的设定目标,即使这些目标每天都在变化,刚设置完就已经没用了。但是,上层的大老板没时间细致地去管所有的实现细节,他们只能通过纸面上的目标设定、执行计划,近似地去猜测一个项目是否值得投入。所以,即使你觉得这些汇报技巧让人不屑,也依然不得不遵守这个世界现有的规则。
|
||||
|
||||
我们在13讲曾经提到过,反爬虫主要的收益包括:信息保护,商业优势,竞对压制以及竞对爬虫的资源消耗,这四点的可操作性是逐个递增的,我们这一讲也会主要通过这些方面来进行讲解。而这一讲,不但会涉及OKR相关的思路,也会有一些ROI的计算。
|
||||
|
||||
注意:你设定的目标能否说明老板,并不是因为你的理论多么完善,执行多么到位,更多的是领导内心想被你说服。这也是说服别人的常用技巧。
|
||||
|
||||
我们先来看一个战国策的例子:《东周欲为稻》
|
||||
|
||||
|
||||
东周想种水稻,西周不放水,东周为此而忧虑。-
|
||||
-
|
||||
苏子就对东周君说:“请让我出使西周说服放水,可以吗?”-
|
||||
-
|
||||
于是去拜见西周君,说:“您的主意打错了!如果不放水,反而使东周有了致富的机会。现在东周的百姓都种麦子,没有种其他东西。您如果想坑害他们,不如突然一下子给他们放水,去破坏他们的庄稼。放下了水,东周一定又改种水稻;种上水稻就再给他们停水。如果这样,那么就可以使东周的百姓完全依赖于西周而听命于您了。”-
|
||||
-
|
||||
西周君说:“好。”于是就放水。-
|
||||
-
|
||||
苏秦得到了两国赏金。
|
||||
|
||||
|
||||
这个故事在战国策里算一个简单易懂又经典的例子了。虽然战国时期,人心不古,欺骗成性不应学习,但是,这类说服别人的技巧还是值得我们深思的。
|
||||
|
||||
西周君是被道理说服的吗?不是的,苏秦并没有提任何天下苍生人民疾苦之类的大道理,反倒是直接和他谈起了利益以及他内心真正的关切。而苏秦说的这些话是真的能实现吗?这也很难说。但是事实是,苏秦的确说服了西州君,完成了这一游说工作。
|
||||
|
||||
当然,这样可能会有一些后遗症,比如西周最终真的卡东周脖子怎么办?但是不管怎么说,“说服”这个动作已经成功了。西周卡脖子的事情……没准是下周的事情下周再说呢?或者也许到时候西周人员变动已经忘了这个事情了?这谁说得准呢。
|
||||
|
||||
眼下,我们说服老板也是一样。
|
||||
|
||||
很多人都会吐槽:老板不行啊,肉食者鄙啊,就只知道看眼前利益,我去和他说,他也不听。这里要注意啊,你说的这些道理,老板真的不知道吗?这可不一定哦,除非存在强烈的信息差,否则大部分情况下是因为他没有更好的解决方案,不得不牺牲一部分。而你坚持的刚好是被牺牲的这一部分。
|
||||
|
||||
你要想说服他,最重要的是让他觉得,应该按照你说的去做,而不是让他改变主意听你的话——毕竟他可能本来就知道你说的是对的。由于每个老板想要的都不一样,我们没办法给出统一答案,这个需要你平时观察老板的核心需求来自己想办法处理了。换言之,搞清楚老板的痛点在哪里。
|
||||
|
||||
我们还是以完成事情作为第一要素,而不是滔滔不绝的讲大道理和道德观。这个就像《三体》里一样,程心的很多道理都是对的,但是最终我们还是要靠罗辑来拯救世界。
|
||||
|
||||
当然了,人们并不感谢罗辑。所以,你愿意做罗辑吗?
|
||||
|
||||
信息保护
|
||||
|
||||
明白了“编造”的最终目的之后,我们就要说一下具体的写作方向了。
|
||||
|
||||
信息保护是最原始的反爬需求。事实上,也是唯一合理的需求。是的,另外三个,多多少少都有点忽悠老板的成分在。
|
||||
|
||||
如果你想通过这一点来做OKR立项,说服老板,那么意味着你要放弃一个能力:随机放过。
|
||||
|
||||
我们前面提到过,针对爬虫,我们会随机放过一部分。但是如果你的目标设定为信息保护,那么就不再有任何理由放过爬虫了。
|
||||
|
||||
可能你会说了:老师,这个道理我倒是懂,可是这个信息保护如何量化呢?没法量化,我没法写OKR啊。
|
||||
|
||||
注意了,OKR可量化,是一个常见的误区,虽然很多公司的确是这么操作的。事实上,OKR不叫可量化,叫可衡量。这两者之间差别很大。
|
||||
|
||||
为什么这样说呢?
|
||||
|
||||
因为,这个世界并非一切皆可量化。OKR的核心是什么?是O来指导目标,然后KR来支撑自己的目标实现。
|
||||
|
||||
举个例子,你说:我的O是减肥,减重多少公斤。这是否是一个好的O呢?并不是,因为减重量多种方式,少喝一点水,体重掉的也很快,但是这并不健康,与我们的目标背道而驰。这个时候,减重多少公斤其实是一个KPI,而不是OKR。
|
||||
|
||||
再比如:创建高战斗力的团队。这是否是一个合格的O呢?出乎意料的是,这其实是一个合格的O。虽然他无法量化,但是战斗力是可衡量的。简而言之,哪个团队战斗力强,其实大家是能比较出来的。这个比较不一定是一个数值比较。
|
||||
|
||||
我们再反过来提一下:如果O真的完全可量化,那么OKR和KPI不就没有区别了吗?当然了,有些公司就是拿OKR当KPI来用。不过这就是另一件事了。
|
||||
|
||||
基于这个道理,你要记住:不要追求可量化。否则,你制定的就是一个KPI。当然,也不要因为听了这个理论就诋毁量化,走向反面的极端,这也是不对的。
|
||||
|
||||
好了,既然已经明确了O是可衡量的。那么,如何衡量自己的信息保护做得好不好呢?
|
||||
|
||||
这个其实就是KR的部分了。KR是支撑O的,理论上说,所有的KR如果都完成了,那么O一定完成。从方法论角度来说的确如此,但是世界很复杂,这一点通常做不到。我们试着考虑下:信息保护这个O,最关键的result是什么?
|
||||
|
||||
|
||||
竞对没有抓到自己的数据
|
||||
竞对抓取到的数据是错误的
|
||||
自己随时拥有控制对手的能力
|
||||
|
||||
|
||||
而这些result,本身都极难在线上检测。因此,我们的检测就被逼到了线下。线下,我们主要的合法调研方式就是调研合作伙伴。一般说来,竞对抓取到数据之后,会与合作伙伴共享,或者至少是用马甲公司进行共享。而在线下进行调研,就可以计算出大致的防护效果。
|
||||
|
||||
这个办法在实际操作的时候,难度极高,受益最低,因此是最不推荐的。但是为什么我们还要讲这一点呢?因为,如果你们的项目是大老板支持的,只是需要一个立项的借口,那么这个理由是最优秀的,人人都懂。
|
||||
|
||||
由于不需要“说服”老板,只是要去给老板撑场面,那么自然要选这个最庞大的目标。
|
||||
|
||||
商业优势
|
||||
|
||||
商业优势就相对更容易写一些,这个更多的是价格优势。
|
||||
|
||||
所谓价格优势,指的就是,相同的商品,对方卖得比你贵。这个可以在侧面反映反爬虫的效果。但是有一个问题,那就是,在做这类比价的时候,自己的价格你是可以得到的,那么对方对的价格你如何知道呢?
|
||||
|
||||
你可能会说:老师这个我熟,我只要写个爬虫就行了。
|
||||
|
||||
所以,这里又牵扯到一个问题:你的爬虫准吗?
|
||||
|
||||
面对这样的质疑,其实相对还是比较好解决的。你只要选择人工抽样即可。当然了,实际上我们讲过,人工操作也是有被反爬控制的可能性的,例如真人判定那一章的技巧。
|
||||
|
||||
这里又存在如何“说服”老板的问题了。
|
||||
|
||||
前面我们提到了,不同的老板有不同的需求。但是通用的情况下,老板有个共同的需求,那就是:要应对他的老板。因此,我们可以使用一个通用的利益来劝老板,那就是:盈利。
|
||||
|
||||
是的,商业优势本质上是转为盈利的。你的产品比竞对便宜,那么用户就会来你这里购买。每降低一定的价格,就会有更多的人来自己这里购买。这个属于初中常见的求函数最大值最小值问题,具体做法就不单独讲了。你需要做的就是:证明,每降低一块钱,到底有多少人来自己这里购买?
|
||||
|
||||
这个时候,我们传统的A/B测试,就要发挥作用了。相同的商品,竞对卖100,你可以针对部分人卖100,部分人卖99,然后分析转化率。后续再慢慢变更价格,就可以得到数据了,用于后续的决策。
|
||||
|
||||
AB测试虽然很强大,能够真正实现数据驱动,但是他也会带来一个严重的副作用,那就是:“杀熟”的PR风险。
|
||||
|
||||
杀熟这个事情,对于企业来说是最头疼的。任何一个人,只要看到别人的价格比自己低,就会认为自己被杀熟了。你可能觉得,这是一种被害妄想症,但是,你不能控制用户的思想,只能降低这个概率。
|
||||
|
||||
具体来说,可以让这个价格差变得可解释。例如,随机立减、天降折扣,都可以。只要有个“随机”的名义,就很难投诉得起来。此外,A/B测试不需要真的设置50%的流量做,也可以用小流量来测试,这也更符合“天降折扣”的说法嘛。
|
||||
|
||||
竞对压制
|
||||
|
||||
竞对压制,虽然听起来似乎并不好算收益,但是这却是老板最喜欢的目标。要知道,不止程序员本身有内卷,商业本身也是一个内卷的过程。而内卷的赢家,不仅仅要学会创造收益,更重要的就是,让别人亏本。
|
||||
|
||||
竞对压制本身也是不好衡量的。但是配合上一个,商业优势,一起来计算的话,就容易了一些。
|
||||
|
||||
现在,你能计算出自己多拉了多少个用户了,我们也可以算出函数最大值了。如果你想再激进一点,想降价更凶一点怎么办?这个时候,ROI已经打不平了。所以我们要做的,是在ROI里计算对方的损失。
|
||||
|
||||
简单的来说,每多一个用户来你这里下单,都可以认为是竞对损失了一个客户。而这种损失,在很多公司是可以加权计算自己的收益的。但是一旦进行了这个计算,你就不方便再计算商业优势的收益了,否则会被质疑双倍计算。不过加权的一般都大于不加权的,所以放弃商业优势收益算这个,并不亏。当然也有的公司会把竞对压制收益算为附加收,这样也更简便一些。
|
||||
|
||||
严格来说,竞对压制这种计算方式,有一点耍流氓,因为你其实并不确定你这里新增的用户是否是从竞对那里叛变过来的。不过好在有一点,就是如果有人想质疑你,他也没法证明这个人不是从竞对叛变过来的,尤其是一些领域是被两家公司共同垄断的,非A即B,没有别家可选。
|
||||
|
||||
所以,这里又存在一个问题:如果你想用这个理由说服老板,你的核心方向,应该是什么?
|
||||
|
||||
这里老板的痛点,大部分在于前面说的“质疑”,能走到这一步,说明老板是很挺你的。但是他怕别人质疑这种算法,导致没法接。你需要做的就是调研好一切,别人在任何一个角度质疑,都提前为老板想好应对的话术即可。
|
||||
|
||||
可能你会说:老师你这不是教我们忽悠人吗,这不是向上管理吗,我们公司明令禁止向上管理啊。
|
||||
|
||||
没错,这的确就是向上管理,但是向上管理未必是贬义词。有的公司禁止向上管理,其实就是不想让大家学会如何走捷径。
|
||||
|
||||
但是你想过没有,他们是不是发明了一个词叫向上对齐?这不是一个意思吗?
|
||||
|
||||
竞对爬虫资源消耗
|
||||
|
||||
竞对爬虫资源消耗,就是最后一个办法了。虽然落地性最好,但是ROI最低,基本是锦上添花的存在,而不是做为反爬团队的主ROI。
|
||||
|
||||
我们在开篇词就提过资源的定义:机器成本与人力成本的总和。当时我们也提到过,机器成本其实并不高,但是人力成本是水涨船高。因此,尽可能按照破解速度来计算人力成本。例如,N个人,平均每次发布要破解X小时,这段时间他们干不了别的需求,基本上就是和你消耗。用N*X即可。
|
||||
|
||||
X可以用“每次发布后多久被破解”这个时间来计算。注意,这个计算其实你是占优势的,因为理论上说应该从发现开始计算,如果对方有M个小时,没有发现你的变更,那么这段时间其实他是不知道你变更了的,不应该计算在X内。但是,你也不知道M是多少对不对?所以不要多事去提这个M。如果有人质疑再说。
|
||||
|
||||
真有人质疑的时候,你可以用“对手消耗不高于多少时间”来做统计口径。这个在交流中会给人一个错觉,认为天花板就是实际值。这是人类的一个常见误解。举个例子,你问我一个月能赚多少钱,我说不到5万吧。你是不是就觉得我一个月赚4万多?实际上没准我就赚3000呢?也是不到5万啊!
|
||||
|
||||
那么,我们的核心问题就是:N如何取?
|
||||
|
||||
实际上,最靠谱的办法是抓出有多少人在调试你的站点。但是这样做太难了。线上太难的办法,依然可以选择线下来处理。具体做法,就又是社会工程学了……例如,让猎头去挖一下竞对的人……让他们来面试,套一下方案什么的……
|
||||
|
||||
加餐:网站稳定性
|
||||
|
||||
网站稳定性,只适用于过于疯狂的爬虫。例如,有些爬虫控制不住,可能爬挂你,你就记下来他们都是谁。后续你拦截了这类爬虫,统计出消耗的资源,算出如果不拦截,这个爬虫爬挂网站的概率有多大,就能直接算出网站不稳定导致的损失了。挽救的损失,都是你的收益。
|
||||
|
||||
虽然理论上这个很容易被质疑,但是实际上并没有人会发声。因为质疑点主要在于:我怎么知道那个爬虫是不是你自己写的?但是实际上,这类质疑攻击性过强,容易给人一种对人不对事的感觉,所以一般来说不是深仇大恨,没有人愿意惹这个麻烦。
|
||||
|
||||
如果真碰到了,你也可以搬出企业文化来怼他,毕竟这种对人不对事的质疑,扔到任何一个公司都一定是违反企业文化的。而企业文化这个东西又非常好用……怎么说呢,道德绑架的东西都很好用……
|
||||
|
||||
小结
|
||||
|
||||
这一讲比较杂,也比较虚,但是管理类的事情就是这样,往往没有那么脚踏实地,更多的是互相说服。毕竟,如果人人都讲道理,都自然而然地走向正确的方向,那要领导层干什么呢?就是因为人类是一种复杂的生物,所以才需要管理。
|
||||
|
||||
这一讲,我们主要提了四种不同的OKR编造方式:信息保护,商业优势,竞对压制和竞对爬虫资源消耗。竞对爬虫资源消耗已经是很锦上添花的方向了,我们还加餐了更加锦上添花的网站稳定性方向,来证明反爬虫的重要性。
|
||||
|
||||
还是那句话:也许你在这里学了一些自己之前认为不合适的做法。但是,最终证明一件事合适不合适,看的是结果,而不是过程中你做了什么。就像章北海,为了拯救人类,忍辱负重做了大量看起来不合适的事情,但是最终大家依然觉得他是个英雄,对吧?
|
||||
|
||||
这个世界,需要更多的英雄。
|
||||
|
||||
思考题
|
||||
|
||||
好了又到了愉快的思考题时间。由于管理的特殊性,我们这三道题可能有些不正经,但是也许你有一天又会觉得它正经。所以,你按照你当前的理解来回答吧。我会尽可能按照你的思路来回复哦!
|
||||
|
||||
|
||||
ROI计算中有大量的“猜测”数据,如果别人质疑你预设的数值,你一般会如何回复他?
|
||||
网站稳定性,可能会被认为是运维的业绩,而不是反爬的业绩。你如何证明这是反爬的功劳?
|
||||
如果你的领导一直很支持你,忽然有一天疯狂的质疑你的数据,你觉得是因为他忽然想明白了,还是有什么苦衷呢?
|
||||
|
||||
|
||||
期待你在评论区的分享,我会及时回复你。反爬无定式,我们一起探索。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
173
专栏/反爬虫兵法演绎20讲/19如何搞定老板(中):如何组建团队.md
Normal file
173
专栏/反爬虫兵法演绎20讲/19如何搞定老板(中):如何组建团队.md
Normal file
@ -0,0 +1,173 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
19 如何搞定老板(中):如何组建团队
|
||||
你好,我是DS Hunter。
|
||||
|
||||
上一讲,我们讲了如何编写合适的OKR。如果你运作得顺利,那么你应该申请下了项目,申请了HC。结合再前面的JD如何编写,你可能招到了一些人。目前为止,你可能认为自己的团队已经组建好了。
|
||||
|
||||
且慢!不是这样的,并不是人凑够了就叫团队!
|
||||
|
||||
就像你打游戏一样,只要凑够了5个人,能去打排位了,这就是一个好的团队了吗?并不是。随着不断的掉分,可能内讧就产生了,甚至刚到逆风局的时候,内讧可能就已经开始了。慢慢的,团队人数越来越少,凑起来的团队也烟消云散了。
|
||||
|
||||
因此,我们不但要凑够数量,还要保证质量,才能让团队更稳定。
|
||||
|
||||
我们按照时间线一个一个来讨论,从面试到离职,看一下每一步应该如何避雷。
|
||||
|
||||
第一步:人才获取
|
||||
|
||||
先来看第一步,人才获取。根据候选人的不同,我们的人才获取途径主要有面试进来、转岗进来和主动挖人进来三种。
|
||||
|
||||
面试
|
||||
|
||||
反爬虫面试和别的部门是不同的。除了常规考核以外,还有两点要注意:第一要防止自己套面试者方案,引发PR问题。第二是要防止面试者套自己的方案。
|
||||
|
||||
套面试者方案比较常见。但是,如果你本来没有想套对方的方案呢?结果对方觉得你只是想套方案,没有诚意,轻则不想来,重则发帖抱怨,引发PR问题。
|
||||
|
||||
反爬毕竟是个非主流的方向,而且做法大同小异。即使做法截然不同,在几十分钟的面试里,因为信息获取不全,也可能会给人感觉,大家做得差不多。而我们又提到过,反爬更像一个魔术,一旦解密了,就感觉不到什么技术含量。所以面试者通常对“套方案”戒心很重。和前一讲我们说过的杀熟一样,一旦用户产生了这个戒心,无论你说点什么,他都怀疑你在套方案。
|
||||
|
||||
那么如何消除这一戒心呢?
|
||||
|
||||
避免猜疑,最好的办法就是坦诚清晰地直接说出来,而不是用各种方式欺骗对方。因此,你可以在开篇直接说类似这样一段话:
|
||||
|
||||
|
||||
“我们都是做反爬的,我们都知道,很多反爬技巧属于公司机密,不方便透露,部分数值也可能引发泄密风险。因此,在整个面试过程中,你可以主要阐述你们的思路,尽可能避开具体实现方式。至于数值,你可以脱敏后再说,或者直接用较为主观的描述,例如非常好,较好,一般,等等,而无需说出具体数值。毕竟,我们也不希望未来你去面试别的公司的时候,带着我们的数值说给别人”
|
||||
|
||||
|
||||
这样坦诚的开场白,会让候选人尽量放下戒心,能够与你坦然地继续交流。此外,还给了对方一个心理暗示,那就是,我们已经把你当自己的员工来看待了。这样,也有助于对方发挥。
|
||||
|
||||
这里要注意一点:面试者紧张,吃亏的不仅仅是面试者,企业也很吃亏。因为很多工作并不需要社交能力,因为缺乏社交能力而导致紧张,进而导致发挥失常,会让你错失优秀的人才。
|
||||
|
||||
那么,如何防止对方套自己方案呢?
|
||||
|
||||
一般套企业方案,都是在“你有什么问题想问我吗”这个环节。因此,解决方案还是一样的,坦诚清晰地说:你有什么想问我的吗,除了反爬相关的问题都可以。
|
||||
|
||||
应聘者只要情商不堪忧,就能理解你。所以不用担心。
|
||||
|
||||
那么,我们的正题就来了:面试问什么?
|
||||
|
||||
这里你要明白一件事情,那就是反爬并不是一个有固定套路的行业,因此面试的时候大家有不同见解,是很正常的。你需要考察的,反倒是计算机基础知识以及灵活的处理技巧。因此比较建议的有:数据结构,前端基础,一些“脑筋急转弯”。但是不同的是,不要预设标准答案,每个问题都回答到标准答案的人,应该是很难做好反爬的,我们需要的是与众不同,是创新。
|
||||
|
||||
转岗
|
||||
|
||||
除了面试以外,转岗也是一个非常重要的人才引进途径。
|
||||
|
||||
转岗可以分主动转岗和被动转岗。针对主动转岗,我们主要考核的,与面试区别不大。只是除了常规的基础之外,还要加一些公司框架工具的使用经验等内容。因为大家都是一个公司的,部分框架工具也都是共用的,如果这些使用经验少,那其实就说明了一点:代码写得少。你不希望组建团队的时候招来的是只会写文档的人吧?
|
||||
|
||||
而被动转岗,通常指的是因为考评不好,被迫选择变更一个岗位的人。这类人其实比较麻烦,一般我不建议用。因为大部分情况下,双方的最优解其实都是:离职,换个公司。要知道,你收了他,就要给予他一定的承诺,而这些承诺通常对于团队已有的人是不公平的。
|
||||
|
||||
当然,如果真的碰到大神级别的(但是这种人如果被打了低绩效,你应该考虑的是,是不是公司出了问题呀,你应该先想想自己的退路了。当然这是题外话),也是可以额外考虑的。在充分与团队做好沟通之后,可以走常规流程。
|
||||
|
||||
这个时候面试的内容主要可以围绕绩效问题来讨论。不要怕不好意思说,首先你们是一个公司的,大家没什么可藏着掖着的。其次,他很可能在外面也在找工作,和你谈完之后没准接了外面的offer直接就走了。但需要注意的是,针对低绩效,他的抱怨有多重。低绩效一定会有抱怨,这是人之常情。但是如果全篇都在抱怨环境问题,那么你就要慎重考虑了。
|
||||
|
||||
主动挖人
|
||||
|
||||
主动挖外面的人,是一个周期很长的事情。所以,你要挖的,应该是非常核心的人物才行,不然对不起这么长时间的跟踪。
|
||||
|
||||
当然,即使是猎头,也没法完成这种定向的挖人计划。你想想,首先你要对他们足够了解,其次还要引发他对公司的不满,还要在恰当的时间接他过来。这一套流程下来,你可能会怀疑:这真的是人类干得出来的事情吗?
|
||||
|
||||
还真可能。这就是社会工程学,你做反爬的必备技能啊。一个最简单的例子,就是你注册他们公司的脉脉,进入他们的职言区。剩下的,就是一场剧本杀了。
|
||||
|
||||
第二步:新人培训
|
||||
|
||||
假设你的面试结束了,保密协议也签了,那么就到了新人培训的阶段了。
|
||||
|
||||
普通的新人培训有两种:第一,学习各种基础知识,公司规范,然后慢慢上手;第二,直接扔上战场,在战场中接受培训。
|
||||
|
||||
反爬虫的团队与这些都不同。记得我们提到过的“套方案”问题么?你怎么知道这个新人不是来套两个月方案然后就走的呢?
|
||||
|
||||
当然,也可能他套了两年方案才走,这个就另说了。要知道,离职后的保密协议与在职的保密协议,用起来效果完全不一样。因此,要避免新员工快进快退。毕竟,他完全可以用“反爬太卷了”为理由离职,你也没什么好的阻止方案。
|
||||
|
||||
这个时候,新人的权限就很重要了。如果新人能够接触到所有的反爬系统,那么理论上说他就可以迅速摸清你们的做法,然后光速离职走人了。
|
||||
|
||||
因此,注意!反爬千万不要使用实习生!千万不要!
|
||||
|
||||
而你需要做的,其实很可悲,是要给新人提供一个蜜罐系统,这个系统可以用来熟悉生产环境,但是又与生产不同。一个比较好的做法,就是使用过时的系统,例如一年前的系统,给他熟悉。这样,回头给他正式系统的时候,也方便熟悉,也了解了历史的技术债,一举两得。
|
||||
|
||||
第三步:第一个任务
|
||||
|
||||
新人培训到了一定程度,你就可以给予他第一个任务了。
|
||||
|
||||
时间虽然不能太短,但是也别拖太长,不要第一个任务都拖过试用期,那就麻烦了。
|
||||
|
||||
第一个任务的性质,应该是一个非关键的需求。例如,线上策略测试。这种测试,即使他搞出问题,也不会引发生产故障。
|
||||
|
||||
可能你会问:埋点需求总可以吧?感觉这个也不会引发什么问题。
|
||||
|
||||
注意!埋点需求虽然本身不会引发问题,但是埋点错误可能导致无法发现生产问题。
|
||||
|
||||
举个例子,你让他改误伤埋点,结果他代码有问题,导致所有的误伤都报不过来。这个时候,刚好你们的一个反爬工程师动了规则引擎,导致大量误伤。但是从曲线上看,却是没有任何误伤报告的。这是不是意味着你们会耽误急救的最佳时间呢?这和生产引发的故障其实没有什么区别。
|
||||
|
||||
而线上策略测试则不同。首先,线上策略测试,测完了是入库的,暂时不用。其次,一个策略你不可能就测一次,下次测试就相当于校验了一次。最后,这个任务只动策略,不动框架。而我们前面提到过,框架应该提供足够的安全性,保证策略崩了也不会影响生产。
|
||||
|
||||
这样,新人就可以平安度过第一个任务了。
|
||||
|
||||
第四步:步入正轨
|
||||
|
||||
新人步入正轨之后,可能你就需要对他全面开放所有的技术细节了。毕竟,反爬团队也不会很大,你也没有太多可以藏着掖着的东西了。这个时候,他应该和一个正常员工一样了——参与整个系统,自己把控一切,注意安全。
|
||||
|
||||
这里需要注意的主要有两点,一个是战斗力问题,一个是带新人的问题,我们一起来看一下。
|
||||
|
||||
反爬团队人员流动频繁,出于保密需要又不能留下清晰的新人培训文档。因此,你可以理解为这个团队时时刻刻都在进行交接。一个模块,如果只有一个人知道怎么做,那就是危险的。你需要保证团队时刻处于技术交流的状态,或者说处于一个人人都知道每个模块如何做的状态。甚至,你也可以和爬虫团队密切交流,这就有点去中心化,分布式的感觉了。
|
||||
|
||||
这样做,固然会降低效率,但是这是值得的。要知道,人员离职导致的团队战斗力崩溃,才是最可怕的。就像你正开着五黑,但是团队大哥掉线了,那这仗还能打吗?
|
||||
|
||||
第五步:离职面谈
|
||||
|
||||
天下没有不散的筵席。尤其是反爬虫,散得会更快一些。
|
||||
|
||||
正常员工离职,离职面谈一般就是走个形式,无非就是青山不改,绿水长流,后会有期。但是反爬虫不同,这里拥有着大量的保密信息,如果离职人员带去竞对,对你们的打击是十分巨大的。因此,需要强调保密的重要性,必要的时候也可以带上法务或者人事一起。该签保密签保密,该签竞业签竞业,千万不要不舍得给钱。虽然这些钱可能会算入你的成本,但是永远不亏。
|
||||
|
||||
如果因为竞业问题导致ROI算不过来,可以和老板商量,操作转组再离职,也就是把成本转嫁给高收益的组。当然,如果你的老板是十分支持反爬的老板,他会同意这样操作的。
|
||||
|
||||
加餐:技术分享
|
||||
|
||||
好了,到了最敏感的话题了:反爬要不要出去做技术分享?
|
||||
|
||||
我猜99%的人会说:当然不要啊,反爬这东西,我分享了,别人就知道怎么做了。你前面说过了,魔术一旦被解密,就没有什么神秘的了。出于这个目的,我当然要低调。
|
||||
|
||||
没错,我前面强调过多次,爬虫要低调,反爬要低调。
|
||||
|
||||
但是你有没有想过,会不会去做分享才是低调的行为呢?
|
||||
|
||||
当你出去做了反爬的分享之后,全世界都看着你,你的竞对自然也盯着你的分享,试图找到你的技术突破口。
|
||||
|
||||
你在分享的时候,基本上也是知无不言,坦诚清晰地向全世界都讲述了自己的全部干货。全世界都知道了:哦,原来你们公司是这么做反爬的啊。于是纷纷按照你给的思路去做了。
|
||||
|
||||
但是,你给的思路里面,如果还有其它偷偷埋的一些小陷阱没有对外说出去,这算欺骗观众吗?
|
||||
|
||||
当然不算。如果说,漏说了什么事情就算欺骗,那这个世界几乎所有的演讲都是在欺骗观众啊!
|
||||
|
||||
这个时候,全天下的人纷纷在你预设的道路上,踩着你的陷阱,还全然不知,没有一个人肯回头去换一条路走。你觉得,这对你是好事还是坏事?反过来想,这是低调,还是不低调?
|
||||
|
||||
这简直就是一个大型社会工程学现场啊!
|
||||
|
||||
小结
|
||||
|
||||
这一讲,我们主要探讨了反爬团队创建中,一个新人从入职到离职的全过程。
|
||||
|
||||
你应该已经发现了,虽然人员管理并不是团队建设的全部,但是反爬人员管理的整个过程,却是和其余团队差别最大的一点。我们从新人的面试,培训,上手,工作,到离职,都给予了详尽的探讨。这里呢,我也给你准备了一个团队建设的关键流程笔记供你参考。
|
||||
|
||||
|
||||
|
||||
最后,我们还在加餐环节,探讨了技术分享的优势所在。当然了,也欢迎你未来参与到极客邦的各种技术分享中。分享时思想碰撞出来的火花,往往更加迷人。
|
||||
|
||||
思考题
|
||||
|
||||
好了,又到了愉快的思考题时间。老规矩,三选一。
|
||||
|
||||
|
||||
如果分享之后,对手纷纷跳入了你的陷阱,只有一个对手跳过了陷阱,走向终点。你觉得他是听了分享才过去的,还是一直能跳过陷阱?
|
||||
如果你给离职员工签竞业,被质疑乱花公司的钱,你如何解释这一切?
|
||||
主动挖人要认证竞对公司的脉脉,但是明显你没有他们公司的邮箱,你如何解决这一问题呢?
|
||||
|
||||
|
||||
期待你在评论区的分享,我会及时回复你。反爬无定式,我们一起探索。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
168
专栏/反爬虫兵法演绎20讲/20如何搞定老板(下):团队考核怎么做?.md
Normal file
168
专栏/反爬虫兵法演绎20讲/20如何搞定老板(下):团队考核怎么做?.md
Normal file
@ -0,0 +1,168 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
20 如何搞定老板(下):团队考核怎么做?
|
||||
你好,我是DS Hunter。这是本专栏正文的最后一讲了,恭喜你坚持到了最后!
|
||||
|
||||
在整个进阶篇里,你招好了人,搭好了团队,到了最后,你的团队也许已经获得了一定的业绩。而年底应该也到了,又到了愉快的发奖金时间。
|
||||
|
||||
对于没有做过管理的人来说,考评是一个很容易的事情。而做过管理的人都知道,这简直不是人干的事。
|
||||
|
||||
那么,考评到底哪里难呢?
|
||||
|
||||
员工对考评不满意,本质上就是预期管理出现了问题。每个人都会高估自己,可是考评的结果一般都会低估自己,这个落差是大部分人不能承受的——除非领导给的是考评的上限,否则一般都不满意。而考评上限,又只有有限的人可以拿到,因此,大部分人一定是不满意考评结果的,只是不满意的程度各不相同而已。
|
||||
|
||||
这个时候你可能会说:老师,我知道了,本质是预期管理的问题,那我降低他的预期,不是就能解决这个问题了吗?
|
||||
|
||||
恭喜你,无师自通了PUA的知识。啊,但这并不是一个好事情。
|
||||
|
||||
PUA能够帮你顺利度过考评,但导致的结果却是,被PUA的人真的认为自己能力不行,最终丧失成长的机会,而你会收获一个很听话,但是没什么战斗力的团队。
|
||||
|
||||
如果是做别的项目,也许这还可以接受。但是你负责的是反爬虫团队,这意味着一定不能没有战斗力。反爬虫没有战斗力,那还不如解散了。
|
||||
|
||||
因此,你可以试试和老板申请额外的考评流程。相信我,别的团队也许不行,但反爬团队是很容易申请下来的。至少,你可以申请免除差评。一般公司考核是按照总数来配平的,因此大的团队可以在总体上配平,局部小团队可以单独操作。不过不能对外公布,否则容易引发其余团队的抗议。
|
||||
|
||||
这里还是要注意:要想获得这种“特殊待遇”,你的业绩要够啊。不然就不要想了。
|
||||
|
||||
考评本质上就是分蛋糕的问题。你的蛋糕够大,怎么分大家都满意。你的蛋糕不够大,怎么分都不行。这个是大前提。而我们所有做法的目的,都是最大化地提升反爬虫这个团队的战斗力。
|
||||
|
||||
在你的蛋糕够分的情况下,我们来看下考评常见的一些问题。
|
||||
|
||||
FAQ 1:公开还是不公开
|
||||
|
||||
薪资不公开,并不是什么神秘的操作。几乎所有的公司都有“薪资保密”这一条规定。原因其实很简单,每个人都会高估自己的实力,因此即使按照能力定了完美的薪资,也会让所有人都感觉自己亏了。就像前面提的杀熟一样,有的人可能会有这种“被害妄想症”的心态。因此薪资不公开,似乎没有什么道理可讲。
|
||||
|
||||
不过,难道薪资真的是秘密吗?并不是。
|
||||
|
||||
事实上,线下大家讨论薪资,并不是什么稀奇事,只是表面上假装不知道而已。实际上线下已经一个个摸得差不多了。
|
||||
|
||||
那么,在这种“薪资似乎成了一个公开信息”的情况下,我们要不要干脆就公开了呢?
|
||||
|
||||
不可以!
|
||||
|
||||
虽然我们经常看到一些新闻,说某公司薪资是公开的,如何如何好,但是注意,别人能做到的事情,你不一定做得到,因为团队的文化氛围不一样。我见过有些团队,真的就毫无争强好胜的心理,彼此之间都嘻嘻哈哈的。后来一打听,哦,原来每个人工资都不高,也没啥好争的。
|
||||
|
||||
互联网公司,薪资方差非常大,很容易引发大家争强好胜的心理。所谓“不患寡而患不均”,就是这个意思了。因此,公司设定薪资保密这一点,其实是给你降低管理压力了。
|
||||
|
||||
何况,即使你真的克服万难,实现了“以能力定薪资”,那么你有一个量化的模型来考核反爬的能力吗?说实话,这个很难。有时候谁立功了,完全就是运气好,和能力没啥关系。也就是说,这个时候很容易就变成随机定薪了,会引发更大的不满。
|
||||
|
||||
所以,即使你可能现在心里不满意这种做法,觉得“如果我做了领导一定要改变这个世界的规则”,但是我还是建议你,至少,在刚做领导的前两年,不要试图去改变规则。
|
||||
|
||||
有些规则,自然有他的道理。
|
||||
|
||||
FAQ 2:升职加薪要不要分开操作
|
||||
|
||||
大部分情况下,升职一定加薪。而不升职的,按照规定,也有一部分人可以调整。
|
||||
|
||||
可能有些人就会疑惑了:唉,为什么我升职了,反倒不如没升职的人加得多呢?
|
||||
|
||||
这是因为大部分公司的升职,是给予Leader一个总包,总包之内随意分配。升职或者不升职,给予不同的上限。但是,注意,这就和你游戏里的攻击上限是一样的,你的攻击力是0-50,他的攻击力是0-20,你打的攻击力就比他高吗?不一定啊,你可能只打到了15,但他可能打到了20的上限,这都是合理的数值啊。换句话说,即使升职的人理论上应该涨得更多,但由于种种原因,还是会达不到上限。
|
||||
|
||||
那么,为什么要做这种奇怪的操作呢?
|
||||
|
||||
原因可能是多方面的,有可能是你画的大饼到期了要兑现,有可能是升职的人有额外的期权激励,等等。
|
||||
|
||||
那么你也许会问了:反爬团队需要这样操作吗?
|
||||
|
||||
这个问题的答案是:其实不是需要不需要,而是你根本无法避免这种事情。理论上说,如果真的追求公平,那就应该只有升职的才加薪。不升职的加薪,理论上说都是暗箱操作,因为这个不用公开,但是升职是公开信息。但是,你做不到绝对的公正,总是有一些让人为难的操作。
|
||||
|
||||
FAQ 3:要不要大锅饭
|
||||
|
||||
不要!
|
||||
|
||||
这个问题的答案其实相当明确。虽然我们前面提到了“不患寡而患不均”,可能你会觉得,大锅饭刚好解决了这个问题啊,每个人加一点,雨露均沾,大家都没有特别不开心。
|
||||
|
||||
但是,这样做的结果就是,每个人都觉得自己亏了。
|
||||
|
||||
记不记得我们刚刚说,要让团队更有战斗力?大锅饭的结果就是,每个人都觉得自己亏了,回头心思各异,人心散了,队伍不好带。
|
||||
|
||||
此外,大锅饭会导致一个温水煮青蛙的效果,最终大家都不肯离职。
|
||||
|
||||
当然了,大家都不离职,从公司管理角度来说,可能会觉得你工作做得好,人员稳定。但是,这是最优解吗?要知道,跳槽到外面,很多公司会卡30%的涨幅,但是你的大锅饭,能给几个人30%的涨幅呢?
|
||||
|
||||
我们做管理,切记不要贪图指标。很多指标其实并不合理,只是找不到更好的办法不得不定而已。大锅饭是最容易完成指标的,但是也是最容易让战斗力崩溃的。要知道,反爬拼的就是团队战斗力,这一点远远超过价值观和方法论。
|
||||
|
||||
那么正确的做法是什么呢?
|
||||
|
||||
正确的做法是,给头部的人最大程度的加薪,保证这些人持续输出战斗力。团队内所有的人,如果有离职倾向,尽可能挽留。但是,如果实在留不下来,也要真心祝福他们有一个更好的未来。毕竟,人生路漫漫,他们今天是你的下属,明天也许就成了你的上级。
|
||||
|
||||
当然了,别忘了签保密协议和竞业禁止。竞业禁止注意范围,只需要不去竞对即可,不要让人家没工作可找。
|
||||
|
||||
FAQ 4:如何正确的画大饼
|
||||
|
||||
画大饼,现在已经是一个贬义词了。似乎领导只会画大饼,不会做正事一样。
|
||||
|
||||
但是,画大饼,我们换个词来说——“构建长远的目标”,咦,是不是忽然就感觉没那么贬义了?
|
||||
|
||||
事实上,排除纯忽悠的画大饼以外,大部分情况下,大家感觉到的“大饼”,其实是正经的职业规划。只不过,很多人自己做不了职业规划,最终是Leader帮着给做了。而Leader没法帮你做五年、十年的规划,毕竟你也呆不了这么久。他只能帮你做个一年两年的规划。而一旦这个规划稍稍长远一点,就会给人一种画大饼的感觉。
|
||||
|
||||
虽然下属会误会,但是该做的规划还是要做。一个合格的Leader,最重要的就是帮助下属成长,少走弯路——至少不要走自己走过的弯路。
|
||||
|
||||
那么这个时候,你的下属面临的规划选择有:-
|
||||
|
||||
|
||||
有了这样清晰的规划,一切将不再沦为虚无缥缈的大饼。当然,最关键的是,你如果承诺了什么,那就一定要实现。如果因为一些原因不能实现了,例如你离开了岗位,那么也一定要把这个当“遗嘱”留给下一任,不论怎样,一定要实现承诺。Leader岗位,很多时候是靠信任度来支撑的。如果失去了信任,别人很难跟你去奋斗。
|
||||
|
||||
一旦能够兑现自己的承诺,那大饼也将不再是大饼,而是美味的蛋糕。
|
||||
|
||||
FAQ 5:下属虚线带人,要不要听取考评建议
|
||||
|
||||
虚线带人,是一个很奇葩的发明。部分公司为了避免层级过深,发明了扁平化这个做法。但是,毕竟一个人的经历是有限的,那么相应的,他的管理能力也是有上限的,所以就被迫发明了“虚线”这种玩法。也就是一个人下面带了几十上百号人,然后挑出小组长,小组长带人,但是小组长没有考评权,他们只有考评建议给你。
|
||||
|
||||
这种做法,我一直觉得很奇葩。为什么?你想一下,如果你的代码长度过长了,一个函数管理不过来,你会怎么办?
|
||||
|
||||
当然是抽取成子函数啊。
|
||||
|
||||
你会把代码用空格分开,假装他们成了不同的组,然后骗自己说:看,我每个组都不超过多少行哦!会这样自欺欺人吗?
|
||||
|
||||
肯定不会啊。
|
||||
|
||||
所以,为什么到了管理人的时候,就喜欢这么自欺欺人呢?
|
||||
|
||||
反爬也是一样的道理,我们是One Team,但是本身有分工的存在,如果你真的让一个人带了团队,那么就正常给他考评权利,不然下属给他干的时候,自己心里也很虚:我要不要好好听他的话?最后他又不给我考评,万一我一年白干了呢?
|
||||
|
||||
这样谈何战斗力呢?
|
||||
|
||||
但是假设你就是在这样的公司,公司制度不是你能够变更的。那么,你如何处理这个事情呢?要听取“组长”的考评建议吗?
|
||||
|
||||
正确答案是:当然要听取。
|
||||
|
||||
不但考评的时候要听取,更要提前很久就要告诉大家,99%的情况下你会直接使用他的考评,而不会进行变更。这样相当于授权给他,也就相当于给了尚方宝剑。这样,他才能真正意义上指挥的动其他的人,让大家发挥100%的战斗力。Leader这个岗位,权利与义务是对等的。你不能让他有义务对项目负责,但是又不给他任何权利——这不是欺负老实人吗。
|
||||
|
||||
小结
|
||||
|
||||
这一讲,我们谈了一些关于考评,也就是考核的相关事情。包括薪资的公开性,升职加薪分离操作的原因,大锅饭的坏处以及职业规划相关的讨论。在这里,我们要时刻记住一点:首先要让大家成长,让公司有收益,然后再考虑自己的指标。这个似乎说起来轻松,但是操作起来还是很困难的。毕竟,指标才是你的,其余的都是别人的呀!
|
||||
|
||||
你可能会说:老师,怎么感觉并没有提具体的考核操作呢?
|
||||
|
||||
主要是因为,各个公司的考核操作千差万别,但是最终还是给Leader留下了极大的发挥空间,因此知道了具体的指导思想,就可以在任何一家公司进行考评操作。注意,这一讲里面的推荐做法,很多时候并不是主流的Leader做法,更多的是一种理想主义的推荐操作,如果在你们公司不具备落地性,你可以进行一定的微调,但是不要调整到反面去。
|
||||
|
||||
如果你还没有成为一个管理者,可能会觉得这一讲只是说了一些做人的基本道理。但是如果你已经是管理者了,或者有一天成为了管理者,你可能会反过来感慨:
|
||||
|
||||
“真的好难啊!”
|
||||
|
||||
好了,随着这一讲的结束,我们的整个课程也就到了尾声。整个课程,我们探讨了反爬虫相关的理论,实践知识,以及可能存在的团队建设理论。反爬无止境,记住,我们是在一起探索,而不是单向的输出小的技巧。
|
||||
|
||||
我们再重申一次:反爬是一个腐蚀人心智的行业,而管理也是一件腐蚀人心智的事情,那么,做着反爬的管理,你还能保持纯真善良的心吗?我们的本意是让世界变得更好,千万不要被KPI压昏了头脑,变成反面呀!不要像阿尔萨斯一样拔出宝剑,成为了屠龙勇士,然后转身像恶龙一样,坐上巫妖王的宝座。
|
||||
|
||||
虽然没有下一讲了,但是我们永远可以在评论区见!
|
||||
|
||||
思考题
|
||||
|
||||
情绪都调动完了,结果还有思考题呢,好了,安可时间。
|
||||
|
||||
|
||||
大家为了反爬付出了艰辛的努力,甚至包括彻夜与对手的对抗。到了年底,你的老板强制你团队出一个差评。你会如何处理呢?
|
||||
下属和你谈,非竞对挖他,涨薪40%。这个时候你预估了一下,你最高可以给他涨30%,但是这样做了之后,其余的成员的下次调薪就会受到影响。你会硬着头皮用掉这30%把他留下吗?
|
||||
你在反爬的注释里写:我们团队待遇如何如何好。借此来扰乱竞对的军心。这个时候,你手下一个薪资极低的人跑来问你:老大,你在注释里写了我们待遇那么好,是不是真的?这个时候,你会如何回答呢?
|
||||
|
||||
|
||||
期待你的分享,我们永远可以在评论区沟通交流!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
77
专栏/反爬虫兵法演绎20讲/加餐反爬虫的专家级鉴别力:用户习惯检测.md
Normal file
77
专栏/反爬虫兵法演绎20讲/加餐反爬虫的专家级鉴别力:用户习惯检测.md
Normal file
@ -0,0 +1,77 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
加餐 反爬虫的专家级鉴别力:用户习惯检测
|
||||
你好,我是DS Hunter。又见面了。
|
||||
|
||||
上一讲,我们讨论了反爬虫方检测真人的几种方式,分别是各种游戏验证码、变态验证码以及滑块验证码。当然,除了这三种检验方式,还有一个更简单的验证码,让用户单纯地看图猜字。这些非黑即白的方法,可能会给你一种感觉,让你觉得:这是一个不可解的问题,没有哪个方法是完美的啊!
|
||||
|
||||
记不记得上一讲除了真人检测的几种方式,我还说过什么?“完美解不存在,生活中很多方案都是依靠近似解来进行的”。同样,我也给你提到了,我们在成为反爬虫专家的这条路上,需要的不仅仅是一些通用的、非黑即白的鉴别方法,更要有敏感的鉴别力。
|
||||
|
||||
那么现在,我就带你回到寻找近似解的问题中,给你补充一个动态拦截方式:用户习惯检测。
|
||||
|
||||
检测真人的目的是什么?
|
||||
|
||||
这里,我们首先回归一下初心,明确接下来所有动作的目的。你可以想一想,我们为什么要检测真人?是出于对机器人的厌恶?还是有什么洁癖吗?
|
||||
|
||||
不是的。进行检测,单纯的只是因为机器人不仅不会带给我们经济利益,反而会消耗我们的资源。
|
||||
|
||||
明确目的之后,“真人检测”这个问题近似解的方向就变得简单了:其实,我们并非一定要检测出谁是真人。我们的目标,是检测那些ROI不高的账号,我们并不在乎他是不是真人。
|
||||
|
||||
检测方法:用户画像分析
|
||||
|
||||
为了检测出ROI不高的账号,我们可以针对订单量的高低以及服务器的消耗情况这两方面,综合判断出每种组合情况下的用户类型以及可能出现的爬虫类型。通过这样的分析,我们就可以给所有账号进行分层了:
|
||||
|
||||
|
||||
|
||||
从图表中可以看到,爬虫是可以隐藏在各个地方的。而我们之所以想拦截爬虫,单纯的只是希望提升ROI。
|
||||
|
||||
基于这样的想法,我们可以分析一下四个区域的爬虫和它们的应对方式了。
|
||||
|
||||
分布式爬虫,咱们之前已经讨论过了,作为爬虫界的主力和炮灰,我们整个系列都在探讨如何拦截或者误导它们。而这篇加餐则主要特指那些看起来漫无目的、迷惑反爬虫方的炮灰爬虫。
|
||||
|
||||
除了分布式爬虫,这里还出现了两个新的定义:价格爬虫和搬单爬虫。当然,他们都属于咱们在06讲中说过的分布式爬虫,只不过这里因为有了明确的目的,就单独进行讨论了。最后,图表中还有一个分类是由价格爬虫和搬单爬虫两者混合组成的。它们虽然大幅提高了订单量,但也让服务器的消耗变高了。这里,我们明确一下两个新名词的定义:
|
||||
|
||||
价格爬虫:以抓取货物价格为主,并且不产生任何支付行为的爬虫。
|
||||
|
||||
搬单爬虫:通过自动下单,实现订单转移功能,补全爬虫方的货物缺失。
|
||||
|
||||
价格爬虫是大家深恶痛绝的,这个没什么说的,订单量低,意味着没钱赚,同时对自己服务器的消耗又高,所以直接拦住即可。至于搬单爬虫,可能你会表示不理解:这个,有什么不好的吗?人家这是来送钱来了啊?
|
||||
|
||||
没错,搬单爬虫是送钱的,甚至还会让你的财报变得好看。所以很多公司决策者对这种爬虫也是又爱又恨。爱就不用说了,谁不爱钱呢。而恨,主要在于,长期来看,用户在对方站点下单,爬虫在自己这面下单,时间长了,自己就沦落为“供应商”了。而做互联网,最重要的是用户,不是短期收益。因此,大部分公司最终会对搬单爬虫进行拦截。
|
||||
|
||||
检测详解:搬单爬虫的判断方式
|
||||
|
||||
针对搬单爬虫,非技术手段主要是财务手段,卡对方流水时间。这里的具体方案可以咨询公司财务,他们会有大量的苦水给你吐的,你自然能在里面找到大量的搬单爬虫的痛点。一定要记住,反爬的核心就是:抓住爬虫的痛点,不断强化,把它痛死。
|
||||
|
||||
技术角度方面,浏览器端主要就是针对人的行为进行检测。这方面,大家的手段还是偏猜测更多一些,并没有什么通用的办法,一般就是在线上分析用户习惯,然后头脑风暴,看哪些习惯是人类特有的,这些习惯就可以做为评分标准。当分值低到一定程度的时候,就可以认为这个人可疑。再之后,就可以进行一些拦截操作了。
|
||||
|
||||
这里主要举几个例子来说明这个判断方式。
|
||||
|
||||
第一个,姓名的复制粘贴。大部分的搬单爬虫,内容是直接set的,不会引发输入法的输入,机械得过于明显了。也就是说,爬虫方的模拟失误,把自己给暴露出来了。
|
||||
|
||||
而人工操作的话,会有两种情况。一种是真的普通人,这种人用输入法输入名字,选字的时候由于输入法已经有了记忆,所以第一个选项就是自己的名字。这种用户我们就只能进行无罪推定,认为是真人了——总不能不让输入法记忆用户的名字吧?还一种情况就是人肉搬单了。是的,即使他们是人类,我们也照拦不误。人肉搬单, 一般把名字都是复制粘贴进来。因此,这样的过程是一个很强的减分项。
|
||||
|
||||
第二个,手机号归属地与IP地址不匹配。虽然我们不能拿到手机号的常用地点——不考虑现在的行程码这种技术,这不是普通人能用的——但是我们依然可以在一定程度上用这个分数做参考。但是,跨手机归属地使用手机,现在已经逐渐是个常规操作了。因此,这一条也可以是你的判断条件之一,只是分数也不用给得太高。
|
||||
|
||||
第三个,切屏操作。众所周知,在面试系统里,切屏是一个严重的减分项。为什么呢?因为求职者如果切屏了,那就是在找资料。这是一个严重的作弊行为。
|
||||
|
||||
那么,搬单的人也是一样的。如果是人肉搬单,那么他们会在一个内部系统里查看需要填写的信息。这些信息,一般说来都是切屏过去复制,再过来粘贴。就算有经验的人,避免了复制粘贴,也很难避免切屏:大部分搬单的员工都是低薪聘请的,不会给他们配第二块显示器的。不过,一样的道理,万事无绝对,要精细调整每一项对应的分数。
|
||||
|
||||
除了上面说的三点之外,其实还有一些特殊的判断方式,你可以根据业务的形态不同,自己去头脑风暴一下。这样想出来的方法,才是最适合自己业务的,也是最好用的。
|
||||
|
||||
为什么这么说呢?你可以看到,上面的三种方法,第一种和第三种就和下单流程的适配度很高,但是对于小说、视频等信息类的平台来说,就没有那么合适了,甚至可以说毫无用武之地。所以,网上查到的办法,大多数是别人的总结,一般放在自己业务,都有些水土不服,需要进行改造或者自己发挥。
|
||||
|
||||
小结
|
||||
|
||||
好了,以上就是这次分享的主要内容了。实际上真人检测是一个不可完成的任务,我们都是在追求一个近似解。而且,思路上,我们主要是检测某些流量是否与别人不一致,这里包括作弊的真人,也要被拦截。所以最终我们一定会算个总分,然后根据情况设置个可配置的分数做为阈值,来实现动态的拦截效果。
|
||||
|
||||
截止到目前,爬虫与反爬虫逐个过招的战争就大致告一段落了。从08讲开始,我们会专注反爬虫的技术细节。其中08讲是法务相关,偏向非技术方向。而09讲到12讲,理论性会越来越强,尤其是12,写的时候我自己都犯困,大家要做好准备不要打盹啊!建议你边听音频边浏览,有人在耳边跟你说道说道,效果肯定不一样。
|
||||
|
||||
我们08讲见!
|
||||
|
||||
|
||||
|
||||
|
107
专栏/反爬虫兵法演绎20讲/春节加餐01破解还是不破解,这是一个问题.md
Normal file
107
专栏/反爬虫兵法演绎20讲/春节加餐01破解还是不破解,这是一个问题.md
Normal file
@ -0,0 +1,107 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
春节加餐01 破解还是不破解,这是一个问题
|
||||
你好,我是DS Hunter。
|
||||
|
||||
今天是除夕夜,在这里先祝你新春快乐。
|
||||
|
||||
终于远离爬虫和反爬虫尔虞我诈的战场了,有没有轻松一些?今天,我们就先远离这些纷乱的硝烟和危险的斗争,远离爬虫和反爬虫的“知识点”。
|
||||
|
||||
我在开篇词的时候就和你说过,希望这门课能够帮助你堂堂正正地,还把工作完成了。而这种虚无缥缈的话,你肯定不信;那些苦口婆心的说教,你肯定也不爱听。所以,咱们就来点轻松的,看看在无故事王国里,爬虫和反爬虫的战场是什么样的。
|
||||
|
||||
先给你预告一下,春节期间呢,我一共会给你讲三次故事。除夕夜、大年初二的时候每次给你讲两个故事,无故事王国里充满了匪夷所思的事情,不要觉得惊讶。至于看了故事之后给你总结出点什么?故事王国里的事放到现实世界的意义,还是自己理解比较好。爬虫和反爬虫的这些弯弯绕绕,全靠悟。
|
||||
|
||||
到了立春那天,也就是大年初四了。我会针对近期的一个爬虫案子给出一点个人的分析。新的一年,咱们看看过去的事,帮着自己在爬虫和反爬虫的这条路上找找方向。当然,这里要注意一点:我是技术人员,不是专业法务,因此所谈的一切,仅限于个人观点,不代表权威法律指南。如果和你们公司法务的说法有冲突,那还是请你以公司法务的说法为准。
|
||||
|
||||
那我们现在就开始吧。
|
||||
|
||||
故事一
|
||||
|
||||
有些事情,不靠技术也可以解决,甚至可能比技术还管用
|
||||
|
||||
|
||||
根据常规故事的开头,这件事应该发生在一个孤独的夜晚,外面交织着青蛙的叫声和潺潺的流水。这是一个偏僻的郊外,创业公司只租得起这样的办公场地。一个爬虫工程师,我们叫他小陶吧,努力睁圆自己小小的眼睛,试图对这个反爬系统做最后的破解。-
|
||||
-
|
||||
半个月过去了,小陶对系统进行了大量的破解。刚来的时候,他只会Python。现在,他对js(JavaScript)的作用域、浏览器兼容以及各种js黑魔法了如指掌。三天前,公司的前端还来找他请教问题。这一切都来源于在对这个系统的破解中,小陶不断的学习。但是截止到现在,他还是无法拿到Token的计算方式。-
|
||||
-
|
||||
不过,看起来胜利就在眼前了。他已经顺利地过了四层不同的加解密,代码结构已经变得清晰了,甚至已经解出了一些可读的代码。不出意外的话,天亮之前就能得出结果。-
|
||||
-
|
||||
第二天早上,工友发现他睡倒在位置上,嘴角还露出甜甜的微笑,比找到女朋友还开心。-
|
||||
-
|
||||
当天下午, 他提出了离职申请。-
|
||||
-
|
||||
老板大吃一惊:之前毫无征兆啊!这是他们最优秀的工程师,来的时候懵懵懂懂,试用期还没过就已经成长为公司大牛了。但是出于法律要求,也只能批准了他的申请,然后赶紧找人交接。-
|
||||
-
|
||||
交接的员工用了半个月,终于也破解到了那个让小陶离开的地方。因为上一个人就是在这里离职的,所以这次大家一起盯着他破解,想看小陶到底看到了什么,居然让他看完就离职了。-
|
||||
-
|
||||
交接的员工找到了最后一次破解的关键所在,缓缓敲下最后一行命令,终于看到了真正的代码所在。只见屏幕上赫然写着一行注释:-
|
||||
-
|
||||
“当你看到这句话的时候,以你的知识量,应聘一个前端工程师,月薪一般最少是XXXXX元……”-
|
||||
-
|
||||
这是一个五位数的月薪,也许在互联网行业比较常见,但是这个创业公司无疑是给不起的。
|
||||
|
||||
|
||||
我们并不清楚后来公司发生了什么,只知道这个交接的人无奈地发了一条知乎来吐槽这件事。
|
||||
|
||||
这个事情能告诉我们什么呢?这里并不想过多地引导什么,只能说一个最简单的道理:有些事情,不靠技术也是可以解决的。甚至,可能比技术还管用。
|
||||
|
||||
此外,员工心理必须时刻关注。很多事情都是心理导致的,而且是长年累月积攒的。等到爆发,其实只需要一个导火索。而一旦爆发,一定是让人措手不及的。
|
||||
|
||||
不过,总体来说,还是个值得开心的故事:技术人员能够跳槽、获得更高的薪水,这个结局还是不错的。让我们祝福小陶吧,也祝大家新的一年也能获得高薪。
|
||||
|
||||
当然,别忘了,拿高薪的前提,还是要多学习啊。
|
||||
|
||||
我们再看下一个小故事。
|
||||
|
||||
故事二
|
||||
|
||||
你根本不知道自己的哪部分代码在起核心作用
|
||||
|
||||
|
||||
一个公司,爬虫团队一直在试图破解竞对的反爬虫系统。这个反爬虫系统里面有一个很绕的异步循环调用,爬虫团队每次都卡在里面,即使明知道策略发生变化后,这个异步没有变,他们还是会被坑在里面很久,每天都搞得自己要崩溃了。最后,两家握手言和不再竞争了。-
|
||||
-
|
||||
这个时候,公司员工和对方交流的时候,忍不住问了一下:你们那个异步循环调用是个什么逻辑?每次我们都被坑在里面。对方愣住了,说:异步循环?我们没有这个东西啊,你说的是什么地方?-
|
||||
-
|
||||
然后双方联手调试了下反爬虫代码。-
|
||||
-
|
||||
反爬工程师最终感慨地说道:“第一,这是我第一次调试自己的线上代码,真的是太他妈恶心了……我都要调吐了。第二,你刚刚说的那个异步循环,根本不是什么异步循环,只是一个Promise的polyfill……因为低版本浏览器不支持Promise,所以我不得不自己实现一个。至于你问的那个地方为啥感觉跳得很奇怪……很简单……我当时没写好,那是个Bug……”
|
||||
|
||||
|
||||
这个故事告诉了我们两件事。第一个呢,就是你根本不知道自己的哪部分代码在起核心作用。第二个,就在反爬虫代码里,任何Bug,只要能够让系统正常运行,都将是一个优秀的Feature。
|
||||
|
||||
魔幻吗?不魔幻。
|
||||
|
||||
事实上,我们的大部分系统都是这么跑起来的,不仅仅是反爬虫系统,整个系统通常也就是这个样子:
|
||||
|
||||
|
||||
|
||||
可想而知,当我们的系统只有依靠一个Bug才能正常运行的时候,维护人员内心是多么的崩溃。
|
||||
|
||||
而反爬虫写代码则不同,不止自己这面的人要维护,对方的人也要不断地阅读你的代码,这个时候写出一些比较恶心的代码,也许是个好事情呢?
|
||||
|
||||
从这个角度出发,我们也可以脑洞大开,难以维护本来是一个贬义词,这里居然成了好事情。那么我们扩展下,其余的研发相关贬义词呢?
|
||||
|
||||
性能低、可维护性差,等等。细分下来还有:全局变量、长函数、goto、eval……
|
||||
|
||||
那些你觉得臭名昭著的特性,写一次就被Leader骂一次的代码,都可以用上来啊!
|
||||
|
||||
当然,我们还是要注意:不要影响自己的阅读。例如eval,调试的人看到的是eval,你看到的应该是正常的无eval的代码。 所以你需要一个转换器。 在后面的《10 | 反爬虫概述(中):无收益的前端如何帮助后端处理爬虫?》里,我还会详细论述具体的做法,你可以期待一下。
|
||||
|
||||
小结
|
||||
|
||||
那么,今天的故事就到这里了。在别人眼里并不重要的事情,对于当事人来讲,有的时候却是无比重要的。报酬是这样,摇摇欲坠的代码也是这样。
|
||||
|
||||
下节加餐,我们会继续以故事为主。敬请期待。
|
||||
|
||||
思考题
|
||||
|
||||
不用害怕,咱们今天的思考题呢,就没有那么学术了。而我今天,只有一个问题想问你,并且是开放性的。我们都说,反爬虫代码以乱为美,但是这么乱的代码却要嵌入到你的系统里,你的系统也就变乱了,那怎么办呢?
|
||||
|
||||
期待你在评论区的分享,我会及时回复。反爬虽然“无定式”,不过春节了,咱们就不一起探索了。我们一起,聊聊天。
|
||||
|
||||
|
||||
|
||||
|
100
专栏/反爬虫兵法演绎20讲/春节加餐02真实世界里,小心屠龙勇士变恶龙.md
Normal file
100
专栏/反爬虫兵法演绎20讲/春节加餐02真实世界里,小心屠龙勇士变恶龙.md
Normal file
@ -0,0 +1,100 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
春节加餐02 真实世界里,小心屠龙勇士变恶龙
|
||||
你好,我是DS Hunter。新年快乐!
|
||||
|
||||
今天已经是大年初二了,不知道你有没有开始准备走亲访友呢?
|
||||
|
||||
在上一节加餐里,我们讲了两个小故事。第一个故事告诉我们,有些事情,尤其是反爬虫这件事情,不靠技术也能解决问题。而另一个故事呢?它告诉我们,在这样你来我往的博弈中,从不同的角度部署反爬虫代码,没准会有意想不到的收获。
|
||||
|
||||
好像爬虫、反爬虫的战场就是这么的不同。有的时候,我们必须把目光放在战场外,才能找到更加合适、更加出其不意的策略。那今天,我就再给你讲讲另外两个小故事吧。
|
||||
|
||||
今天的故事,会稍稍偏非技术一些。不过呢,还是会引发不小的思考,不会像除夕夜那天的故事基调一样轻松了。反爬虫这件事,本来就是三分靠技术,七分靠心理。你以为十分满分了?不是的,剩下九十分,基本看天意了。
|
||||
|
||||
故事三
|
||||
|
||||
反爬真的是一件腐蚀人心智的事情,因为这件事本身就不太光明。
|
||||
|
||||
|
||||
曾经有一家公司,被竞对爬得很惨。这个时候,公司成立了一个反爬虫组,小蔡成了整个组的Leader。他使用了大量阴险狡诈的办法,让竞对痛不欲生,最终被自己收购了。-
|
||||
-
|
||||
后来,新的竞争对手慢慢起来了。这时候,公司打算重启反爬组。-
|
||||
-
|
||||
小蔡思考了下周围的办公室环境:上次,自己反爬做得好,一路升得很快,很多人对自己羡慕嫉妒恨。其中,最重要的,就是嫉妒。-
|
||||
-
|
||||
这个时候,几个组都虎视眈眈,希望能拿到这块肥美的蛋糕。小蔡最终决定,把反爬交接出去。他的理由是:我年纪大了,卷不动了,这辈子也不想再做反爬了。-
|
||||
-
|
||||
最终经过一番斗争,小郑拿到了反爬这块大蛋糕。-
|
||||
-
|
||||
但是小郑做下来发现,反爬根本不像想象中的那么好做。竞对抓得很疯狂。于是,小郑开始研究之前小蔡的套路。-
|
||||
-
|
||||
很快,他发现了一大堆放水代码(在07讲我们也会讨论战略性放过爬虫的问题)。经过一番研究,他终于找到了各种“不拦爬虫”的借口。然后他恍然大悟:哦,原来小蔡是这么升的职啊,我还以为他真的做了什么呢。-
|
||||
-
|
||||
就这样,他开始疯狂地刷存在感、秀加班,但是并不拦爬虫。最终,虽然各种事故频出,爬虫拦截没多少,但是上层一直以为他效果很好,以为是在做“战略性部署”。-
|
||||
-
|
||||
但是业务的眼睛是雪亮的,他们根本不会被这种高层玩法欺骗。业务的思维永远在第一层,平常我们都会看不起第一层,但其实第一层的思维是最直接的。拦不住就是拦不住,有什么可说的呢?最终,真正做反爬的几个技术人员不堪重负,选择了离职跳槽竞对。-
|
||||
-
|
||||
业务压力加剧,大老板就开始反思了:会不会我用人不当?要不要考虑把小蔡换回来?-
|
||||
-
|
||||
小郑非常恐慌,因为他知道一旦把小蔡换回来,自己的布局就彻底完了。于是他选择了公布小蔡的放水代码,各种诋毁他,最终导致了小蔡离职。-
|
||||
这个故事告诉了我们些什么呢?有时候我也在反思,因为信息量实在太大了。
|
||||
|
||||
|
||||
小郑是做了反爬才变坏的?还是本来就这么坏?谁也不知道。不过,我能说的就只有一点,那就是:反爬真的是一件腐蚀人心智的事情,因为这件事本身就不太光明。
|
||||
|
||||
刺客信条里有一句话,说的是,_“We work in the darkness to serve the light”_,意思是我们虽然在黑暗中工作,但是我们侍奉的是光明。
|
||||
|
||||
要做到这一点是真的很难。
|
||||
|
||||
大部分人,一旦 “Work in the darkness” ,就真的会变成 “Darkness” 的一部分了。最终,也成为了自己最痛恨的人。当然,也有一些人的“黑化”,并非什么转变,其实就是内心的恶魔被唤醒了。这谁说得清呢。
|
||||
|
||||
这里,我还想用刺客信条里的另一句话来补充一个观点,_“Nothing is true, everyting is permitted”_,翻译过来就是:万物皆虚,诸事皆允。其实也就是说,万物没有对错可言,无需考虑条条框框。
|
||||
|
||||
你要注意,这个信条是对内心强大的英雄而言的。而对于我们普通人来说,失去的规则,其实往往才更是我们应该遵守的。内心不够坚定的人,一旦让自己自由奔放,实现所谓的 “Everything is permitted” ,那结果往往就如同魔兽世界的阿尔萨斯,虽然他拔出受诅咒的宝剑,也是为了拯救子民,但事实是,最终他不受自己控制,成为了新的巫妖王。
|
||||
|
||||
故事四
|
||||
|
||||
是防火墙先动手,还是法务先动手呢?
|
||||
|
||||
|
||||
一个公司的爬虫工程师每天都在调试对方的反爬代码。他每次看的时候,都感觉:这也能叫反爬?然后迅速改好代码,上线。但是很快被业务反馈:这都抓的什么玩意,什么也没有啊。-
|
||||
-
|
||||
奇怪了,到底是为什么呢。-
|
||||
-
|
||||
于是他再调试,找了好久,觉得没啥问题啊。就找到一个小的地方,这也不至于被封啊。等他再次修复了这个小问题上线,发现上线后依然抓不到数据。诶,奇怪了,到底对方在哪里藏了东西呢。-
|
||||
-
|
||||
直到后来,公司和对方达成一致,不竞争了。这个时候,他忍不住问对方:你们是怎么防我们的?我一直调试你们的代码,感觉没有啥反爬措施,为啥我就是抓不到数据?-
|
||||
-
|
||||
对方淡淡地说了句:很简单,我们针对你们的办公楼,放掉了所有的反爬虫规则。也就是说,你上班的时候,调试的都是“没有反爬措施的代码”。实际上,你还从来没见过我们的反爬虫逻辑,更不要说破解了。-
|
||||
-
|
||||
爬虫工程师当场吐血。然后又反问了句:你就不怕我们在办公室直接部署机器抓取么?-
|
||||
-
|
||||
对方笑笑说:怎么可能呢,真到了这个份上,有两个东西会等着你,一个是简单的防火墙封IP,一个是法务。你猜哪个会先来?
|
||||
|
||||
|
||||
你猜猜真到了那一天,是防火墙先动手,还是法务先动手呢?
|
||||
|
||||
如果你觉得法务不可能动手,那就大错特错了,事实上爬虫惹上法务问题根本不是什么新鲜事,甚至经常上新闻。所以,不要存在侥幸心理,更不要在这些尔虞我诈中失去方向。
|
||||
|
||||
小结
|
||||
|
||||
好了,这两篇加餐的新年故事就到此结束了。谢谢你耐心地听我讲了这么多东西。
|
||||
|
||||
最后,我还是想强调一下,其实,这些故事里面包含了很多尔虞我诈的欺骗艺术,不过我想说的是:一定要时刻要记住,欺骗技巧,仅仅是用于商业竞争的,绝对不要失去自我,最终沦落为一个擅长欺骗的人。否则,我们为了坚守正义而选择了反爬这条路,最终的正义又在哪里呢?
|
||||
|
||||
屠龙勇士最终变为恶龙的故事,我们听得太多了。希望,你能永远不忘初心,永远坚持当初的信仰。
|
||||
|
||||
下节加餐,我们就看看法务是如何对爬虫下狠手的。
|
||||
|
||||
思考题
|
||||
|
||||
不用紧张,今天的思考题咱们还是讨论和故事相关的内容。那就是:你做爬虫或者反爬虫,是主动请缨的,还是被动安排的?如果给你一个重选的机会,你会怎么处理呢?
|
||||
|
||||
期待你在评论区的分享,我会及时回复。反爬虽然“无定式”,不过春节了,咱们就不一起探索了。我们一起,聊聊天。
|
||||
|
||||
|
||||
|
||||
|
147
专栏/反爬虫兵法演绎20讲/春节加餐03低调驶得万年船.md
Normal file
147
专栏/反爬虫兵法演绎20讲/春节加餐03低调驶得万年船.md
Normal file
@ -0,0 +1,147 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
春节加餐03 低调驶得万年船
|
||||
你好,我是DS Hunter。又见面了。
|
||||
|
||||
新年也快结束了,我们终于可以谈一点略沉重一些的故事了。
|
||||
|
||||
前天我也和你预告过了,我们要谈的是爬虫引上的官司。这里我选择了两个故事,第一个是大规模爬虫惹上官司, 第二个是小规模爬虫惹上官司。两者对应的法律条款也各不相同。
|
||||
|
||||
实际上,爬虫虽然是个历史悠久的技术,但是从法律上来说,这还是一个新生事物,因此也会引发很多的争议。无论你是大公司,正规地使用爬虫对抗竞对,还是个人研发者,自己靠兴趣写着玩,都能有一定的借鉴意义。
|
||||
|
||||
而反爬虫惹上官司的故事,暂时还没有先例,不过这并不代表反爬虫不会惹上官司,只能说难度大了很多。总的来说,我们还是尽量保持善意吧。我们常说,法律是道德的最低底线,那么不降低自己的道德底线,一般来说就能安全很多。
|
||||
|
||||
此外,这里先给你提两个醒吧。
|
||||
|
||||
第一,还是强调一下,文章的内容呢,都是我个人的一些见解。像开篇词里说的,我是一个纯纯的技术人员,不是专业法务,所以一切还是以公司法务的说法为准。咱们今天就当聊聊天,交流交流。
|
||||
|
||||
第二点,由于直接评论现实发生的事情,很容易引发名誉权问题。所以,老规矩,我还是会用A公司、B公司之类的称呼来描述。相信你们也猜得出是什么公司。不过,我可没有黑任何公司啊。
|
||||
|
||||
好了,那咱们就从大规模爬虫惹上的官司开始说起吧。
|
||||
|
||||
爬虫和不正当竞争?
|
||||
|
||||
首先是A公司侵犯B公司版权的爬虫案子。
|
||||
|
||||
某一年,A公司抓取B公司的用户评论信息,被B公司起诉了。
|
||||
|
||||
理由是,A公司大量复制B公司的评论,并且放在了自己的网站上。B公司认为,这样违背了商业道德与诚信原则,构成了不正当竞争。此外,A公司还使用了自己的图文标识,让公众以为双方是合作关系,属于擅自使用知名服务特有名称的不正当竞争行为。
|
||||
|
||||
同时被卷入的还有C公司,C公司使用了A公司的服务,因此网站上也有B公司的Logo。
|
||||
|
||||
也就是这样,B同时起诉了A和C两家公司。
|
||||
|
||||
|
||||
|
||||
对此,A公司和C公司都有自己的说法:
|
||||
|
||||
|
||||
A公司辩称,自己的抓取符合robots.txt协议,因此是合法抓取。
|
||||
C公司辩称,自己使用的是A的服务,因此不构成共同故意或过失。
|
||||
|
||||
|
||||
最终法院定的结论是:
|
||||
|
||||
A和B服务模式几乎一致,构成直接竞争关系。A使用B的用户评论,会导致B的流量减少。此外,虽然A的抓取符合robots协议,但是并不意味着可以任意使用抓取到的信息。但是,对A公司的侵权使用Logo行为,法院认为,是为了表明信息来源,并无不当。
|
||||
|
||||
至于C公司,它虽然使用了A的服务,但并未扩散数据,而是将数据局限在了A的服务范围内,因此不构成共同故意,也就是不侵权。
|
||||
|
||||
这个事情会比较绕,比较烧脑,甚至我写这段话的时候都绕晕了自己好几次。我们纵览一下整个结论,就会发现一个问题:
|
||||
|
||||
爬虫呢?为什么法院没怎么管爬虫的事情?爬虫到底有罪还是没罪呢?
|
||||
|
||||
我知道大家最关心的就是这个直接结论:爬虫到底有罪吗?
|
||||
|
||||
实际上,爬虫是一种行为,而法律不仅会根据行为来定罪,还会根据后果、性质等其他方面进行定罪。例如,故意伤人和正当防卫,都是“把别人打了”这个动作,但是我们不会直接说打人是否犯罪,还会考虑动作的性质。这也就是大家常说的“技术无罪”的来源。
|
||||
|
||||
因此,爬虫也一样,我们不能只考虑爬虫是否有罪,还要根据造成的后果、事件的性质等问题综合分析。当然,再强调一次,我并非法律专业人士,这些法律指导思想也仅仅是我个人的想法,实际上法律是一门非常严谨的学科,要让专业人士去讨论。
|
||||
|
||||
那么退回到这个问题,从抓取行为来看,法院提到:虽然遵守robots协议,但是不能任意使用抓来的信息。可能这个比较让人不解,那么我换个生活的说法,你就觉得这个判定没有问题了:
|
||||
|
||||
“购买菜刀需要实名制, 因此我实名制买的菜刀,是合法的。我要用买到的菜刀随便去砍人”
|
||||
|
||||
是不是这个就感觉明显违背生活常识,定罪没跑了?那么我们换回来:
|
||||
|
||||
“抓取数据需要符合robots协议。因此我遵守了robots协议抓取了数据,是合法的。我可以随意使用这些数据”。
|
||||
|
||||
这句话和上一句是完全一样的。虽然爬虫是个新领域,但是发生的行为实际上还是没有什么新意的。就想我前面提到过的那样,互联网其实没什么创新,就是把线下的事情搬到了线上。
|
||||
|
||||
从“买菜刀”的例子你就能明白“抓取数据”这回事了。技术本身,确实是无罪的。不过,也千万不要打着“技术无罪”的幌子任意妄为,使用技术去做有罪的事情,那就不能用“技术无罪”为自己辩解了。
|
||||
|
||||
接下来,我们就可以做几个判断题了:
|
||||
|
||||
|
||||
爬虫是违法的(错)
|
||||
爬虫是合法的(错)
|
||||
爬虫是否合法,取决于法院的心情(错)
|
||||
爬虫是否合法,取决于使用场景以及性质(对)
|
||||
|
||||
|
||||
三短一长选最长,你都懂的。这里的正确答案明显是第四个。这也就回答了大家一直以来的困惑:爬虫到底违法吗?是破解了才违法?那按键精灵违法不违法?为什么我们感觉正常的判了违法,我们觉得罪大恶极的居然没事?
|
||||
|
||||
原因啊,就是吃瓜群众的判断往往是着眼于行为本身的,而不是考虑后果。我们讨论一个行为是否违法的时候,多半是有争议的。通常,讨论行为人的思考方式以及造成的后果,才是法律的思考方式。
|
||||
|
||||
爬虫和“破坏计算机信息系统”?
|
||||
|
||||
那我们再讨论这样一个案子,可能近期你也看到了:
|
||||
|
||||
A同学为了给自己的女朋友抢挂号资格,试了下自己的脚本,意外地发现自己的脚本非常好用。
|
||||
|
||||
于是,A同学决定,也帮别人抢。最终,抢号这件事变成了一门生意,A同学开始收费帮别人抢。
|
||||
|
||||
最终,A同学的行为被警方发现。以涉嫌破坏计算机信息系统罪,暂时采取刑事强制措施,案件还在进一步审理中。
|
||||
|
||||
这里我们就不预测案件审理结果了。因为案件审理与多种因素有关,像是情节判定、认错态度等等各种因素。我们就只单独看一下这个例子里,爬虫是否又涉嫌违法了?
|
||||
|
||||
很多事情,我们在网上都会对违法行为有争议。我认为,可能是由于对法律并不了解的人,往往会混淆“违法”和“犯罪”这两个概念。严格来说,开车超速就是违法行为,但是这不一定是犯罪行为。违法行为中,违反刑法的行为才是犯罪。
|
||||
|
||||
我们单独看这个问题,爬虫是否涉嫌犯罪?
|
||||
|
||||
警察认为“涉嫌破坏计算机信息系统罪”给的理由是,刑法286条(这个编号还真的很有计算机的感觉,早年有个CPU就叫286):
|
||||
|
||||
|
||||
第二百八十六条-
|
||||
-
|
||||
违反国家规定,对计算机信息系统功能进行删除、修改、增加、干扰,造成计算机信息系统不能正常运行,后果严重的,处五年以下有期徒刑或者拘役;后果特别严重的,处五年以上有期徒刑。-
|
||||
-
|
||||
违反国家规定,对计算机信息系统中存储、处理或者传输的数据和应用程序进行删除、修改、增加的操作,后果严重的,依照前款的规定处罚。-
|
||||
-
|
||||
故意制作、传播计算机病毒等破坏性程序,影响计算机系统正常运行,后果严重的,依照第一款的规定处罚。
|
||||
|
||||
|
||||
那么,我们回到这个例子,回答几个问题。
|
||||
|
||||
首先,是条款里的关键词“故意”,他是主观故意的吗?
|
||||
|
||||
是的,就是为了赚钱。你总不能说我对钱没有兴趣吧?
|
||||
|
||||
其次,还是依据条款的提问。那就是,他是否造成了损失?
|
||||
|
||||
有。虽然我们暂时很难确定损失多大。可能有人觉得,只是插队啊,这没啥吧。
|
||||
|
||||
那么我们换个例子:假设你在北京,准备摇号获取车牌,忽然前面插队了1000人,你被挤出去了,这时候你是否觉得这1000人侵害了你的合法权益?
|
||||
|
||||
大部分情况下,当自己的权益受到侵害的时候,大家就能反应过来了。所以可以把自己代入到受害者角度来看看,问题就很好理解了。这里的争议主要在于损失有多大,毕竟可能会对“后果严重”有影响。
|
||||
|
||||
最后,我想问你一个问题:是否有证据?
|
||||
|
||||
有,自己发了帖子,全天下都知道是他干的。
|
||||
|
||||
这里,我作为一个技术人员,依旧无法给出一个明确的回答,告诉你A同学是否犯罪,爬虫是否违法。不过总体总结下来,你就会发现,要想保护自己,核心还是两个字:低调!
|
||||
|
||||
低调驶得万年船,在爬虫界永远不会错的。
|
||||
|
||||
好了,今天的案例分析就到这里。最后,我再次和你强调一下,今天的分析只是我个人的一些观点,我是一个纯纯的技术人员,不是专业法务,所以一切还是以法律人士的说法为准。
|
||||
|
||||
结束的诗词就给大家一个祝福吧,新的一年里,祝大家:
|
||||
|
||||
工作富裕且合法,事业轻松又有钱。
|
||||
|
||||
我们年后见。
|
||||
|
||||
|
||||
|
||||
|
169
专栏/反爬虫兵法演绎20讲/答疑课堂爬虫反爬虫调试对抗技巧以及虚拟机详解.md
Normal file
169
专栏/反爬虫兵法演绎20讲/答疑课堂爬虫反爬虫调试对抗技巧以及虚拟机详解.md
Normal file
@ -0,0 +1,169 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
答疑课堂 爬虫反爬虫调试对抗技巧以及虚拟机详解
|
||||
你好,我是DS Hunter。
|
||||
|
||||
因为一些保密需要,我们的课程充满了理论,可能你会认为难以落地。因此啊,我们总要有一讲,擦着泄密的边缘,稍稍讲一点实际的例子,也在课程的基础与理论实践篇快要结束的时候做个总结。
|
||||
|
||||
反爬虫领域里的例子就像魔术揭秘一样,一旦了解背后的秘密了,我打赌你会先惊讶一下:哦原来是这样?然后仔细想想,就会再说:哦……不过如此!
|
||||
|
||||
不过在后续自己做的时候,还是要咬着牙慢慢自己往下Coding才行,你会有一种“感觉看了一堆明明能直接落地的东西,但无能为力”的感觉,在自己落地试试的时候,似乎也摔得不轻。
|
||||
|
||||
是的,这就是反爬。相同的招式对圣斗士是无效的,我们必须自己学会创新才行。我们能做的,就是看历史、学思路。
|
||||
|
||||
今天,我会为你总结技术对抗与非技术对抗这两大思路,并一一展开说明。最后,也会给你讲一讲在反爬虫中加密强度最高、最复杂的大招——虚拟机。也就是,对各类反爬虫的手段以及实现方法做一个快速的总结。
|
||||
|
||||
技术对抗
|
||||
|
||||
首先我们要明确,所有技术对抗的本质目标不是加密,而是浏览器bug检测。其余的所有手段都是为了隐藏自己的这个目标。
|
||||
|
||||
我们提到过,假币唯一的特征就是与真币不一样。那么爬虫唯一的特征就是与浏览器不一样。哪里不一样?浏览器有bug,爬虫不一定有。你要模拟得一样,需要模拟所有的bug才行。我们都知道,抄别人代码很容易,但是抄别人bug?那可不是一般的困难。
|
||||
|
||||
举个例子,我们看这样一个小bug:
|
||||
|
||||
|
||||
在部分版本的IE8下面,如果一个a标签的innerText与href相同,那么当你修改href的时候,它会自动帮你修改innerText。-
|
||||
-
|
||||
这个很傻的bug意味着什么?-
|
||||
-
|
||||
这意味着你作为一个爬虫,如果对网站声称自己是IE8,那么,他会让创建一个a标签,然后运行相关的js操作DOM。然后,如果你能把这个bug模拟对了,他就相信你是浏览器。如果你不知道有这个bug,你妥妥的按照正常的方式去模拟。那么,你就是爬虫!
|
||||
|
||||
|
||||
但是,请注意,如果你代码赤裸裸写着:if,你是IE8,那么,你要创建一个a标签……等等。你觉得爬虫傻吗,他们不会觉得这个有问题吗?他们看你这么弄肯定觉得奇怪,会真的装个IE8试试啊。然后调试完了,他发现,什么,原来是这样,太阴险了。下次他还会上当吗?
|
||||
|
||||
想让一个人上两次当,唯一的办法就是:让他不知道自己上当了。这样,你卖完拐,卖完车,改个担架还能卖给他。
|
||||
|
||||
那么,强加密必然是基操了。诶,是不是你这时候忽然意识到了js加密的重要性?而且是不是这时候也明白了,加密不是目标,加密是手段?浏览器bug的检测才是目标。或者说,各个浏览器的差异,才是反爬虫技术对抗的核心。
|
||||
|
||||
好了,还是要帮你解决一下这个问题,我们回到这个例子本身。你可能会觉得:我知道这个bug了,可是要怎么知道哪些版本的浏览器会触发这个bug呢?注意,不要一个一个检测。有些人可能会有洁癖,一定要知道IE什么版本,UA里面拆除一堆字段,然后逐个判断。注意啊,不需要!
|
||||
|
||||
我们可以直接用浏览器bug和UA进行mapping!也就是说,有bug的所有UA如果我都能存起来,这个问题是不是就解决了?我不需要拆解UA啊。那么如何建立这个mapping呢?实际上,你只要预先用这个规则跑一段时间,但是不拦截,直接把埋点发送回来就可以了。一般做反爬的公司,都不是什么小厂,有足够的流量来做这个操作。线上跑个一周半周就可以了。
|
||||
|
||||
那么,你可能会问了:那如果对方发现我检测这个,不是提前就有准备了吗!
|
||||
|
||||
没错!那么你再想想怎么办才好?
|
||||
|
||||
哦,是不是给埋点设置一个强加密就行了?这个破解了也不影响拉接口,爬虫才没心思破解这玩意呢。这时候你是不是就意识到了埋点需要强加密的原因了?
|
||||
|
||||
到这里,你应该明白了,反爬的战场是瞬息万变的。很多经验,都是由实战训练出来的;很多选择,等你面对的时候才知道要怎么选。如果你觉得前面有些结论似乎没什么用,不妨反过来想想:如果我反向操作会引发什么问题吗?当你想到了问题所在,自然就明白为什么要这么操作了。
|
||||
|
||||
下面我们看几个例子。
|
||||
|
||||
迭代对抗:hook与反hook
|
||||
|
||||
hook这个技术本来是在native世界常用的方法。但是浏览器端,因为js修改的便利性,hook的玩法更加丰富多彩。
|
||||
|
||||
我们看这样一段对话:
|
||||
|
||||
|
||||
A:我的接口需要检测xx信息,并且经过了超强的加密,你信息不对我就不给你调接口!-
|
||||
-
|
||||
B:我根本不用看你的加密逻辑。我用xx工具进行操作,hook掉你的检测接口,如果你检测,我就mock一个数据给你,让你以为自己拿到了物理数据,实际是我模拟的!-
|
||||
-
|
||||
A:Too young。我用API检测你的软件列表,如果你安装了xx工具,我就不让你运行!-
|
||||
-
|
||||
B:你才too young,我hook你的检测API,你问我装没装这个工具,我就说我没装!-
|
||||
-
|
||||
A:你才too young,我用native代码实现检测,然后用框架调用,让你无法在框架级别进行hook!-
|
||||
-
|
||||
B:你才too young,我hook你调用native的方法,然后塞给你一个我写的函数,说这就是你的native方法!-
|
||||
-
|
||||
……
|
||||
|
||||
|
||||
其实,这个对话还可以不断的扩展下去,这里先赶紧打住。我们可以看到,欺诈与反欺诈检测是一个无休止的问题,只要一方解决了对方出的难题,就可以立刻进行反制。
|
||||
|
||||
而大家经常说的:反爬虫系统最终总是能破解,只是时间问题。这句话是什么意思呢?其实这句话你可以这么理解:反爬虫系统,对于爬虫来说,相当于一个单机游戏。单机游戏,总有通关的一天。也许是明天,也许是后天,也许是下个月、半年?但是总是过得去的。甚至可以开外挂来过啊。
|
||||
|
||||
那么什么游戏不能通关呢?没错,网络游戏不能通关,它可以无休止地升级下去。你装备刚毕业,他改版了。就这样,一直下去,等于没有破解。就像一些模拟战争游戏抢要塞一样,刚抢完没多久,过期了,又要重抢。这就等于没怎么抢到手。
|
||||
|
||||
那么对应js里面,这个是什么呢?其实就是对函数的拦截、模拟、切片等等。比如上一课我们提到的eval的攻防,就是一个简单的hook与反hook。
|
||||
|
||||
此外,其余的函数也可以用这种互相hook检测的办法。这个和石头剪子布一样,永远是最后出的赢。我们要做的,就是不断地更新,迭代改版。
|
||||
|
||||
Debugger对抗:无限Debugger
|
||||
|
||||
反爬虫方反爬虫方针对很多函数,都会设置大量的debugger,甚至在EventLoop里不断设置。
|
||||
|
||||
事实上,这样的办法是拦截初级调试者的。爬虫方呢,只要在代理上进行一次拦截,然后批量替换掉所有的debugger即可。这样,当js到达浏览器的时候,debugger就完全消失了。
|
||||
|
||||
但是,反爬虫方也可以针对这种批量替换继续出招。例如,检测函数的toString是否包含debugger。如果不包含,就可以认定函数被篡改。事实上,判定函数的toString,是反爬虫方一个很常用的技巧。在一定程度上,这甚至可以当函数签名使用。而一旦有了这样的代码,反爬虫方就不敢随意替换了。
|
||||
|
||||
注意:debugger甚至不一定放在代码里,还可以放在注释里。要知道,Function的toString,是包含注释在内的。这样,不但可以检测debugger在不在,还可以检测debugger的位置,并且不影响自己调试。另外有了这个思路之后,注释内可以隐藏大量的签名。
|
||||
|
||||
视觉对抗:阿拉伯文与emoji
|
||||
|
||||
很多浏览器在指定区域语言下,多语言支持做得是比较差的。如果线上测试发现指定的浏览器版本支持多语言,并且兼容很好,那么阿拉伯语将成为一个相当恐怖的杀器。
|
||||
|
||||
类似这类语言的字符有个很恐怖的地方,就是它们有的时候是从右向左写的。而且对于不懂阿拉伯语的人来说,根本不理解到底为啥代码左右乱跳。此外,一些畸形的字符都可以使用,都可以在视觉上严重影响阅读。例如QQ群里常见烟斗字符等等。
|
||||
|
||||
此外,emoji也是一个十分影响观感的一个选项。举个例子,10个狗构成一个变量名,11个狗构成另一个变量名,我相信正常人类是很难在一群狗里面调试下去代码逻辑的。当然,这里同样只是建议轻微使用,不建议大规模铺开。
|
||||
|
||||
理由有两个。一方面是兼容性问题。一旦出现,非常难调试。理论上它们可以做变量名,但是实际上哪个浏览器兼容,要以线上测试为准。另一方面,对方只要再走一次minify即可,这个我们前面提到过,破解成本比较低,所以我们大规模铺开的意义不大。因此,emoji这种方法不宜做大招使用。不过,小范围恶心一下对手,也很可能成为压死骆驼的最后一根稻草。
|
||||
|
||||
JSFuck对抗
|
||||
|
||||
大名鼎鼎的JSFuck,这个发明一度震惊了全世界。js的混乱程度被用到了极致。但是要注意,这种加密方式已经有比较成熟的工具来逆向解析了。此外,代码长度急剧膨胀,简直不能忍受。因此,如果使用,只能放在核心代码上绕一下对手。而且,建议进行自定义,而不是使用标准做法,避免被工具逆向。
|
||||
|
||||
工具对抗:调试状态检测
|
||||
|
||||
判定浏览器调试状态也是一个很关键的做法。在一些浏览器里,你可以有意引发一个异常然后catch住,判定error的信息。你会发现,在Console里运行的函数与直接运行的函数,引发的error有很大差别,这个差别很明显,就不详细展开了。此外,启动Devtools的时候会引发一次size的change,这个也可以持续监听。最后,Console里运行的时候,会有一些Console特有的函数。
|
||||
|
||||
这些都可以做判定。具体可以查阅Chrome的帮助文档。
|
||||
|
||||
非技术对抗
|
||||
|
||||
除了正面硬刚的技术对抗,还会有一些角落中的非技术对抗。非技术对抗大部分是心理对抗。当然,在很大程度上,心理对抗都比技术对抗效果好。毕竟,反爬打的不是算法,是人。
|
||||
|
||||
薪资对抗
|
||||
|
||||
薪资对抗,或者福利对抗,都是比较常用的心理战术。例如,随着调试的不断深入,不断给对方报价。
|
||||
|
||||
举个例子,爬虫方破解你第一层加密的时候,提示:唉,这算啥啊,月薪三位数都能走到这。再破解一层,就提示:这也就拿个月薪四位数。甚至可以直接报价,乃至于直接留HR邮箱。这并非天方夜谭,很多爬虫工程师技术非常优秀,并且非常不想继续做爬虫了,能转前端多开心啊!专业也对口,HR业绩也完成了。
|
||||
|
||||
但是注意:不要在这里鄙视竞对,否则容易惹上法务风险。
|
||||
|
||||
关键字的作用
|
||||
|
||||
很多人都知道,某知名网站在反爬里经常会写一些稀奇古怪的话。这些话非常猖狂,让人破解完忍不住要写一篇博客吐槽他们。注意,你写的博客很快会被搜索引擎收录。而他们有个爬虫帮自己不断检测关键字是否被收录。嗯,没错,你被发现了,爬取时自以为的低调真的只是“自以为”了!他们反爬组当然会写爬虫啊!
|
||||
|
||||
因此后续记住,看到反爬代码里的冷嘲热讽,或者一些稀奇古怪的话,无视即可,千万不要当回事。只要多看一眼,你可能就输了。
|
||||
|
||||
重头:虚拟机
|
||||
|
||||
很多大型反爬一定会有一个虚拟机的。但是回到我们刚刚说到的反爬虫思路来看,虚拟机不是目的,只是手段。webassembly也是虚拟机。但是我们在第10讲提到过,webassembly不好用,大家还是会自己实现虚拟机的。而虚拟机的核心作用,就是对代码进行加密,让破解变得更难。因为只有难以破解的代码,才能更好地隐藏你的小心机。
|
||||
|
||||
虚拟机的实现
|
||||
|
||||
虚拟机的实现方式,基本上就是看你熟悉哪门语言,就实现对应的解释器就行了。一般不建议使用主流语言,而是尽可能用冷门语言。Lisp或者汇编都是不错的选择。甚至,你自创一门语言,都是可以的。只要你有办法写完解释器。
|
||||
|
||||
解释器本身还需要再进行加密。例如,eval,变量名混淆,都可以。甚至更疯狂地说,我们都知道大部分语言都是自举的。也就是说,你的解释器可以用另一个解释器来解释执行,套娃解释。最终,你的竞对一定会被绕晕,根本看不出这是两层解释器。
|
||||
|
||||
至于再增加层数,就没必要了。理由是,两层解释器的代码已经大大超出预期。再高可能会因为js过大,影响用户体验了。
|
||||
|
||||
这里强烈安利Lisp解释器。我不方便透露太多细节,我只能说,某站点的反爬是用Lisp解释器做的,已经跑了六七年了,直到现在,我搜各种破解博客,大家还都在纠结如何破解那个“汇编解释器”的问题。事实上,那是Lisp……他只是简单解释了一颗语法树……
|
||||
|
||||
虚拟机的部署
|
||||
|
||||
实现了虚拟机的功能,我们就要开始部署了。虚拟机的部署有站点直接部署与CDN部署两种。
|
||||
|
||||
首先看站点部署。最原始的部署方式一定是由站点直接生成js文件,那么文件头就会有一个虚拟机。因为虚拟机是共用的,所以有些大聪明可能会考虑放到CDN。也不是不能放CDN,但是放了CDN,你的虚拟机就定死了,不能变更了。实际上,这样反而降低了别人的破解难度。
|
||||
|
||||
但是不放CDN,又太慢了,因为很难使用缓存机制。怎么办呢?
|
||||
|
||||
实际上,如果你是两层虚拟机,那么可以把一层放在CDN,利用缓存。然后再套娃解释一个简单虚拟机。例如,CDN放汇编解释器,然后用汇编解释器解释一个Lisp解释器,Lisp解释器用站点直接下发。这样,就可以实现CDN大量加速,同时代码破解难度也不低。
|
||||
|
||||
在这种情况下,我们的代码复杂度会逐渐提升。那么,如果爬虫方不读代码,直接用浏览器运行呢?
|
||||
|
||||
谢天谢地那太好了,我们等得就是这一天。一旦爬虫不读代码了,那就意味着,无论发生什么,都是黑盒了,他失去了调试的能力。你可以随机封他IP,封他指纹,增加浏览器bug检测。放心检测就好,虽然他使用了浏览器,但他还是会不断换UA的,假装自己是很多种浏览器的,所以你可以用各种办法随机坑他。而他只会认为自己的浏览器模拟有问题,而不是去调试哪行代码有问题——毕竟他是自己放弃这个能力的。
|
||||
|
||||
这能怪谁呢……
|
||||
|
||||
好了,今天的答疑课堂就到这里了。希望我的分享可以帮助你了解反爬虫这件事上思路的重要性。而当你没有思路的时候,一定要回到最初的想法:我完成反爬虫这个动作的最终目的是什么呢?如果我反向操作会引发什么问题吗?回归初心,往往能够帮助你直达目标。
|
||||
|
||||
|
||||
|
||||
|
106
专栏/反爬虫兵法演绎20讲/结束语达到理想不太易.md
Normal file
106
专栏/反爬虫兵法演绎20讲/结束语达到理想不太易.md
Normal file
@ -0,0 +1,106 @@
|
||||
|
||||
|
||||
因收到Google相关通知,网站将会择期关闭。相关通知内容
|
||||
|
||||
|
||||
结束语 达到理想不太易
|
||||
你好,我是DS Hunter。
|
||||
|
||||
恭喜你和我一起走完了这一趟反爬虫的旅程。这是我们的最后一节课了,在这节课里,我想和你一起分担一下“反爬虫”这条路的艰辛。
|
||||
|
||||
不知道你有没有玩过“魔兽争霸”这个游戏,我们先从游戏里的一句话开始吧。
|
||||
|
||||
|
||||
“Nothing shall prevent me from having my revenge, old friend. Not even you. Now, I call out to the spirits of this place. I will give anything, or pay any price, if only you will help me save my people.”-
|
||||
-
|
||||
|
||||
|
||||
—— Arthas 拾取“霜之哀伤”时的台词
|
||||
|
||||
|
||||
大学期间,我第一次玩war 3的时候,就被这段台词震撼了。当时我内心的感觉就是,以后一定要成为一个阿尔萨斯一样的人,为了我们的人民,不惜付出一切代价,赴汤蹈火在所不辞。
|
||||
|
||||
结果我遭遇了人生中最快的打脸:五分钟后,下一关的剧情开始了。后来的事情大家都知道了,最终他登上了冰封王座,说出了那句知名的:
|
||||
|
||||
“Now,we are one!”
|
||||
|
||||
说回到现实,“5·12”地震那年,大家都在外面打地铺。我和同学在外面走着,忽然就停了下来。同学问我怎么了,我说有一种子民在受苦的感觉。
|
||||
|
||||
同学哈哈大笑说,咱都要毕业了,现实一点好吗,不要再这么中二下去了。
|
||||
|
||||
后来,工作中,我遭遇了爬虫。
|
||||
|
||||
我和同事使用了大量的高阶技术手段,最终于事无补。直到后来,我们开始和对方玩各种套路、各种坑蒙拐骗的手段。出乎意料的是,效果出奇的好。那个时候的感觉,就像是拿到了“霜之哀伤”一样。
|
||||
|
||||
但是很快,我们就反应过来,感觉不对劲了。在一切的“保密”只有我们自己知道的情况下,我们发现,我们不仅可以忽悠竞对,也可以很容易地忽悠自己的老板,欺骗自己的同事和公司。而这个时候,我们已经被竞对的压力压得快喘不过气来了。另一方面,公司又给了我们其他人垂涎欲滴的资源,我们在业务的核心,被众多人关注(当然,也会面对别人的质疑)。这个时候,我们完全可以用自己已经纯熟的欺骗技巧,拿尽所有的好处。
|
||||
|
||||
万幸的是,我们和竞对的合并速度非常快。后续我们不再继续打竞对,而是打一些游兵散将。我们之前也提到过,游兵散将没什么可“随机放过”的,直接全封就行,根本不用搞任何套路。而我们也终于回归到了“好人”的路径上来。
|
||||
|
||||
故事到这里就结束了。可是我想问问你,如果“收购竞对”这个事情发生得慢一点呢?如果这个故事的主人公不仅是我,还有正在看这节课的你,我们还能保持初心不忘使命吗?沉重的KPI压下来,我们会不会这样思考呢:就稍稍欺骗一点点,老板会理解我们的……
|
||||
|
||||
在“反爬虫”这条路上,除了“保持初心”并没有想象得那么简单以外,你也没办法保证遇到的人都是,或者说大部分是真的翩翩君子。
|
||||
|
||||
这个世界有两种伪君子。
|
||||
|
||||
一种是没有经历过事情,所以处处喊着道德。这种人的建议,你听听就行了,毕竟都是纸上谈兵。还有一种是经历过所有的事情,最终发现还是道德绑架好用,所以虽然干着龌龊的事情,但依然处处喊着道德。这种人你一定要小心。
|
||||
|
||||
面对这两种困难,我又是比较幸运的。
|
||||
|
||||
在反爬虫这条路上,我和你一样,也经历了很多。说得不那么自谦一点,也算是跨过了山河大海、堕入过黑暗、想挣扎又无法自拔过了。当然,最后还是离开了这个行业,走上了平凡之路。至于后续,也有过多次再做反爬的机会,但是都被我拒绝了。因为我知道,再走一次,也许就不是平凡之路,而是“诅咒之路”了。
|
||||
|
||||
你可能会问,为什么这么幸运?这样的幸运需要什么样的buff加持吗?
|
||||
|
||||
你可以回想一下,整个课程里我们反复强调的只有两句话。其中的一句是:要低调。这个你一定很容易理解。
|
||||
|
||||
另一句话就是:反爬,是一个腐蚀人心智的行业。
|
||||
|
||||
人性是脆弱的,千万不要考验人性,包括考验自己的人性。我们总是自以为能够经受得住考验,而在第20讲结束的时候又都会说:哪个干部经受得起这种考验啊。
|
||||
|
||||
我们的整个课程都结束了,也许你会觉得,有些课程讲得好好玩啊,像第13讲一样,吃着小龙虾的时候,下一个双月规划就已经有了,非常搞笑。
|
||||
|
||||
但是请记住,喜剧的内核,其实是悲剧。每一个有趣的知识点,背后都有一段痛苦不堪的回忆。因此,你要面临的,绝对不是一个“好玩的任务”。
|
||||
|
||||
所以,在你接受爬虫或者反爬这个任务的时候,“霜之哀伤”就已经摆在你面前了。你可以选择拔出它,用它大杀四方,然后任由自己被腐蚀,成为公司的罪人。也可以选择忍痛不用,然后用自己最原始的办法,慢慢找解决方案,然后因为没有完成KPI,最终还是成为了公司的罪人。
|
||||
|
||||
想成为一个幸存者,大概只有两个方法了。第一种,如果十分幸运,“霜之哀伤”还没来得及腐蚀你,你就离开了这个行业,那么你就会成为像我一样的幸存者。又或者,你也可以像第20讲里我们说得那样,做出足够明确的规划,着迷又清醒,投入又远离。
|
||||
|
||||
这,就是这个行业的宿命。
|
||||
|
||||
但是,这是否意味着,我们要放弃这个行业呢?
|
||||
|
||||
当然不能。
|
||||
|
||||
因为这个世界,总是需要“罪人”。这种“罪人”,我们往往又称之为“英雄”,因为他们承受的更多,失去的也可能更多。
|
||||
|
||||
当我们年迈的时候,和一堆程序员朋友在一起喝酒聊天吹牛的时候,有的朋友说,我写了一辈子CRUD,一直写到XX岁写不动为止;有的朋友说,我切了半辈子图,又写了半辈子MVVM,直到干不动为止;又有的朋友说,我每天盯着服务器,直到视力下降干不动了;有人说我调了一辈子参数,总是没完没了。
|
||||
|
||||
这个时候,你自豪地站起来:我在公司最危难的时候,面对敌人的挑衅,面对同事的质疑,排除万难,敢于亮剑,最终拯救了公司,甚至整个行业。
|
||||
|
||||
这不刺激吗?这不荣耀吗?这不比抓了一辈子狮王休玛有意义多了!
|
||||
|
||||
相比之下,之前的困难又算得了什么呢?
|
||||
|
||||
这也正是我开设这门课程的初衷。这门课,很可能是你反爬入门的第一课。但是我希望它能指引你,知道困难在哪里,依然勇敢地冲向前方。
|
||||
|
||||
因为,这个世界需要更多的英雄。
|
||||
|
||||
反爬这个行业,比较特殊。最开始的我们可能是误入了险境,也可能是带着一颗英雄的心大踏步地闯了进来。那么我这里能告诉你的就是:
|
||||
|
||||
|
||||
我们唯一能做的,就是保持自己的正义之心,毕竟这是你入行(不仅包括反爬)的初衷。无论遇到多么艰难困苦的事情,都不要违背自己的正义之心,不要总想着“稍作变通”,通过欺骗盟友来稳固自己的位置。绝对不要。-
|
||||
|
||||
|
||||
——来自一个站着说话也腰疼的前辈,给予你的最后的劝导
|
||||
|
||||
|
||||
反爬是一个腐蚀人心智的事情。我们要时刻保持初心,即使损失自己,也不要让他腐蚀。就像一首歌说的一样,虽然“达到理想不太易”,但是依然要以“自信打不死的心态活到老”。
|
||||
|
||||
也许这样不够现实,也许这样有些中二。
|
||||
|
||||
但是,这是我们的初心,我们的使命,也是我们最终的信条。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user