python 的scrapy框架

1. 什么是Scrapy框架?

Scrapy是一个基于Python语言的web抓取框架,可以方便地抓取Web站点,并将抓取的数据存储到本地或各种数据库中。它使用了异步IO模型,处理速度快、效率高,并且支持多个网站的抓取任务。

1.1 安装Scrapy框架

要使用Scrapy框架,需要先安装Scrapy模块。可以通过命令行输入以下命令安装:

pip install scrapy

详细的安装过程可以查看官方文档。安装完成后,可以通过以下命令查看版本信息:

scrapy version

2. Scrapy框架的基本结构

Scrapy框架的三个主要组成部分是:

Spider:定义如何抓取Web站点的规则,以及如何从网页中提取数据

Item:定义抓取的数据模型

Pipeline:定义数据的处理过程,例如存储到数据库或输出到文件等

2.1 Spider组件

Spider组件是Scrapy框架中最重要的组件之一,它定义了如何抓取Web站点的规则,并且从网页中提取数据。Spider组件需要继承自Scrapy提供的Spider类,并实现几个方法:

import scrapy

class MySpider(scrapy.Spider):

name = 'myspider'

allowed_domains = ['example.com']

start_urls = ['https://example.com']

def parse(self, response):

# 解析网页,抓取所需数据

pass

上面的代码就定义了一个简单的Spider。其中,name属性指定了Spider的名称,allowed_domains属性指定了允许抓取的域名,start_urls属性定义了起始网页的URL地址。

Spider组件的核心方法是parse()方法,它接受一个response对象作为参数,这个对象包含了网页的HTML代码。Spider组件需要解析HTML代码,抓取到其中所需的数据。

2.2 Item组件

Item组件指定了抓取的数据模型,它可以看作是抓取到数据的一个容器。每个Item对象代表一条记录,包含了多个字段。

import scrapy

class MyItem(scrapy.Item):

field1 = scrapy.Field()

field2 = scrapy.Field()

field3 = scrapy.Field()

上面的代码就定义了一个简单的Item组件。其中,Field类定义了一个字段。Item组件的每个字段都可以设置为一个Field对象。这样,Spider组件抓取到的数据就可以保存到Item中。

2.3 Pipeline组件

Pipeline组件定义了数据的处理过程,例如存储到数据库或输出到文件等。Pipeline组件需要继承自Scrapy提供的Pipeline类,并实现几个方法:

class MyPipeline(object):

def process_item(self, item, spider):

# 处理数据

pass

上面的代码就定义了一个简单的Pipeline。其中,process_item()方法接受一个Item对象和Spider对象作为参数,Pipeline组件需要对Item对象进行处理。一般情况下,处理完成后的数据会被输出到文件或数据库中。

3. Scrapy框架的使用方法

在实际使用Scrapy框架时,一般按以下步骤进行:

定义Spider组件,写好抓取规则,抓取需要的数据

定义Item组件,设置好数据模型

定义Pipeline组件,处理抓取到的数据,例如存储到数据库或文件中

运行Scrapy命令,启动抓取流程

3.1 定义Spider组件

定义Spider组件最关键的是抓取规则,Scrapy提供了强大的选择器和XPath等语法,可以方便地从HTML代码中提取所需的数据。例如,以下代码就用XPath语法从网页中提取了所有标签的链接地址:

import scrapy

class MySpider(scrapy.Spider):

name = 'myspider'

allowed_domains = ['example.com']

start_urls = ['https://example.com']

def parse(self, response):

# 提取所有链接地址

for href in response.xpath('//a/@href'):

url = response.urljoin(href.extract())

yield scrapy.Request(url, callback=self.parse_item)

def parse_item(self, response):

# 解析详情页,提取所需数据

pass

以上代码中,response.xpath()方法返回了一个XPath选择器对象,代表了网页中所有的标签元素。这个选择器对象使用了XPath语法,选取了所有标签的href属性。然后,通过response.urljoin()方法,将这个链接地址补全,变为绝对地址。

抓取到所有链接地址后,使用scrapy.Request()方法重新请求这个URL地址,并返回一个新的response对象。这个response对象又会被送到parse_item()方法中,提取网页中所需的数据。

3.2 定义Item组件

Item组件定义了抓取得到的数据模型,例如在上面的例子中,可以定义如下的Item:

import scrapy

class MyItem(scrapy.Item):

