有思俱乐部学习园地

Python Scrapy 入门指南


序言

Python是一种广泛使用的高级编程语言,属于通用型编程语言,由吉多·范罗苏姆创造,第一版发布于1991年。可以视之为一种改良(加入一些其他编程语言的优点,如面向对象)的LISP。作为一种解释型语言,Python的设计哲学强调代码的可读性和简洁的语法(尤其是使用空格缩进划分代码块,而非使用大括号或者关键词)。相比于C++或Java,Python让开发者能够用更少的代码表达想法。不管是小型还是大型程序,该语言都试图让程序的结构清晰明了。

与Scheme、Ruby、Perl、Tcl等动态类型编程语言一样,Python拥有动态类型系统和垃圾回收功能,能够自动管理内存使用,并且支持多种编程范式,包括面向对象、命令式、函数式和过程式编程。其本身拥有一个巨大而广泛的标准库。

Python 解释器本身几乎可以在所有的操作系统中运行。Python的正式解释器CPython是用C语言编写的、是一个由社区驱动的自由软件,目前由Python软件基金会管理。

Python Scrapy 是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。本指南基于 Scrapy 1.5 进行编写,内容涉及安装,使用,开发,API 调试等全部知识点,帮助读者学习使用 Scrapy 框架开发网络爬虫。


部署开发环境

本指南基于以下环境进行开发,以供读者参考

操作系统

Windows 10 x64 1803 专业版

Python 3.6

下载链接

https://www.python.org/downloads/release/python-365/

PIP 10.0.1

于 Windows 下的 Python3.6 已经包含pip,故无需另外安装,若不是最新版本可以用过在CMD中输入以下命令进行升级:

python -m pip install --upgrade pip

Scrapy

Scrapy 1.5 可以通过在CMD中输入下方命令进行安装:

pip install scrapy

在安装过程中会自动安装所需的依赖,只需静候安装完成即可


文本编辑器

极力推荐使用 VSCode 进行开发,下方的链接是VSCode的官方站点

https://code.visualstudio.com/

你可以在下载列表中选择你需要的版本,这里作者选择的是 Windows 10 x64 Installer 版本

当然,其它文本编辑器也可以用来编码,作者在此只是进行编辑器的推荐,其它如Sublime Text, Atom, Notpad++ 等其它文本编辑器都是不错的。


起手式:创建一个 Scrapy 项目

在开始爬取之前,我们首先要创建一个scrapy项目,在命令行输入以下命令即可创建:

scrapy startproject myFirstSpider

若出现类似下方提示,就说明创建成功

New Scrapy project 'myFirstSpider', using template directory 'c:\\python36\\lib\\site-packages\\scrapy\\templates\\project', created in:

    E:\workspace\myFirstSpider

You can start your first spider with:

    cd myFirstSpider

    scrapy genspider example example.com

这样,我们就成功创建了一个名为 myFirstSpider 的 Python Scrapy 项目,我们来看看他的目录结构:

我们只需要输入一行命令,Scrapy 就会为我们将项目目录初始化完成,十分便捷

接下来,我们创建一个爬取 NGA 社区彩虹六号首页的爬虫试试看吧

我们只需要在CMD中进入刚才初始化完成的项目目录,然后输入如下命令:

scrapy genspider ngaSpider http://bbs.ngacn.cc/thread.php?fid=600

运行后,我们会发现,spiders 目录下会多出一个名为 ngaSpider.py 的文件,该文件内容如下:

其中 parser 函数是解析函数,如果不特别指明的话,scrapy抓回来的页面会由这个函数进行解析

对页面的处理和分析工作都在此进行,这个示例里我们只是简单地把页面内容保存到本地

我们将代码改成如下图所示的样子:

我们来尝试运行一下看看效果,只需要再 CMD 中输入下方的命令即可:

scrapy crawl ngaSpider

会的到类似下方的输出:

如果出现错误,只需要用下方的命令安装 pywin32 后,再运行爬虫即可

pip install pywin32

爬虫运行完成后,我们会得到一个爬虫保存的文件,静静的躺在我们的项目目录下,如下图所示

我们用文本编辑器打开这个文件,就可以看到这个页面的内容了

看上去,我们像是被反爬规则限制导致我们没有抓取到首页的内容,只抓取到一些没有意义的乱码。

