大数据流行的今天,网络爬虫成为了获取数据的一个重要手腕。但要学习好爬虫并没有那么简单。由于学习点、学习方向等实在是太多了,而且它涉及到计算机网络、后端编程、前端开发、App 开发与逆向、网络安全、数据库、自动化运维、机器学习、数据分析等各个方向的内容,它像一张大网一样,把如今一些主流的技术栈都囊括在内。正由于设计内容的多样性,需要学习的东西也变得十分零散和杂乱。很多初学者找不到具体的学习方向。学习过程中遇到反爬、JS渲染等问题,也不知道该如何处理。基于这些年的爬虫经验,梳理了一下作为一个初学者,需要掌握的内容。
语言的选择
C语言历史悠久,Java横行当下,大多初学者可能在大学都接触过这两门语言。但他们都有缺点,C语言学习难度大,Java太复杂,效率也有点底,Python则刚刚好。所以,本文所讲内容均以Python为开发语言。
初学爬虫
一般的网站,常常不带任何反爬措施。比方某某博客站点,我们要爬全站的话就顺着列表页爬到文章页,再把文章的时间、作者、正文等信息爬下来就能够了。
那代码怎样写呢?用 Python 的 requests 等库就够了,写一个根本的逻辑,顺着把一篇篇文章的源码获取下来,解析的话用 XPath、BeautifulSoup、PyQuery 或者正则表达式,或者粗暴的字符串匹配把想要的内容抠出来,再加个文本写入存下来就完事了。
代码很简单,就几个办法调用。逻辑很简单,几个循环加存储。最后就能看到一篇篇文章就被我们存到本人的电脑里面了。如果有的童鞋说代码我也不想写,那么你就用第三方的可视化爬取工具,如某爪鱼、某裔采集器等,也能经过可视化点选的方式把数据爬下来。
如果在存储方面需要在扩展一下的话,可以结合MySQL、MongoDB、Elasticsearch、Kafka 等来完成数据的持久化。以后查询等也会方便很多。所以,在不考虑效率的情况下,一个完整没有反爬的网站用最最根本的方式就搞定了。
看到这里,你就说你学会采集了?NO,Its a long way off!
动态数据(Ajax、动态渲染)
随着互联网的开展,前端技术也在不时变化,数据的加载方式也不再是单纯的效劳端渲染了。如今你能够看到很多网站的数据,可能都是经过接口的方式传输的,或者即便不是接口那也是一些 JSON 的数据,然后经过 JavaScript 渲染所来。
这时,你要再用 requests 来爬那就不顶用了,由于 requests 爬下来的是HTML或jsp等源文件内容,和浏览器中看到的内容并不一样。真正的数据是需要经过 JavaScript 渲染,数据来源可能是 Ajax,也可能是页面里的某些 Data,也可能是一些 ifame 页面等。不过,一般情况下 Ajax 接口获取方式较多。
所以很多状况下需要分析 Ajax流,分析这些接口的调用方式,然后通过代码来模拟访问,请求相应的数据。但是有些接口带着加密参数,比方 token、sign 等等,又不好模仿,咋整呢?
一种办法就是去剖析网站的 JavaScript 逻辑,死磕代码逻辑,分析出各个参数含义,梳理出思路,再用爬虫模仿重写就行了。假如你解出来了,那么直接模仿的方式获取数据的效率会极高。当然,这就需要你会一些 JavaScript 知识了,当然有些网站加密逻辑做的太牛逼了。有时,你可能花一个星期也解不出来,最后还是放弃了。
这时候咋办呢?那我们就用一种简单粗暴的办法来获取数据,那就是直接用模拟浏览器访问的方式来爬取,比方用 Puppeteer、Pyppeteer、Selenium、Splash 等,这样爬取到的源代码,就是JavaScript 渲染以后的真正的网页代码,数据自然就好提取了。同时也就绕过分析 Ajax 等 JavaScript 逻辑的过程。这种方式就做到了可见即可爬,难度也不大。
当然,现在的网站有一些技术挺牛的,能够辨识出webdriver等驱动,看到你是用的 Selenium 等工具,直接拒绝访问或不返回数据,所以碰到这种网站,还是需要具体情况具体分析一下,找到解决的方法。
多进程、多线程、协程
上面说的模拟浏览器方法的方式挺简单的,但是就是爬虫数据的速度较慢,不适合生产环境下使用。
爬虫是 IO 密集型的任务,大多数状况下都是在等候网络的响应,如果网络响应速度慢或者网站响应慢,就一直处于等待的状态。但这个等待时间,其实是可以让 CPU 去做其他的事情。那需要如何实现呢?这时,多线程就派上用途了。
虽然说多线程有 GIL 锁,但对于爬虫来说其实影响并不大,某些场景下加上多进程、多线程,数据的爬取速度会呈指数的增长。那怎么做呢?这时threading、multiprocessing等出现了。
如果能再使用上异步协程,就更牛X了,结合使员工 aiohttp、gevent、tornado 等插件,你想搞几并发就搞几并发,但还是要控制好速度,一方面是为了避免网站封你 IP、封你账号、弹验证码、返回假数据,另一方面,也要做一个有道德的爬虫,不能把别人的网站搞瘫了。
总之,用上这几个,采集速度一定是不用担心了。
分布式布式
多线程、多进程、协程都能够加快采集的速度,但终还是单机版。要真正做到规模化, 还得靠分布式来实现。分布式核心是资源共享。比方爬取队列、去重指纹等共享。现实中,小数据量的采集可以使用数据库,如MySQL、DB2、Oracle等实现,但是到规模化、大批量采集时,数据库会成为瓶颈,Redis等基于内存的NoSql数据库是个不错的选择。
如今主流的 Python 散布式爬虫还是基于 Scrapy 的,对接 Scrapy-Redis、Scrapy-Redis-BloomFilter 或者用 Scrapy-Cluster 等等,他们都是基于 Redis 来共享爬取队列的,总会多几少遇到一些内存的问题。所以一些人也思索对接到了其他的消息队列上,比方 RabbitMQ、Kafka 等等,其实效果也差不多少。
总之,想大规模、批量、高效的采集数据,分布式是必不可少的。
常在河边走哪有不湿鞋,爬取的网站多了,总会遇到那么几个难搞的网站,此时验证码就是其中之一。想要解决反爬,验证码首当其冲。
现在很多网站都会有各种各样的验证码了,比方最简单的图形验证码,要是验证码的文字规整的话,OCR 过一遍或者根本的模型库都能辨认,不想搞这个的话能够直接去对接个打码平台来搞,精确率还是有的。
但是现在图形验证码已经越来越少了,都在向行为验证码发展,如某验、某盾等等,国外也有很多,比方 reCaptcha 等等。一些略微简单一点的,比方滑动的,你能够找点方法辨认缺口,比方图像处置比对、深度学习辨认都是能够的。轨迹呢本人写个模仿正常人行为的,加点颤动之类的。有了轨迹之后咋模仿呢,假如你牛逼,那么能够直接去剖析验证码的 JavaScript 逻辑,把轨迹数据录入,那就能得到里面的一些加密参数,直接拿着这些参数放到表单或接口里面就能直接用了。当然也能够用模仿阅读器的方式来拖动,也能经过一定的方式拿到加密参数,或者直接用模仿阅读器的方式把登录一同做了,拿着 Cookies 来爬也行。
拖动只是一种验证码,还有文字点选、逻辑推理等,要是真不想搞,能够找打码平台来解出来再模仿,但毕竟花钱的,一些高手就会选择本人锻炼深度学习相关的模型,搜集数据、标注、锻炼,针对不同的业务锻炼不同的模型。这样有了中心技术,也不用再去花钱找打码平台了,再研讨下验证码的逻辑模仿一下,加密参数就能解出来了。不过有的验证码难得很,有的我也没搞定。
当然有些验证码可能是请求过于频繁时才会弹出来,这时换个IP什么的也就解决了。
封 IP
封 IP 也是个令人头疼的事,一般解决的办法就是使用代理。
代理很多种,市面上免费的,收费的太多太多了。但是访问速度都不是太好,这是可以买一批比较便宜的云主机作为代理服务器使用,不过就是成本高一点。如果对效率没有要求,可以把市面上免费的代理用起来,搭建一个代理池,搜集一切可用的免费代理IP,然后加一个测试器不断不时测试,测试的网址能够改成你要爬的网址。这样测试经过的普通都能直接拿来爬你的目的网站 。
付费代理也是一样,很多商家提供了代理提取接口,请求一次可以获取几个代理IP,我们能够同样把它们接入到代理池里面。但这个代理也分各种套餐,什么开放代理、独享代理等等的质量和被封的几率也是不一样的,一般情况下IP还有时效。
有的商家还应用隧道技术搭了代理,这样代理的地址和端口我们是不晓得的,代理池是由他们来维护的,比方某布云,这样用起来更省心一些,但是可控性就差一些。
还有更稳定的代理,比方拨号代理、蜂窝代理等等,接入本钱会高一些,但是一定水平上也能处理一些封 IP 的问题。
不过这些背后也不简单,为啥一个好好的高匿代理就是莫明其妙爬不了,背后的一些事就不多讲了。
封账号
有些信息,只有在模仿登录的情况下才能看到,如果爬的过快,人家网站直接把你的账号封禁了,就啥都没得说了。比方爬的,人家把你号封了,那就全完了。
一种处理办法当然就是放慢频率,控制下节拍。
还有种办法就是看看别的终端,比方手机页、App 页、wap 页,看看有没有能绕过登录的法子。
另外比较好的办法,那就是分流。假如你号足够多,建一个池子,比方 Cookies 池、Token 池、Sign 池反正不论什么池吧,多个账号跑出来的 Cookies、Token 都放到这个池子里面,用的时分随机从里面拿一个。假如你想保证爬取效率不变,那么 100 个账号相比 20 个账号,关于每个账号对应的 Cookies、Token 的取用频率就变成原来的了 1/5,那么被封的概率也就随之降低了。
反爬
上面说的是几种比拟主流的反爬,当然还有十分多奇葩的反爬。比方返回假数据、返回图片化数据、返回乱序数据、返回骂人的数据、返回求饶的数据,一般情况下,具体问题就需要具体分析了。
这些反爬也得当心点,之前见过一个反爬直接返回 命令行 rm -rf 的也不是没有,你要是正好有个脚本模仿执行返回结果,结果就可以跑路了,哈哈哈....
JavaScript 逆向
这一步是比较有难度的。
随着前端技术的进步和网站反爬认识的加强,很多网站选择在前端上下功夫,那就是在前端对一些逻辑或代码停止加密或混杂。当然这不只仅是为了维护前端的代码不被随便盗取,更重要的是反爬。比方很多 Ajax 接口都会带着一些参数,比方 sign、token 等等,这些前文也讲过了。这种数据我们能够用前文所说的 Selenium 等方式来爬,但总归来说效率太低了,毕竟它模仿的是网页渲染的整个过程,而真实的数据可能仅仅就藏在一个小接口里。
假如我们可以把一些接口的参数真正找出其中的逻辑,用代码来模仿执行,那效率就会有成倍的提升,而且还能在一定水平上躲避上述的反爬现象。
但是.......好难好难啊。
Webpack 是一方面,前端代码都被紧缩和转码成一些 bundle 文件,一些变量的含义曾经丧失,不好复原。然后一些网站再加上一些 obfuscator 的机制,把前端代码变成你完整看不懂的东西,比方字符串拆散打乱、变量十六进制化、控制流扁平化、无限 debug、控制台禁用等等,前端的代码和逻辑曾经改头换面。有的用 WebAssembly 等技术把前端中心逻辑直接编译,那就只能渐渐抠了,固然说有些有一定的技巧,但是总归来说还是会破费很多时间。但一旦解出来了,那就万事大吉了。怎样说?就像奥赛题一样,解出来升天,解不出来 GG。
很多公司招聘爬虫工程师都会问有没有 JavaScript 逆向根底,破解过哪些网站,比方某宝、某多、某条等等,解出来某个他们需求的可能就直接录用你。每家网站的逻辑都不一样,难度也不一样。
App客户端
当然爬虫不只仅是网页爬虫了,随着互联网时期的开展,如今越来越多的公司都选择将数据放到 App 上面,以至有些公司只要 App 没有网站。所以数据只能经过 App 来爬。
咋爬呢?首当其冲的就是抓包工具了,如:Charles、Fiddler等,抓到接口之后,直接拿来模仿就行了。
假如接口有加密参数怎样办呢?一种办法你能够边爬边处置,比方 mitmproxy 直接监听接口数据。另一方面你能够走 Hook,比方上 Xposed 也能够拿到。
那爬的时分又怎样完成自动化呢?总不能拿手来戳吧。其实工具也多,安卓原生的 adb 工具也行,Appium 如今曾经是比拟主流的计划了,当然还有其他的某精灵都是能够完成的。
最后,有的时候可能真的就不想走自动化的流程,我就想把里面的一些接口逻辑抠出来,那就得搞逆向了,IDA Pro、jdax、FRIDA 等工具就派上用场了,当然这个过程和 JavaScript 逆向一样很痛苦,有时甚至得分析汇编指令。搞一个案例掉一把头发也不是不可能的。
智能化
上面的这一通,都搞熟了,祝贺你曾经超越了百分之八九十的爬虫玩家了,当然特地搞 JavaScript 逆向、App 逆向的都是站在食物链顶端的男人,这种严厉来说曾经不算爬虫范畴了,这种神我们就不算在里面了,反正我不是。
除了上面的一些技艺,在一些场所下,我们可能也需求分离一些机器学习的技术,让我们的爬虫变得更智能起来。
比方如今很多博客、新闻文章,其页面构造类似度比拟高,要提取的信息也比拟相似。
比方如何辨别一个页面是索引页还是详情页?如何提取详情页的文章链接?如何解析文章页的页面内容?这些其实都是能够经过一些算法来计算出来的。
所以,一些智能解析技术也营运而生,比方提取详情页,一位网友写的 GeneralNewsExtractor(GNE) 表现就十分好。
假设说我来了一个需求,我要爬取一万个新闻网站数据,要一个个写 XPath 吗?假如有了智能化解析技术,在一定的容错条件下,完成这个就是分分钟的事情。
总之,假如我们能把这一块也学会了,我们的爬虫技术就会如虎添翼。
运维
这块也是一个重头戏。爬虫和运维也是息息相关。
比方写完一个爬虫,怎样去快速部署到 100 台主机上跑起来。
比方怎样灵敏地监控每个爬虫的运转状态。
比方爬虫有处代码改动,如何去快速更新。
比方怎样监控一些爬虫的占用内存、耗费的 CPU 情况。
比方怎样科学地控制爬虫的定时运转、
比方爬虫呈现了问题,怎样能及时收到通知,怎样设置科学的报警机制。
这里面,部署大家各有各的办法,比方用 Ansible 当然能够。假如用 Scrapy 的话有 Scrapyd,然后配合上一些管理工具也能完成一些监控和定时任务。不过我如今用的更多是还是 Docker + Kubernetes,再加上 DevOps 一套,比方 GitHub Actions、Azure Pipelines、Jenkins 等等,快速完成分发和部署。
定时任务大家有的用 crontab,有的用 apscheduler,有的用管理工具,有的用 Kubernetes,我的话用 Kubernetes 就多一些了,定时任务也是很好完成。
至于监控的话,也有很多,一些爬虫管理工具自带了一些监控和报警功用。一些云后台也带了一些服务器监控的功能。我用的是 Kubernetes + Prometheus + Grafana,什么 CPU、内存、运转状态,了如指掌,报警机制在 Grafana 里面配一下也很便当,支持 Webhook、邮件以至某钉。
数据的存储和监控,用 Kafka、Elasticsearch 个人觉得也挺便当的,我主要用的是后者,然后再和 Grafana 配合起来,数据爬取量、爬取速度等等监控也都了如指掌。
结语
至此,爬虫的一些涵盖的学问点也就差不多了,怎样样,梳理一下,是不是计算机网络、编程根底、前端开发、后端开发、App 开发与逆向、网络平安、数据库、运维、机器学习都涵盖到了?上面总结的能够算是从爬虫小白到爬虫高手的途径了,里面每个方向其实可研讨的点十分多,每个点做精了,都会十分了不起。
爬虫常常学着学着,就成为了一名全栈工程师或者全干工程师,由于你可能真的啥都会了。但是没方法啊,都是被爬虫逼的啊,假如不是生活所困,谁愿意一身才气呢?
但是有了才气之后呢?摸摸头顶,卧槽,我的头发呢?
嗯,大家都懂的。最后最重要的,珍爱生命、珍爱每一根头发。