写给爬虫小白,浅谈网络爬虫的道与术

2020-11-01 14:31:01 +08:00
 Austin2035

路漫漫其修远兮 吾将上下而求索


2016 年被称为人工智能的元年,这一年 AlphaGo 赢了世界第一围棋高手,IBM 机器人Watson花了几秒钟时间就读懂了诺贝尔文学奖获得者鲍勃迪伦的歌曲所反映的情绪,这类弱人工智能是基于大数据实现的,这些数据来自何方?相当一部分就来自于网络爬虫。
现如今什么最值钱?毫无疑问,是数据。如何获取数据?可以用网络爬虫。有了数据,我们就可以对数据分析,让数据变得有价值,现如今火爆的 AI 、BI 都是基于数据工作。
在大数据时代,网络爬虫是获取数据的重要手段,但这把利剑想驾驭好并不简单,因为铸造它使用了很多技术。它关系到,网站建设、WEB 开发、JavaScript 逆向、APP 逆向、深度学习等。可谓是,道阻且艰。

技术无黑白 攻防无绝对


网络安全圈曾非常流行这句话,我想它放在网络爬虫领域中也同样适用。如果说网站开发者是防守者,那么开发网络爬虫的就是"攻者"。 如果说网站开发者用的是正向思维,那么网络爬虫开发者就是逆向思维。
与安全技术类似,爬虫技术也处于灰色地带,一不小心就从面向对象编程变成了面向“监狱”编程。火可暖身,亦可焚身。 爬虫可以做很多有益于我们的事情,首先我们可以把爬虫理解为你的很多分身,这些分身分别从不同的网站抓取大量的信息并从中筛选出来对你有价值的信息。谷歌和百度搜索引擎的基础就是放出无数个爬虫,想办法从互联网几乎所有网站中索引信息再通过复杂的算法让人们检索出有价值的信息。同样,网络爬虫也可以用来抓取用户的隐私信息,非法破解网站接口从而抓取未经授权的非公开或未经授权的数据。我们一般将前者称为善意的爬虫,后者称为恶意的爬虫。另外,网站创建者可以通过种种方式限制爬虫采集数据,但是爬虫开发者总有应对之道,由于网站主要还是服务访客的,不可能为了防止爬虫而将无辜的访客拒之门外,因此我们便可以顺着伪装为普通访客这样的基本思路解除反爬虫限制。夫不可陷之盾与无不陷之矛,不可同世而立。今天就浅谈,网络爬虫中的道与术。

知己知彼,百战不殆

语见《谋攻》篇:“知彼知己,百战不殆;不知彼而知己,一胜一负;不知彼不知己,每战必殆。”作为贯穿全书的认知原则,其主要内容包括:知是战的前提和基础。打仗不能糊涂、莽撞、不明敌情。

现在请把自己想象为一个调兵遣将、攻城拔寨将军,把目标网站想象为敌人,如何才能战胜它呢?只有了解影响战争的诸要素情况,才能作出正确的战争决策,奠定胜利的基础。在开发爬虫的时候,我们要像“将军”一样思考,对方如何,我方如何,清楚对方网站的架构,用到的反爬虫技术,从而见招拆招,成功抓取到想要的数据。

千里之行 始于足下

一般来说,我们可以简单地将一个垂直的网络爬虫分为以下几步:

  1. 请求数据, 向服务器发出请求,得到服务器相应的 html
  2. 解析数据, 查看并解析 html 中的数据
  3. 数据持久化, 也就是把数据存储下来
    • 首先你要懂得 HTTP 协议基础,最起码得懂 GETPOST,并能利用某一门编程语言发出 HTTP 请求进而才可能获取到网页数据。这里以 python 为例子,新手初学建议用 requests 模块就完全足够了。而且requets源代码是典型的pythonic风格,也很适合学习。
    • 其次,熟悉 HTMLCSS 是必须的。因为我们要的不应该是请求来的一行行 html 格式的字符串,而是解析出我们想要的数据。这就需要我们学会定位元素,找出想要的内容在元素中的位置。一般而言,初学者学 BeautifulSoup 是比较适合的,其实用的比较多的是通过 xpath 定位。除了 Beautifulsoup 外,lxml、PyQuery 也很不错。还有就是用正则表达式,根据返回内容的规则,用正则表达式直接匹配出我们想要的数据。正则表达式,几乎各个主流语言都有支持,但是想学精通正则表达式也不太简单,有很多书专门讲正则表达式,实际上,它本身就是一门语言了。
    • 最后,我们数据请求来了,解析完了,放哪呢?一般来说,都是放到数据库的,数据量小也可以直接把结果写到 txt 文件或者 xlsx 表格。这一步,也被称为数据持久化。数据库有很多种,比如 Sqlite 、MongoDB、MySQL 等。这就需要我们至少能够熟悉一种数据库的增删查改,笔者比较倾向于使用 mongoDB 这种介于关系型和非关系型之间的数据库,谁用谁爽。
      你以为,这就完了?才刚刚开始呢。

