前言

Scrapy is coming!!

在写了七篇爬虫基础文章之后,终于写到心心念念的Scrapy了。Scrapy开启了爬虫2.0的时代,让爬虫以一种崭新的形式呈现在开发者面前。

在18年实习的时候开始接触Scrapy,花了一个月的时间,理论结合实践学习了Scrapy。本篇文章不写代码操作,只讲前因后果及理论,愿你懂得Scrapy。

原生爬虫面临问题

无论使用Java的Jsoup也好,python的requests也罢,开发爬虫都会面临下面几个问题:

1.分布式

爬虫程序一般只运行在一台主机上,如果是一模一样的爬虫程序部署在不同的主机上,那都是独立爬虫程序。如果想要弄一个分布式的爬虫,通常的思路是将爬虫程序分为url采集和数据采集两个部分。

现将url爬取下来放入到数据库中,然后通过where条件限制,或者直接使用redis的list结构,让不同主机上的爬虫程序读取到不同的url,然后进行数据爬取。

2.url去重

爬取数据的时候会经常遇到重复的url,如果重复爬取是不是浪费时间。通过url去重的思路就是:将爬取的url放入到集合中,每次爬取都去判断url是否存在于集合中。那么,如果程序中途停止了,这个内存中集合也将不复存在,再次启动程序,将无法判断哪些是已经爬取过的。

那么就用数据库,将已经爬取过的url插入到数据库中,这样就算重启程序,爬取过的url也不会丢失了。可是如果我就是想重新开始爬取,是不是还得手动清空数据库中的url表。每次查询数据库耗费的时间,这都是需要考虑的。

3.断点续爬

假如有1000个页面需要爬取,爬到第999个页面,进度条马上满格的时候,程序咯噔一下挂了,就差一个,但是还是没爬完啊,咋整?我选择重新启动程序,那么你说我怎么样才能直接从第999个开始爬取呢?

这里先讲讲我写的第一个爬虫:爬取10+个地市的poi信息。

实习,第一次开发爬虫,也不知道有高德poi接口啥的,于是就找了个网站来爬取poi信息。当时那个网站估计还在起步阶段,服务器带宽应该不高,访问速度是真的慢,而且动不动维护停站,所以我的程序也得跟着停止。如果每次启动都重新爬取,估计几年也爬不完,于是我想了个办法。

我先将所有地市下所有区县数据的条数(网站上有)先手动录入到数据库表中,每次重新启动爬虫程序的时候,先统计结果数据表中各个区县已经爬取的条数,与总条数进行对比。如果小于的话,说明还没有爬取完,然后通过某区县已爬取条数 / 网站每页展示条数计算出我已经爬取到此区县的页数,再通过余数定位到我爬到了此页面的第几个。通过这种方法,最后无丢失爬取了163w条数据。

换种思路,将爬取的url放到表中,重启程序开始爬取url的时候,先去判断url是否存在于数据表中,如果存在就不进行爬取,这样也能实现断点续爬。也是沿用了原始的url的去重的思路。

4.动态加载

在第六篇基金篇写了一个jsonp的动态加载,算是比较简单的一种,只要找到请求接口获取数据进行处理即可。第七篇写了电视猫的eval()的js加密,这算是很复杂的一种动态加载。请求接口的参数是加密的,需要耗费大量时间来分析密密麻麻的js,来计算出这个186位的参数。

so,有没有一种方式让我既能脱离阅读分析js,还能绕过动态加载?

sure!!首先关于动态加载,可以理解为浏览器内核通过执行js在前端渲染数据。那么我们在程序中搞个浏览器内核,我们直接获取js渲染后的页面数据不就可以了么?

通常使用selenium + chrome、phantomjs、pyvirtualdisplay来处理动态加载,但是或多或少都会有性能问题。

上面说了那么多,根据一贯的套路,大家也应该知道接下来我要说什么了。

关于Scrapy

Scrapy带给我的感受就是:模块分明、结构封装、功能强大。

WHAT