title = scrapy.Field()

content = scrapy.Field()

datetime = scrapy.Field()

author = scrapy.Field()

这样,Spider组件就可以从网页中抓取这些数据,并且存放到Item对象中。

3.3 定义Pipeline组件

Pipeline组件定义了数据的处理过程,例如存储到数据库或输出到文件等。例如,以下代码将抓取到的数据保存到了MongoDB数据库中:

import pymongo

class MyPipeline(object):

def __init__(self, mongo_uri, mongo_db):

self.mongo_uri = mongo_uri

self.mongo_db = mongo_db

def open_spider(self, spider):

self.client = pymongo.MongoClient(self.mongo_uri)

self.db = self.client[self.mongo_db]

def close_spider(self, spider):

self.client.close()

def process_item(self, item, spider):

collection = self.db[type(item).__name__.lower()]

collection.insert_one(dict(item))

return item

以上代码中,open_spider()方法在Spider启动时被调用,连接到MongoDB数据库。然后,process_item()方法接收一个Item对象,将其插入到MongoDB的对应集合中。最后,close_spider()方法在Spider关闭时被调用,关闭MongoDB数据库连接。

3.4 运行Scrapy命令

定义好Spider组件、Item组件和Pipeline组件后,就可以使用Scrapy命令来运行了:

scrapy crawl myspider -o result.json

其中,myspider是Spider的名称,-o参数指定输出的文件名,这里将抓取结果保存为了JSON格式的文件。

4. Scrapy框架的示例

下面以一个具体的应用为例,介绍Scrapy框架的实际使用方法。

4.1 应用背景

现在,有一个网站https://www.jianshu.com/,想要抓取其中所发布的所有文章的标题和内容,保存到本地。

4.2 编写Spider组件

首先,定义Spider组件myjianshu:

import scrapy

class MyJianshuSpider(scrapy.Spider):

name = 'myjianshu'

allowed_domains = ['www.jianshu.com']

start_urls = ['https://www.jianshu.com/']

def parse(self, response):

# 提取所有文章链接地址

for href in response.xpath('//a[@class="title"]/@href'):

url = response.urljoin(href.extract())

yield scrapy.Request(url, callback=self.parse_item)

def parse_item(self, response):

# 解析详情页,提取文章标题和内容

title = response.xpath('//h1/text()').extract_first()

content = ''.join(response.xpath('//article[@class="article"]/p/text()')

.extract()).strip()

yield {'title': title, 'content': content}

该Spider组件的作用是从www.jianshu.com中抓取所有文章的标题和内容。其中,parse()方法用于从网站中提取所有文章的链接地址,使用scrapy.Request()方法重新请求这些链接地址,然后返回到parse_item()方法中解析数据。

parse_item()方法中,使用XPath选择器找到了文章标题和内容。这些数据将被存储到一个字典中,并且使用yield关键字返回。

4.3 编写Item组件

上面提到了,需要抓取的数据包括文章的标题和内容。可以使用Item组件来设置数据模型:

import scrapy

class JianshuItem(scrapy.Item):

title = scrapy.Field()

content = scrapy.Field()

这里只定义了两个字段,分别代表文章的标题和内容。这些数据会被保存到Item对象中。

4.4 编写Pipeline组件

要将抓取到的数据保存到本地,可以使用Pipeline组件,将数据以JSON格式保存到文件中。代码如下:

import json

class JianshuPipeline(object):

def __init__(self):

self.file = open('result.json', 'w')

def process_item(self, item, spider):

line = json.dumps(dict(item)) + "\n"

self.file.write(line)

return item

def spider_closed(self, spider):

self.file.close()

__init__()方法中打开了一个文件,并且在process_item()方法中将抓取到的数据以JSON格式保存到文件中。在spider_closed()方法中关闭了文件。

4.5 运行Scrapy命令

在完成Spider组件、Item组件和Pipeline组件的编写后,可以使用以下命令运行:

scrapy crawl myjianshu

这样,Scrapy框架将从www.jianshu.com中抓取所有文章的标题和内容,并保存到result.json文件中。

5. 总结

本文介绍了Scrapy框架的基本原理和使用方法。通过实例,演示了如何编写Spider组件、Item组件和Pipeline组件,并使用Scrapy命令来运行。Scrapy框架具有高效、高速、易用的特点,在Web抓取的应用中具有广泛的应用。

后端开发标签