2016 年被称为人工智能的元年,这一年 AlphaGo 赢了世界第一围棋高手,IBM 机器人Watson花了几秒钟时间就读懂了诺贝尔文学奖获得者鲍勃迪伦的歌曲所反映的情绪,这类弱人工智能是基于大数据实现的,这些数据来自何方?相当一部分就来自于网络爬虫。
现如今什么最值钱?毫无疑问,是数据。如何获取数据?可以用网络爬虫。有了数据,我们就可以对数据分析,让数据变得有价值,现如今火爆的 AI 、BI 都是基于数据工作。
在大数据时代,网络爬虫是获取数据的重要手段,但这把利剑想驾驭好并不简单,因为铸造它使用了很多技术。它关系到,网站建设、WEB 开发、JavaScript 逆向、APP 逆向、深度学习等。可谓是,道阻且艰。
网络安全圈曾非常流行这句话,我想它放在网络爬虫领域中也同样适用。如果说网站开发者是防守者,那么开发网络爬虫的就是"攻者"。
如果说网站开发者用的是正向思维,那么网络爬虫开发者就是逆向思维。
与安全技术类似,爬虫技术也处于灰色地带,一不小心就从面向对象编程变成了面向“监狱”编程。火可暖身,亦可焚身。
爬虫可以做很多有益于我们的事情,首先我们可以把爬虫理解为你的很多分身,这些分身分别从不同的网站抓取大量的信息并从中筛选出来对你有价值的信息。谷歌和百度搜索引擎的基础就是放出无数个爬虫,想办法从互联网几乎所有网站中索引信息再通过复杂的算法让人们检索出有价值的信息。同样,网络爬虫也可以用来抓取用户的隐私信息,非法破解网站接口从而抓取未经授权的非公开或未经授权的数据。我们一般将前者称为善意的爬虫,后者称为恶意的爬虫。另外,网站创建者可以通过种种方式限制爬虫采集数据,但是爬虫开发者总有应对之道,由于网站主要还是服务访客的,不可能为了防止爬虫而将无辜的访客拒之门外,因此我们便可以顺着伪装为普通访客这样的基本思路解除反爬虫限制。夫不可陷之盾与无不陷之矛,不可同世而立。今天就浅谈,网络爬虫中的道与术。
语见《谋攻》篇:“知彼知己,百战不殆;不知彼而知己,一胜一负;不知彼不知己,每战必殆。”作为贯穿全书的认知原则,其主要内容包括:知是战的前提和基础。打仗不能糊涂、莽撞、不明敌情。
现在请把自己想象为一个调兵遣将、攻城拔寨将军,把目标网站想象为敌人,如何才能战胜它呢?只有了解影响战争的诸要素情况,才能作出正确的战争决策,奠定胜利的基础。在开发爬虫的时候,我们要像“将军”一样思考,对方如何,我方如何,清楚对方网站的架构,用到的反爬虫技术,从而见招拆招,成功抓取到想要的数据。
一般来说,我们可以简单地将一个垂直的网络爬虫分为以下几步:
互联网技术日新月异,WEB 开发技术也在不断革新。现在越来越多的网站采用客户端动态渲染数据,前后端耦合性降低,分工明确。遇到这种网站,使用 requests 请求一下,往往是请求了个寂寞,明明你打开的网页中有你想要的数据,但是你请求来的却只有冷冰冰的代码。那是因为,你的网站出现数据大致分为两步,第一步浏览器加载网站前端部分代码,第二步网站代码中 JavaScript 脚本在你浏览器客户端执行,从而请求网站接口获取数据,再通过 DOM 方式、或者 VUE 这种虚拟 dom 的方式对 html 进行一个填充(也就是渲染数据),这样完整的页面才呈现在你的眼前。遇到这种网站,也挺简单的,我们只需要打开浏览器控制台调试工具,然后选择 NETWORK 选项卡,在网页加载的时候,观察每一个链接,找到接口即可。没有加密的 api,比解析传统网站要效率高得多,也舒服的多(废话)。值得一提的是,目前大多数网站不会完全采用前后端分离,为了 SEO,一般首屏采用 SSR (服务端渲染)技术,剩余的采用 ajax 等方式动态加载。这样既保证了对搜索引擎的友好性,又用到了前后端分离。
前文说到,现在很多的网站用前后端分离模式开发,用的都是动态渲染了,一般的直接抓包分析出接口就行,但是有些接口带有 sign 与 token,虽然类似吧,但都挺棘手的。需要有一定的 JavaScript 基础,需要能够从源网站的 JavaScript 代码中分析加签方式或者鉴权方式,从而破解。这就来到了 JavaScript 逆向之路。
很多人遇到爬虫瓶颈就是因为这个,因为只懂 python 不太懂 JavaScript 从而无法分析出加密方式或者鉴权方式以及其流程等。JavaScript 作为一门全世界最流行的语言之一,做爬虫不懂它是做不好的,优秀的爬虫工作者应当熟练掌握 JavaScript 语言。前文提到的接口 sign 与 token,我们可以通过 JavaScript 逆向工程研究网站 JavaScript 源码,弄懂每一个参数是如何构造出来的,我们复现这个过程,就能成功请求到数据。但是,网站开发者们为了防止被逆向,很有可能采用一些措施来降低你看到的 JavaScript 代码的可读性甚至是压根就没打算给人看,比如变量改为非十进制、控制台无限 debug 、webpack 将代码压缩与转义,更甚有采用 obfuscator 机制者,让代码变得非常难看懂。也就是说,你可能看都看不懂,更别提破解里面的加密算法了。看懂是一回事,破解又是另一回事儿了。但是不要紧,不要忘记了第一性原理,我们是为了获取网站代码,既然这条路走不通,那么就可以换条路。比如使用 Selenium 来模拟浏览器操作,所见即所得,能够获取到真正的网站代码,从而实现解析拿到数据。但是这种方式效率较为低下,稳定性也有所降低。
这也是一种比较常见的操作了,数据在你登陆后才展示。浏览器你会,输入账号密码验证码,就能登录,但是如何让我们爬虫登录呢。这就要了解两种 WEB 开发中的登录机制:
我走过最长的路,就是反爬虫的那些套路。除了上面简述的一些机制,还不得不提下面经常遇到的反爬虫套路以及应对方案。
随着互联网的发展,用户从 PC 时代过渡到移动终端时代,几乎人手一个手机,没事都要掏出来看看。这就导致了,大厂们也把开发中心转向了 APP,更甚有不做 web 者。不过,也不得不承认,很多数据,只有 APP 有,而且 APP 的数据好。那么如何抓取 APP 的数据呢,你让我往哪链接发请求?
网络爬虫的主要瓶颈在于目标网站的速度、执行爬虫任务机器的网速以及你代码的速度。我们可以通过多线程与协程来改善程序的抓取速度,当然,快也不一定是什么好事,可能会带来新的问题。这里简单的说一下多线程与协程,假如小明早上起来要做两件事,一件事是烧热水( 5 分钟),一件事是吃早饭( 10 分钟)。现在小明有如下解决方案:
假设让你爬取全网所有的新闻,那么一台机器,显然不太够,要从物理上扩展——多买点服务器。那么爬虫之间的通信、调度就比较有学问了。需要设计出适合你爬虫的调度框架与机制,然后去实现它。也可以使用主流的分布式爬虫框架 Scrapy-Redis 。自己设计出和业务耦合度高的分布式爬虫框架自然是好事,但往往会有很多问题需要解决。
给你一千台机器跑爬虫,你是逐个登录部署吗?显然不够明智。专业的事情交给专业的工具做,一般来说 Docker + Kubernetes 是不错的选择。这里又牵扯到一定的运维知识了,Linux 系统肯定也得玩得转才行。
爬虫水深吗?太深了。因为它涵盖的知识点太多,需要学习的太多。也许你看到这里,可能就要放弃爬虫了。爬虫技术的瓶颈往往在于 JavaScript 逆向与 APP 逆向,所以想搞好爬虫,这两项是必修课。问题不大,会当临绝顶,一览众山小!
说到底,爬虫还是在索取东西。去别人网站采数据一定要小心,不要影响到对方网站的正常运行,你去采蜜直接把蜂巢摘了,这样不好。
本人才浅学疏,本文仅代表个人拙见,望各位大佬批评指正,以求进步。
本文首发于公众号:Code 之禅
同步更新于:
LookCos 的博客 www.lookcos.cn
感谢 dogedoge.com 提供强劲图片存储服务。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.