前后端分离,动态渲染

互联网技术日新月异,WEB 开发技术也在不断革新。现在越来越多的网站采用客户端动态渲染数据,前后端耦合性降低,分工明确。遇到这种网站,使用 requests 请求一下,往往是请求了个寂寞,明明你打开的网页中有你想要的数据,但是你请求来的却只有冷冰冰的代码。那是因为,你的网站出现数据大致分为两步,第一步浏览器加载网站前端部分代码,第二步网站代码中 JavaScript 脚本在你浏览器客户端执行,从而请求网站接口获取数据,再通过 DOM 方式、或者 VUE 这种虚拟 dom 的方式对 html 进行一个填充(也就是渲染数据),这样完整的页面才呈现在你的眼前。遇到这种网站,也挺简单的,我们只需要打开浏览器控制台调试工具,然后选择 NETWORK 选项卡,在网页加载的时候,观察每一个链接,找到接口即可。没有加密的 api,比解析传统网站要效率高得多,也舒服的多(废话)。值得一提的是,目前大多数网站不会完全采用前后端分离,为了 SEO,一般首屏采用 SSR (服务端渲染)技术,剩余的采用 ajax 等方式动态加载。这样既保证了对搜索引擎的友好性,又用到了前后端分离。

难以逾越的两座大山,sign 与 token

前文说到,现在很多的网站用前后端分离模式开发,用的都是动态渲染了,一般的直接抓包分析出接口就行,但是有些接口带有 sign 与 token,虽然类似吧,但都挺棘手的。需要有一定的 JavaScript 基础,需要能够从源网站的 JavaScript 代码中分析加签方式或者鉴权方式,从而破解。这就来到了 JavaScript 逆向之路。

JavaScript 逆向

很多人遇到爬虫瓶颈就是因为这个,因为只懂 python 不太懂 JavaScript 从而无法分析出加密方式或者鉴权方式以及其流程等。JavaScript 作为一门全世界最流行的语言之一,做爬虫不懂它是做不好的,优秀的爬虫工作者应当熟练掌握 JavaScript 语言。前文提到的接口 sign 与 token,我们可以通过 JavaScript 逆向工程研究网站 JavaScript 源码,弄懂每一个参数是如何构造出来的,我们复现这个过程,就能成功请求到数据。但是,网站开发者们为了防止被逆向,很有可能采用一些措施来降低你看到的 JavaScript 代码的可读性甚至是压根就没打算给人看,比如变量改为非十进制、控制台无限 debug 、webpack 将代码压缩与转义,更甚有采用 obfuscator 机制者,让代码变得非常难看懂。也就是说,你可能看都看不懂,更别提破解里面的加密算法了。看懂是一回事,破解又是另一回事儿了。但是不要紧,不要忘记了第一性原理,我们是为了获取网站代码,既然这条路走不通,那么就可以换条路。比如使用 Selenium 来模拟浏览器操作,所见即所得,能够获取到真正的网站代码,从而实现解析拿到数据。但是这种方式效率较为低下,稳定性也有所降低。

登陆后抓取

这也是一种比较常见的操作了,数据在你登陆后才展示。浏览器你会,输入账号密码验证码,就能登录,但是如何让我们爬虫登录呢。这就要了解两种 WEB 开发中的登录机制:

妖魔鬼怪

我走过最长的路,就是反爬虫的那些套路。除了上面简述的一些机制,还不得不提下面经常遇到的反爬虫套路以及应对方案。

APP 爬虫

随着互联网的发展,用户从 PC 时代过渡到移动终端时代,几乎人手一个手机,没事都要掏出来看看。这就导致了,大厂们也把开发中心转向了 APP,更甚有不做 web 者。不过,也不得不承认,很多数据,只有 APP 有,而且 APP 的数据好。那么如何抓取 APP 的数据呢,你让我往哪链接发请求?

多线程与协程

