ReZero's Utopia.

如何写一个简易的爬虫

字数统计: 2.6k阅读时长: 9 min
2020/03/08 Share

如何写一个简易的爬虫

基本概念

有言在先

本文只是新手文,望各位指正

本文图片之类链接打不开,可直接科学上网走外链,参考 原博文

啥是爬虫

按一定规则,遵循协议实现的请求模拟接口。

学会爬虫的好处

  1. 了解一些法律常识
  2. 吃牢饭
  3. 学习 web 相关的基础知识

推荐阅读

robots 协议

Requests 官网文档

大才哥的 Blog

Scrapy 官网文档

基础

1
2
with open('/usr/bin/ls', 'w') as f:
f.write(parse(request.get("http://api.com?id=1' or 1='1)))

上面是一个基础爬虫的所有内容,包括了请求,解析处理以及数据的持久化, 毫无疑问这种爬虫不够快,我们给他改装下,用上多进程和异步协程(python的多线程有全局锁,所以用起来可以说是食之无味),这里推荐阅读 Python 异步协程和多进程使用


多进程协程知识扩展: PENDING


改装过后的爬虫速度上去了,但是不够健壮,爬虫的基本目标数据锁定好后,剩下的工作几乎都是为了让爬虫能够稳定的爬取这些数据,也就是说我们需要应对反爬来制定反反爬策略。

相关技能要求

  1. 一般来说目标数据会有两种存在方式,一种是数据直接清晰的描述在 response 中,这种多见于现行的前后端分离模式,该模式下后端往往提供纯数据的接口供前端渲染。 也有另一种方式,就是模板引擎之类直接渲染在页面上的,这类多是采用解析 element 对页面进行格式化处理来采摘需要的数据。针对前者没什么好说的,后者就要求至少掌握一种 element 的解析方式,这里推荐两种,一种是语义化比较舒服的 bs4, 另一种相对前者略高一点学习成本,有点类似正则自然也具有很高效率的 xpath

  2. 至少了解一种持久化的方式,数据爬取后一般都是要存储的,写文件也好,存关系或非关系型数据库也好,总要有种持久化的方式

  3. 了解一点你所使用语言的性能相关的知识,爬虫毕竟通常是用来采集大量的数据的,如果没有好的性能,效率堪忧不说,也对反爬方的识别提供了充裕的时间。当然这点并非绝对,纯粹的过快的采集也极易被封杀。

常见反爬和反反爬策略

  1. 先说最极端的情况,爬与反爬本来就是个道高魔高的问题,所以一定要把数据持久化,打好标记,做断点续传。

  2. 再说一个极端,反爬针对的是爬虫,所以大部分爬虫都是在模仿人的行为来迷惑目标网站。所以这期间就出了一个特类的爬虫,驱动型爬虫,简单说就是控制浏览器行为模仿人的行为来操作,该方法大多数情况下直接绕过了各类网站做的层出不穷的鉴权操作,这方面推荐的了解是 Chrome Headless, Selenium(很多自动化测试也采用此方法) 此方法过为霸道,霸道总是会有奇效,但此文不做阐述

  3. header 的重要性。http 协议的 request 基本分为三部分, start line, header, body 三部分中body往往封装业务数据作为请求体,start line 几乎是必要的基本信息,那么剩下的 header 部分,就是最适合做验证的地方,对爬虫来说,很重要的一点就是模拟请求,而模拟请求的难点就是 header 的构造。如果全量模拟请求的 header, 那基本得到的就是相同的响应

    • 最基本的反爬操作就是使用随机的 User-Agent 来进行访问,基本两种最为适用,一种是通用的浏览器 User-Agent,另一种是常见的搜索引擎 User-Agent。 看起来后者更有效,其实不然,只需要反爬方简单的nslookup 下几乎一个正则就能判定真伪。而前者才是更通用的选择,毕竟用户就是用的这些通用浏览器。此外有些爬虫可能在 PC 端不好爬,可以通过更换该属性切换另个平台比如手机端进行尝试,有可能有奇效。

    • Cookie, 这个就是过鉴权的方式之一,传统的 web 应用往往基于 Cookie 来存放验证信息,所以爬虫方只要获取一个活性 Cookie 就可以,而为了维护 Cookie 的有效性, 可以考虑去维护一个 Cookie 池,定期取用活性的 Cookie, 清理或刷新失效的 Cookie

    • Referer,溯源链接,带上就好

  4. CSS,反反爬的一个难点 。对于解析页面,审查元素是最常用的定位技能,然而用户看到的数据,和定位的元素未必是同一个数据,这点可以利用 css 的一些方法来实现 trick(比如元素偏移,伪元素,字符集替换等),这里列举几篇文章:CSS 反爬CSS 隐藏式自如反爬SVG 反爬 有兴趣的可以自加搜索。

  5. IP 限频。其实封 IP 这种事应该是一种AOE式攻击,可能效果非常显著,但是误伤的几率也应该很大。所以这个没啥好说的,自己从网上找几个免费代理网站,爬下来维护个 IP 池(这其实和前面的刷 Cookie, User-Agent 效果是一样的),随机取出来能用的作为活性代理即可。这种方法弊端很明显,免费的代理大家都清楚,不稳定,慢,gg 的快,所以除此之外还有一种骚操作,就是 ADSL 拨号,通过拨号上网,既能保障稳定的速度,又能及时更换新的 IP

  6. 投毒蜜罐。 这个是我的知识盲区,试想你每次都打印你同学的实验报告,直到有一次被他发现,然后他就偷偷地在里面掺了一段小黄文。这能怎么办?如果商家返回的数据真的是进行了投毒,对数据进行了掺假,这发现了也许还有应对措施,但大多数情况下无法分辨是否有假数据。相对投毒,蜜罐更加直接,发现你是爬虫之后直接为你替换成假数据接口,甚至对你的行为模式进行分析,下次你再用相同的手段去爬取几乎就是难上加难了。

  7. 验证码, 这个属于鉴权的一种吧。现在多是采用两种应对模式,一种就是找样例数据,打tag,自己去训练模型,对验证码进行识别。另一种就简单暴力,人工打码,上了年纪的人应该都听说过一种兼职叫 刷单,打码平台也是这个道理,他会召集一些可能无聊的人,让他们人工式地去帮忙识别验证码,这种方法的好处是能应对任何人类可以破解的验证码(比如 12306 这种变态的验证),这种方式能想到的坏处就是人力资源可能会越来越贵,所以以后来说可能还是前者可能性更高

  8. SQL 注入, 有一说一,爬虫本来就是种注入手段(例如 SqlMap),所以对面说你先动的手你也没啥好委屈的。说到安全,不得不说,很多渗透或者攻击手段,其实都是直接或间接地利用了爬虫。比如常见的工具 setoolkit 中克隆站点的方式,通过爬取模拟目标网站,采用社会工程的方式去钓鱼,诱导用户。再比如批量构造子域名或访问路径,来猜测目标网站的后台地址,又或者拦截请求,直接修改参数进行暴力破解等。

  9. JS 加密混淆,反混淆工具推荐: JStillery

  10. 图片数据,将数据渲染成图片的形式返回响应。这个没有溯源的办法, 目前可行的都是做 OCR 识别

框架的推荐

  1. 如果只是写简单的爬虫,那么推荐 requests 搭配个 bs4 就够用了,整挺好

  2. 如果想用个成熟点的工具,那么就推荐一下 scrapy ,当然仍强烈推荐阅读官网文档

Scrapy

  • 初始化时核心部分 Engine 会从 Spider 处获取初始请求以开始作为整个流程的起点。

  • 上述的请求会入队 Scheduler

  • Engine 真正取请求进行工作是从 Scheduler 获取的。

  • Engine 将请求发送到下载器。

  • 请求完成后,Downloader 会生成一个响应结果并将其回复给 Engine。

  • Engine 接收响应,并将其发送到 Spider 进行处理

  • Spider 将响应处理成两部分,一部分是解析后的需要数据作为 Item 另一部分是新的请求。

  • Engine 将处理后的 Item 发送到 Item Pipelines,然后将处理后的请求发送到 Scheduler。

  • 重复上述整个流程,直到 Scheduler 无新的请求为止。

其实图片已经描述的很清楚了,这里只是复述了一遍。总体来说框架的结构还是很通俗易懂的,这里有两个特殊的中间件需要关注下:一个是 Spider 和 Engine 的中间件,这个中间件主要可以用来做发起请求的 post_process 或者处理一些异常之类的;另一个中间件是下载器附近那个,这个可以用来过滤请求,或者改变回复响应之类的。

闲话部分

前面介绍的大多是基于 http 协议的爬虫,但像是直播弹幕,聊天记录等等这些一般是通过 websocket 协议去实现的,这里其实道理都是一样的,也推荐篇文章 弹幕爬取

另外爬虫的实践也推荐一下,很有意思的分析 新浪微博模拟登录

CATALOG
  1. 1. 如何写一个简易的爬虫
    1. 1.1. 基本概念
      1. 1.1.1. 有言在先
      2. 1.1.2. 啥是爬虫
      3. 1.1.3. 学会爬虫的好处
      4. 1.1.4. 推荐阅读
      5. 1.1.5. 基础
      6. 1.1.6. 相关技能要求
      7. 1.1.7. 常见反爬和反反爬策略
      8. 1.1.8. 框架的推荐
      9. 1.1.9. 闲话部分