Scrapy是一个分布式爬虫框架,我把它比作成爬虫界的Spring。reqeusts就像是servlet一样,各种功能逻辑都需要自己去实现,而Spring做了集成,底层对用户透明。

就像我们知道,Spring是在application配置文件中初始化bean,在mapper中定义数据库操作一样,而使用者无需关心Spring是如何读取这些配置文件进行各种操作的。同样,Scrapy也提供了这样的功能配置。

所以说,Scrapy是一个爬虫框架,requests是一个爬虫模块,两者是有区别的。

WHY

我的政治老师曾经说过:没有无缘无故的爱,也没有无缘无故的恨。 根据我个人的使用体验,说一下我为什么那么推荐Scrapy。

  1. 性能:基于Twisted进行异步请求,怎一个快字了得!
  2. 配置化:通过配置文件对请求并发、延迟、重试次数等进行定义
  3. 插件丰富:提供了动态加载、断点续爬、分布式的解决方案,几行配置即开即用
  4. 命令行操作:通过命令行可以生成、启停、监控爬虫状态等
  5. Web界面操作:集成了Web界面来启停、监控爬虫
  6. 提供测试环境:提供了shell交互测试环境

HOW

Scrapy又是框架、功能还那么强大,是不是很难学会啊。

这种担忧大可不必,Scrapy的安装和普通python模块的安装一样,只要了解其中四个模块的作用,入门极其简单。而Scrapy爬虫程序的开发逻辑,代码更少、层次更分明,比requests要简单很多。

应用场景

Scrapy作为一个框架,有人觉得scrapy太重量级了,不如requests用起来轻便。在这里只能说,应用场景和侧重点不一样

Scrapy的开发更像是一个工程项目开发。通常用来做多数据源的爬虫数据整合,例如整合视频、小说、音乐、漫画等信息数据到一个数据表中。开发者只需事先约定好的数据字段,即可进行多人协作开发,因为scrapy通过yield关键字即可将数据放到数据库,无需再去显式地调用任何方法。

而requests更适合无需进行统一管理、无需分布式部署的单个爬虫程序的开发。

结语

其实,第一篇应该写Scrapy的架构与安装,但是我觉得用一个技术前,了解这个技术的功能和应用场景还是很有必要的,所以写了这一篇理论知识。

这篇文章写了两遍,第一遍写完了之后,不知道什么原因,在编辑器里被覆盖了,所以只能再重新写一遍。辛亏中间部分截图发给过朋友,还能少写一部分。我也终于明白了曾经网上流传的一种心情:作业写完被狗撕了,不想再写一遍。

希望本篇文章能让你对爬虫的理论知识有更深层次的了解,期待下一次相遇。


95后小程序员,写的都是日常工作中的亲身实践,置身于初学者的角度从0写到1,详细且认真。

文章会在公众号 [入门到放弃之路] 首发,期待你的关注。