网络爬虫的主要瓶颈在于目标网站的速度、执行爬虫任务机器的网速以及你代码的速度。我们可以通过多线程与协程来改善程序的抓取速度,当然,快也不一定是什么好事,可能会带来新的问题。这里简单的说一下多线程与协程,假如小明早上起来要做两件事,一件事是烧热水( 5 分钟),一件事是吃早饭( 10 分钟)。现在小明有如下解决方案:

分布式爬虫

假设让你爬取全网所有的新闻,那么一台机器,显然不太够,要从物理上扩展——多买点服务器。那么爬虫之间的通信、调度就比较有学问了。需要设计出适合你爬虫的调度框架与机制,然后去实现它。也可以使用主流的分布式爬虫框架 Scrapy-Redis 。自己设计出和业务耦合度高的分布式爬虫框架自然是好事,但往往会有很多问题需要解决。

爬虫管理

给你一千台机器跑爬虫,你是逐个登录部署吗?显然不够明智。专业的事情交给专业的工具做,一般来说 Docker + Kubernetes 是不错的选择。这里又牵扯到一定的运维知识了,Linux 系统肯定也得玩得转才行。

路逶迤而修迥兮,川既漾而济深

爬虫水深吗?太深了。因为它涵盖的知识点太多,需要学习的太多。也许你看到这里,可能就要放弃爬虫了。爬虫技术的瓶颈往往在于 JavaScript 逆向与 APP 逆向,所以想搞好爬虫,这两项是必修课。问题不大,会当临绝顶,一览众山小!

如欲采蜜 勿蹴蜂房

说到底,爬虫还是在索取东西。去别人网站采数据一定要小心,不要影响到对方网站的正常运行,你去采蜜直接把蜂巢摘了,这样不好。

最后

本人才浅学疏,本文仅代表个人拙见,望各位大佬批评指正,以求进步。

本文首发于公众号:Code 之禅

同步更新于:
LookCos 的博客 www.lookcos.cn

感谢 dogedoge.com 提供强劲图片存储服务。

3129 次点击
所在节点    分享创造
24 条回复
sadfQED2
2020-11-01 15:04:12 +08:00
直接翻到最后
Austin2035
2020-11-01 16:21:00 +08:00
@sadfQED2 为何?看不下去?
misaka19000
2020-11-01 16:40:38 +08:00
现在爬虫不都是吃牢饭的代名词了吗
sunorg
2020-11-01 16:42:58 +08:00
@lookcos 时而文纠纠,时而不是,主题就忘记了
Austin2035
2020-11-01 17:25:49 +08:00
@sunorg 你说的有点道理,越写越拉跨😂
Austin2035
2020-11-01 17:26:56 +08:00
@sunorg 这篇不是我一气呵成,好几个时间片段拼凑写的。情绪不太一样,大致意思就那了。
SaltyLeo
2020-11-01 19:25:41 +08:00
要提炼一些二三级标题啊,几百字一段怎么看的下去...
Austin2035
2020-11-01 20:45:12 +08:00
@SaltyLeo 下次一定
mimi888
2020-11-01 21:01:15 +08:00
其实你应该去写小说
towser
2020-11-02 00:24:49 +08:00
其实内容不错的,只是文章标题主题都不够概括。
Austin2035
2020-11-02 08:12:44 +08:00
@towser 感谢支持
@mimi888 感谢支持
differentPlayer
2020-11-02 09:01:03 +08:00
因为 v2 长文一般都是推广公众号的哈哈哈
Asshasahole
2020-11-02 10:04:11 +08:00
其实写的不错的,我等新手可看
Austin2035
2020-11-02 12:15:56 +08:00
@Asshasahole 现在的人生活节奏快,一篇长文鲜有人能耐心读下来。
如果读下来我这篇,多多少少有点收获。
tikazyq
2020-11-02 17:32:41 +08:00
写得还是不错的,如果能帮我推广一下分布式爬虫管理平台 Crawlab 就更好了

https://github.com/crawlab-team/crawlab
zdb1115
2020-11-02 22:57:34 +08:00
写的很棒 谢谢
L00kback
2020-11-03 14:04:33 +08:00
本来不想看的,结果居然看下去了,内容很棒啊,排版要改改,写的挺好的~

以前写的都是小爬虫爬小网站,加深理解了,感谢
Austin2035
2020-11-03 15:43:05 +08:00
@tikazyq 感谢大佬支持,以后遇到推广机会,会说你这个产品的,哈哈
Austin2035
2020-11-03 15:43:27 +08:00
@L00kback 感谢支持
@zdb1115 感谢支持
lusi1990
2020-11-03 15:52:28 +08:00
建议看看: 浏览器指纹

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/720701

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX