制作Spiders爬取网页
使用Scrapy框架制作爬虫的第三步就是制作Spiders,也就是负责爬取和提取数据的爬虫。我们把制作Spiders分为三个步骤实现,分别是创建爬虫、运行爬虫以爬取网页、和提取数据。接下来就对这三个步骤进行详细介绍。
1. 创建爬虫
首先要在项目中创建一个爬虫,创建爬虫的命令格式如下:
scrapy genspider 爬虫名称 "爬取域"
在创建爬虫的命令中,我们需要为爬虫起一个名称,并规定该爬虫要爬取的网页域范围,也就是爬取域。
打开终端,来到当前目录的子目录mySpider/spiders,使用创建爬虫的命令创建一个名为itcast的爬虫,并指定爬取域的范围为“itcast.cn”,具体如下。
scrapy genspider itcast "itcast.cn"
命令行提示,已经使用模板创建了爬虫itcast,如图1所示。
图1 创建爬虫
在PyCharm中打开mySpider/spiders目录,可以看到新创建的爬虫文件itcast.py,该文件的内容已经自动生成,具体如下所示。
# -*- coding: utf-8 -*-
import scrapy
class ItcastSpider(scrapy.Spider):
name = 'itcast'
allowed_domains = ['itcast.cn']
start_urls = ['http://itcast.cn/']
def parse(self, response):
pass
其实我们也可以自己创建itcast.py文件并编写上述代码,只不过使用命令可以免去编写固定代码的麻烦。
从代码中可以看到,自动创建的爬虫类名称是ItcastSpider,它继承自scrapy.Spider类。scrapy.Spider是Scrapy提供的爬虫基类,我们创建的爬虫类都需要从该类继承。爬虫类中需要定义三个属性(name,allowed_domains和start_urls)和一个方法(parse),这些属性和方法的介绍如下所示。
(1) name属性:表示这个爬虫的识别名称。爬虫的名称必须是唯一的,不同的爬虫需要定义不同的名称。
(2) allow_domains属性:表示爬虫搜索的域名范围,也就是爬虫的约束区域。该属性规定爬虫只能爬取这个域名下的网页,不在该域名下的URL会被忽略。
(3)start_urls属性:表示爬取的起始URL元组或列表。爬虫第一次下载的数据将会从这些URL开始,其它子URL将会从这些起始URL中继承性地生成。
(4)parse(self, response)方法:用于解析网络响应。该方法在每个初始URL完成下载后被调用,调用的时候传入从该URL返回的Response对象做为唯一参数。parse方法主要有两个功能,包括:
解析返回的网页数据(response.body),提取结构化数据(生成item)。
生成访问下一页数据的URL请求。
接下来,我们对生成的ItcastSpider类进行自定义修改。首先将start_urls的值修改为需要爬取的第一个URL,代码如下所示。
start_urls = ("http://www.itcast.cn/channel/teacher.shtml",)
然后修改parse方法,在该方法中将响应信息转换成文本,保存在tearcher.html文件中。代码如下所示。
def parse(self, response):
with open("teacher.html", "w", encoding="utf-8") as file:
file.write(response.text)
2. 运行爬虫,爬取网页
ItcastSpider类的代码修改完成后,接下来就可以运行itcast爬虫来爬取网页了。运行爬虫的命令格式为:
scrapy crawl 爬虫名称
我们在终端中进入itcast.py文件所在的目录,执行如下命令。
scrapy crawl itcast
上述命令里的itcast就是ItcastSpider类的name属性的值,也是使用scrapy genspider命令时确定的爬虫名称。
一个Scrapy爬虫项目里,可以存在多个爬虫,各个爬虫在执行时,就是按照name属性来区分的。
命令执行之后,如果打印的日志出现如下提示信息,则代表爬取过程执行完毕。
[scrapy.core.engine] INFO: Spider closed (finished)
之后当前文件夹就会出现一个teacher.html文件,文件内容就是我们使用爬虫itcast爬取到的网页的全部源代码信息。图2是该文件的部分内容。
图2 teacher.html文件的部分内容
3. 提取数据
通过前面两个步骤,我们已经成功爬取到了网页的源码,接下来就可以从源码中提取数据。要提取数据,首先需要观察页面源码,定位目标数据,分析和了解目标数据的展示结构,如图3所示。
图3 观察页面源码,定位目标数据
从源码中分析的结果是,每个讲师的信息都包含在一个div里,该div展示了讲师的名称、级别和个人信息,其结构如下所示。
<div class="li_txt">
<h3>讲师名称</h3>
<h4>讲师级别</h4>
<p>讲师个人信息</p>
</div>
分析并了解到目标数据的展示结构之后,就可以使用Scrapy支持的Xpath解析方式进行数据提取了。
我们之前在项目的mySpider/items.py目录下定义了MyspiderItem类,需要将该类引入到itcast.py文件中,代码如下。
from mySpider.items import MyspiderItem
然后修改ItcastSpider类的parse方法,将得到的数据封装成一个MyspiderItem对象,每个对象保存一个讲师的信息,然后将所有的对象保存在一个列表items里。代码如下所示。
def parse(self, response):
items = [] #存放老师信息的集合
for each in response.xpath("//div[@class='li_txt']"):
# 将我们得到的数据封装到一个'MyspiderItem'对象
item = MyspiderItem()
# extract方法返回的都是Unicode字符串
name = each.xpath("h3/text()").extract()
title = each.xpath("h4/text()").extract()
info = each.xpath("p/text()").extract()
# XPath返回的是包含一个元素的列表
item["name"] = name[0]
item["title"] = title[0]
item["info"] = info[0]
items.append(item)
# 返回数据,不经过pipeline
return items
此时在命令行中使用“scrapy crawl itcast”命令再次运行爬虫,就可以看到控制台打印出获取到的讲师信息。部分打印信息如图4所示。
图4 获取到的部分目标数据
多学一招:在PyCharm中执行爬虫项目
到现在为止,都是在命令行中输入命令来执行爬虫项目。我们可能会想,如果能够通过PyCharm来执行项目,不是更加简单吗?其实是可以实现的,只需要以下几个步骤。
(1)在PyCharm中打开项目,在项目中添加一个文件,取名为start.py,内容为:
from scrapy import cmdline
cmdline.execute("scrapy crawl itcast".split())
这个文件的内容就调用了命令行来执行语句。
(2)在PyCharm中运行start.py文件,就可以了。这样就不用每次再手动通过命令行来运行了。