Scrapy入门到放弃01:开启爬虫2.0时代的更多相关文章

  1. Scrapy入门到放弃04:下载器中间件,让爬虫更完美

    前言 MiddleWare,顾名思义,中间件.主要处理请求(例如添加代理IP.添加请求头等)和处理响应 本篇文章主要讲述下载器中间件的概念,以及如何使用中间件和自定义中间件. MiddleWare分类 ...

  2. scrapy入门到放弃02:整一张架构图,开发一个程序

    前言 Scrapy开门篇写了一些纯理论知识,这第二篇就要直奔主题了.先来讲讲Scrapy的架构,并从零开始开发一个Scrapy爬虫程序. 本篇文章主要阐述Scrapy架构,理清开发流程,掌握基本操作. ...

  3. Scrapy入门到放弃03:理解settings配置,监控Scrapy引擎

    前言 代码未动,配置先行.本篇文章主要讲述一下Scrapy中的配置文件settings.py的参数含义,以及如何去获取一个爬虫程序的运行性能指标. 这篇文章无聊的一匹,没有代码,都是配置化的东西,但是 ...

  4. Scrapy入门到放弃06:Spider中间件

    前言 写一写Spider中间件吧,都凌晨了,一点都不想写,主要是也没啥用...哦不,是平时用得少.因为工作上的事情,已经拖更好久了,这次就趁着半夜写一篇. Scrapy-deltafetch插件是在S ...

  5. Scrapy入门到放弃05:让Item在Pipeline中飞一会儿

    前言 "又回到最初的起点,呆呆地站在镜子前". 本来这篇是打算写Spider中间件的,但是因为这一块涉及到Item,所以这篇文章先将Item讲完,顺便再讲讲Pipeline,然后再 ...

  6. python scrapy 入门,10分钟完成一个爬虫

    在TensorFlow热起来之前,很多人学习python的原因是因为想写爬虫.的确,有着丰富第三方库的python很适合干这种工作. Scrapy是一个易学易用的爬虫框架,尽管因为互联网多变的复杂性仍 ...

  7. Java从入门到放弃——01.Java 环境搭建

    本文目标: 下载与安装JDK 配置Java环境 1.JDK9下载:  下载地址:https://www.oracle.com/technetwork/java/javase/downloads/jav ...

  8. Python爬虫从入门到放弃(十三)之 Scrapy框架的命令行详解

    这篇文章主要是对的scrapy命令行使用的一个介绍 创建爬虫项目 scrapy startproject 项目名例子如下: localhost:spider zhaofan$ scrapy start ...

  9. Python爬虫从入门到放弃(二十)之 Scrapy分布式原理

    关于Scrapy工作流程回顾 Scrapy单机架构 上图的架构其实就是一种单机架构,只在本机维护一个爬取队列,Scheduler进行调度,而要实现多态服务器共同爬取数据关键就是共享爬取队列. 分布式架 ...

随机推荐

  1. Python学习笔记_购物车案例

    goods_dic = { "iphone":6000, "ipad":3000, "T-shirt":100, "coffee& ...

  2. 鸿蒙的js开发部模式16:鸿蒙布局Grid网格布局的应用一

    鸿蒙入门指南,小白速来!从萌新到高手,怎样快速掌握鸿蒙开发?[课程入口]目录:1.Grid简介2.使用Grid布局实现的效果3.grid-row-gap和grid-colunm-gap属性4.< ...

  3. easyPOI基本用法

    参考网址:http://www.wupaas.com/ 1.Excel文件的导入导出 项目源码:后台:https://github.com/zhongyushi-git/easypoi-demo-ad ...

  4. 基于西门子S7-1500的大型焊接机全套程序,使用博图V14打开(带全部注释)

    程序说明:本套程序是在从事自动化行业时候的做的项目的程序,经过在设备上运行测试,其中包含20多个轴的伺服控制以及模拟量,数字量IO的控制,包括扫描枪的读取,属于大型程序,总步数有好几万步. 本程序注释 ...

  5. Docker daemon socket权限不足

    一.概述 普通用户执行命令:docker ps报错,具体信息如下: docker: Got permission denied while trying to connect to the Docke ...

  6. 学习java之电脑的常用快捷键和DOS窗口下的常用命令

    学习java之电脑的常用快捷键和DOS窗口下的常用命令 电脑一些常用的快捷键 win快捷键: 单独按Windows:显示或隐藏 "开始"功能表 Windows+BREAK:显示&q ...

  7. python基础学习之类的属性 增删改查

    类中的属性如何在类外部使用代码进行增删改查呢 增加.改变: setattr内置函数以及 __setattr__魔法方法 class A: aaa = '疏楼龙宿' a = A() setattr(a, ...

  8. go语言实现数组去重

    import ( "fmt" ) func main() { a := []int{2, 1, 2, 5, 6, 3, 4, 5, 2, 3, 9} z := Rm_duplica ...

  9. Python中类的特殊属性和魔术方法

    1.属性 属性 含义 __name__ 类.函数.方法等的名字   __dir__ __module__ 类定义所在的模块名 __class__ 对象或类所属的类   只是返回基类 __bases__ ...

  10. 初见pyecharts

    pyecharts(可互动的可视化) 模块准备 在Anaconda Prompt中下载pyecharts v1版本(>=python3.6) pip install pyecharts 可视化最 ...