scrapy爬虫框架入门

1

  • Scrapy Engine(引擎): 负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等。

  • Scheduler(调度器): 它负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎。

  • Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理,

  • Spider(爬虫):它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器),

  • Item Pipeline(管道):它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方.

  • Downloader Middlewares(下载中间件):你可以当作是一个可以自定义扩展下载功能的组件。

  • Spider Middlewares(Spider中间件):你可以理解为是一个可以自定扩展和操作引擎和Spider中间通信的功能组件(比如进入Spider的Responses;和从Spider出去的Requests)

  • 创建一个Scrapy项目
  • 定义提取的Item
  • 编写爬取网站的 spider 并提取 Item
  • 编写 Item Pipeline 来存储提取到的Item(即数据)

创建项目

在开始爬取之前,您必须创建一个新的Scrapy项目。 进入您打算存储代码的目录中,运行下列命令:

scrapy startproject tutorial

该命令将会创建包含下列内容的 tutorial 目录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
tutorial/
scrapy.cfg

tutorial/
__init__.py

items.py

pipelines.py

settings.py

spiders/
__init__.py
...

其中, tutorial 为项目名称,可以看到将会创建一个 tutorial 文件夹,目录结构大致如下:

下面来简单介绍一下各个主要文件的作用:

  • tutorial.cfg :项目的配置文件

  • tutorial/ :项目的Python模块,将会从这里引用代码

  • tutorial/items.py :项目的目标文件

  • tutorial/pipelines.py :项目的管道文件

  • tutorial/settings.py :项目的设置文件

  • tutorial/spiders/ :存储爬虫代码目录

定义Item

Item 是保存爬取到的数据的容器;其使用方法和python字典类似。虽然您也可以在Scrapy中直接使用dict,但是 Item 提供了额外保护机制来避免拼写错误导致的未定义字段错误。

首先根据需要从dmoz.org获取到的数据对item进行建模。 我们需要从dmoz中获取名字,url,以及网站的描述。 对此,在item中定义相应的字段。编辑 tutorial 目录中的 items.py 文件:

1
2
3
4
5
6
import scrapy

class ItcastItem(scrapy.Item):
name = scrapy.Field()
title = scrapy.Field()
info = scrapy.Field()

一开始这看起来可能有点复杂,但是通过定义item, 您可以很方便的使用Scrapy的其他方法。而这些方法需要知道您的item的定义。

编写第一个爬虫(Spider)

Spider是用户编写用于从单个网站(或者一些网站)爬取数据的类。

其包含了一个用于下载的初始URL,如何跟进网页中的链接以及如何分析页面中的内容, 提取生成 item 的方法。

为了创建一个Spider,您必须继承 scrapy.Spider 类, 且定义一些属性:

1
2
3
name: 用于区别Spider。 该名字必须是唯一的,您不可以为不同的Spider设定相同的名字。
start_urls: 包含了Spider在启动时进行爬取的url列表。 因此,第一个被获取到的页面将是其中之一。 后续的URL则从初始的URL获取到的数据中提取。
parse() 是spider的一个方法。 被调用时,每个初始URL完成下载后生成的 Response 对象将会作为唯一的参数传递给该函数。 该方法负责解析返回的数据(response data),提取数据(生成item)以及生成需要进一步处理的URL的 Request 对象。

在当前目录下输入命令,将在mySpider/spider目录下创建一个名为itcast的爬虫,并指定爬取域的范围:
scrapy genspider itcast "itcast.cn"
打开 tutorial/spider目录里的 itcast.py,默认增加了下列代码:

1
2
3
4
5
6
7
8
9
10
11
import scrapy

class ItcastSpider(scrapy.Spider):
name = "itcast"
allowed_domains = ["itcast.cn"]
start_urls = (
'http://www.itcast.cn/',
)

def parse(self, response):
pass

以下为我们的第一个Spider代码,保存在 tutorial/spiders 目录下的 itcast.py 文件中:

1
2
3
4
5
6
7
8
9
10
import scrapy

class ItcastSpider(scrapy.Spider):
name = "itcast"
allowed_domains = ["itcast.cn"]
start_urls = ("http://www.itcast.cn/channel/teacher.shtml",)

def parse(self, response):
filename = "teacher.html"
open(filename, 'w').write(response.body)

或者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# -*- coding: utf-8 -*-
import scrapy
from tutorial.items import ItcastItem


class Opp2Spider(scrapy.Spider):
name = 'itcast'
allowed_domains = ['itcast.com']
start_urls = ['http://www.itcast.cn/channel/teacher.shtml/']

def parse(self, response):
#open("teacher.html","wb+").write(response.body).close()
# 存放老师信息的集合
items = []

for each in response.xpath("//div[@class='li_txt']"):
# 将我们得到的数据封装到一个 `ItcastItem` 对象
item = ItcastItem()
#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)

# 直接返回最后数据
return items

scrapy保存信息的最简单的方法主要有四种,-o 输出指定格式的文件,,命令如下:

  • json格式,默认为Unicode编码
    scrapy crawl itcast -o teachers.json

  • json lines格式,默认为Unicode编码
    scrapy crawl itcast -o teachers.jsonl

  • csv 逗号表达式,可用Excel打开
    scrapy crawl itcast -o teachers.csv

  • xml格式
    scrapy crawl itcast -o teachers.xml

Donate? comment?