不过没有关系,通过上面的步骤,我们对 Scrapy 的流程已经有一个初步的了解了,我们换一个目标站点继续深入学习。

接下来我们将对 http://lab.scrapyd.cn 这个站点进行数据抓取。

我们将爬虫的代码修改一下,改成如下图所示的样子

输入 scrapy crawl labSpider 运行一下,我们会得到的结果如下

我们打开文件会看到抓取到的内容

这一节只是简单的介绍 Scrapy 的一些流程和用法,在下一节,我们会用到 Scrapy 一些非常有用的工具来帮助我们达到数据抓取的目的。

按规则批量抓取

我们接上一节内容继续。

首先我们先分析 http://lab.scrapyd.cn 页面内容

页面里面有很多类似这样的句子,有内容、作者、以及这个句子附带的标签。

接下来我们尝试将这些内容抓取下来

首先我们需要查看页面的HTML结构,比如下面这张图的结构对应上图的内容:

那我们要爬取的标签分别是:

  • 名言,对应着 class=“text” 标签里面的内容
  • 作者,对应着 class=“authou” 里面的内容
  • 标签,对应着 class=“tags” 里面的内容

我们这个时候可以借助 Scrapy Shell 来分析页面内容,帮助我们编写代码

我们只需要在 CMD 中输入 scrapy shell http://lab.scrapyd.cn 即可

这时我们会得到类似这样的输出:

接着,我们尝试用CSS选择器来选择元素,比如:

sentence1 =  response.css('div.quote')[0]

用来选择页面中第一个class为quote的div,选择完成后,我们来看看里面的内容,输入下方语句即可:

sentence1.css('.text::text').extract_first()

对应的,我们也能用这个方法来分别获得作者、标签等等信息。


既然我们现在已经知道怎么样解析页面内容了,我们就针对页面内容来写解析函数,比如下面这个样子:

运行后得到的结果如下:

你会发现,我们要抓取的页面的第一个句子都被写入到本地的文本文件中了。

接下来我们对代码进行一些修改,让他将页面中所有句子都抓取下来,我们将代码修改为下图的样子:

对比之前的代码,区别主要在,选择器选择的是所有句子,而不是每页第一个。

那么我们在CMD输入

scrapy crawl labSpider

运行后的得到的结果如下图

现在我们得到了我们目标页面的所有我们想要的数据。

你可能会问,如果这个网站有100页,我岂不是要输入100个url?

其实不必那么麻烦,我们可以通过一些简单的操作,让爬虫自己抓取下一页的内容!

下一节,文内会讲述如何完成这一步操作。

整站爬取

我们既然要爬取下一页,那我们首先要分析链接格式,找到下一页的链接,那爬取就简单了,我们先来看看,下一页链接长什么样?

DOM内容为下图所示:

我们可以和很清晰的分析出,下一页这个A标签href属性的值是 http://lab.scrapyd.cn/page/2/

这就是我们爬取全站所需的链接了,那到底如何让蜘蛛自动的判断、并爬取下一页、下一页的内容呢?

我们可以这样来做,我们每爬一页就用css选择器来查询,是否存在下一页链接,存在则爬取下一页链接,然后把下一页链接提交给当前爬取的函数,继续爬取,继续查找下一页;找不到下一页,说明所有页面已经爬完,那结束爬虫。

我画了一张图帮助读者理解全站爬取的流程和爬虫的生命周期,我们来看一下简单的流程图,全站爬取的逻辑很清晰,

现在我们来改写一下代码,如下图所示:

首先,我们使用 response.css('li.next a::attr(href)').extract_first() 

查看是否存在下一页链接。如果存在的话,我们使用:urljoin

方法将相对路径转为绝对路径。

接下来我们使用这么一个方法:scrapy.Request

 这个方法还有许多参数,这里我们只使用了两个参数。

第一个,我们继续爬取的链接(next_page),这里是下一页链接,当然也可以是内容页。

另一个是:我们要把链接提交给哪一个函数爬取,这里是parse函数,也就是当前函数。

当然,我们也可以在下面另写一个函数,比如:内容页,专门处理内容页的数据。经过这么一个函数,下一页链接又提交给了parse,那就可以不断的爬取了,直到不存在下一页。

运行完成之后的脚本,得到的结果如下:

这时候你会发现,目标站点每一页内的内容都已经静静的躺在文件夹内了。

数据入库

在实际运用中,我们通常会选择一种数据库来存储我们的数据,而不是像上一节那样,将抓取到的数据放在硬盘中。

因为,这并不便于数据的利用。在这一节,我们选择 MySQL 来作为我们使用的DB类型,并且将我们抓取到的数据存入 MySQL DB 中。

首先我们需要先在 Pip 中安装一个用于连接 MySQL 用的包,命令如下:

pip install PyMySQL

得到的效果类似下图:

我们安装好了用于连接 MySQL DB 的包后,在工作室的实验DB中创建一个新的库,名为 scrapySpiderTest

这里我推荐GUI DB管理软件 Navicat Premium, 非常便捷。

如下图:

字符集与排序规则需要选择 utf8 utf8_general_ci

然后在该DB内创建一个表结构如下图的表:

ID那一栏需要设定为自动递增

至此,用于存储数据用的数据结构已经建立完成,接下来只需要往里面填充数据即可。

接下来需要编写一pipeline 组件,Spider 爬取的数据(也就是item定义的内容),通过 yield 便提交给了 pipeline,然后在 pipeline 里面就可以实现数据的:去重与存储。

如果我们要编写一个 pipeline 组件,比如:mysqlPipline(命名随意,根据这个类的具体功能来即可)我们必须要在这个组件(类)中实现一个名为 process_item(self, item, spider) 的方法,这个方法有两个参数,一个是item,一个是spider。

item 就是爬取到的数据,spider 就是爬取数据的爬虫,执行完数据库插入之后,需要执行返回。

另外在 pipeline 中还有另外两个 scrapy 提供的非必需实现的方法,分别为

  • open_spider(self, spider)
  • close_spider(self, spider)

对应的作用是

  • 在爬虫开始时执行
  • 在爬虫结束后执行

这里只是简单介绍下这两个非必需实现的方法,读者可以根据自己的需求来调整代码实现的部分。

pipeline 组件的编写,我们可以参考项目目录中的 pipeline.py 文件,

那么我们首先需要实现的是创建与数据库的连接,然后再实现具体的类,创建名为 mysqlPipeline.py 文件,代码实现如下

然后修改一下 item.py, 比如下面这样

上面分别是要入库的字段。

最后,再改写 spider 文件,实现如下

最后,很重要的一件事情是,我们需要在 setting 中启用我们编写的 MysqlPipeline 组件,否则运行时会报错。

setting.py 中找到 ITEM_PIPELINES 取消注释,并改写成如下图所示的代码

我们来运行后会得到类似的输出:

看看数据库content表里的内容:

可以看到,数据都已经静静的躺在数据库里面啦,如果你得到下面这样的结果:

你需要检查数据库的字符集类型排序类型以及爬虫插入数据库时使用的字符集类型

至此,数据已经成功入库,在下一节将会讲解使用scrapy开发爬虫过程中的一些杂项,例如在VSCode中调试、绕过反爬虫规则的技巧等等。

在 VSCode 中调试 Scrapy Spider

其实在 VSCode 中调试 Scrapy Spider 是非常简单的事情。

我们在项目目录中新建一个名为 runner.py 的文件,他的内容如下:

from scrapy.cmdline import execute
execute([
'scrapy','runspider', 'fullly qualified path to myspider.py file'])

实际运用上,你需要这样写

这个时候你只需要在你想要调试的文件内设置断点,然后再 runner.py 文件中按F5进入调试,运行到断点时进程会被挂起,这时就可以进行调试操作。

更改 Spider User Agent

有时我们会需要更改如UA等信息以迷惑被爬取的站点,防止将除常规浏览器之外的请求屏蔽,或着处于让spider更像正常访客的角度考虑,我们就需要来修改 Spdier User Agent,也就是UA。

在这里介绍一种非常简单的方式去修改UA,打开 setting.py,找到 User-Agent 改成你想要的UA即可,比如:

这样 Spider 在爬取内容时,提交的 header UA 部分就是自定义的内容了。

结语

通过上面的实践,你会发现,使用 Python Scrapy 开发爬虫其实并不是太难,并且非常的有意思。

在这里,作者提供一些对于深入 scrapy 学习的一些资料,希望正在努力的你有所帮助 :D