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