Scrapy pipeline 管道:清理、验证和存储数据
在了解 Item Pipeline 之前,我们先看一下下图。 您可以看到项目管道位于上图的最左侧。 Item pipeline的主要任务是处理Spider从网页检索到的item。因此,Item Pipeline的主要任务是清理、验证和存储数据。一旦页面被Spider解析,它将被发送到Item管道。 Item Pipeline 检索 Items 中的数据并执行相应的方法,决定是继续进行 item pipeline 中的下一步还是丢弃而不进行处理。
所以对于Item Pipline来说,主要功能包括以下几个:
清理HTML数据。
验证扫描数据并检查扫描字段。
检查并丢弃重复的内容。
将抓取结果保存到数据库中。
核心方法介绍
项目管道主要有4个方法,分别是:
1)open_spider(spider)
2)close_spider(spider))_搜索程序,)4 ) process_item(item,spider)
open_spider (spider) 【参数spider为打开的spider对象】
close_spider (spider) 【参数spider为关闭的spider对象】 在spider关闭时自动调用。这里我们可以做一些后期工作,比如关闭数据库连接等。这个方法是非常必需的,可以根据需求定义实现。 from_crawler(cls,crawler) 【参数1:类参数2:爬虫对象】 该方法在Spider激活时调用,早于open_spider()方法,是类方法。用@classmethod标记,是一个依赖注入的方法。参数为 如果返回一个item对象,则该item将由低优先级item管道的process_item()方法处理,直到调用所有方法。 扩展:ImagesPipline 爬虫程序通常不仅会爬取文本资源,还会爬取图像资源。这就涉及到如何高效下载图片的问题。这里的高效下载是指可以将图片下载到本地电脑,而不会对网站服务器造成任何压力。此时,您不需要自己实现管道中的图像下载逻辑。您可以使用Scrapy提供的图像管道 将所有下载的图像转换为通用格式(JPG)和模式(RGB) 使用说明: 可以在pipline.py中定义一个新的类,如:xxImagePipline,是Scrapy生成的类,默认继承Object。对该类进行修改,继承 处理结果会以元组的形式返回给函数item_completed(),即参数:结果。 result参数的结果为:(success, image_info_or_failure) 其中success表示图片是否已经下载; image_info_or_failure 是一个包含三个属性的字典: 1.url - 图像下载的 url。这是从 get_media_requests() 方法返回的请求 URL。 如果需要erequest_path =None) 请求代表当前下载对应的request对象(request.dict视图属性),该方法用于返回文件名 response返回None info,同样返回一个对象(info.dict视图) 处同时设置必须结合settings.py的配置,比如设置和配置图片保存路径、自定义下载图片管道等。 而Scrapy框架会用到这个 pip安装垫 我们这次浏览的网站是一个有很多治愈系图片的网站,更重要的是,它是免费的。链接是:http://www.designerspics.com 首先使用以下命令创建一个新项目: 然后使用以下命令创建一个新的spider: 这样我们就创建了一个spider。 然后使用PyCharm打开爬虫项目,开始编写爬虫。 如果爬多个页面可以这样写像这样,因为除了第一页之外,每个页面的地址都是这样的 第一页:http://www.designerspics.com/ DesignerspicsItem类的代码如下: 在至此,开始定义Element Pipline,打开piplines .py文件 此时需要在settings.py中进行配置: 启动爬虫: 我们来看看结果吧! spider时触发,常用于初始化,包括:打开数据库连接、打开文件等)。该方法不需要实现,可以根据需求定义。
和 crawler
。通过crawler
对象,我们可以获取Scrapy的所有核心组件,比如全局配置的各个信息,然后创建一个Pipeline实例。参数cls
为Class,最终返回一个Class实例。默认为 2 此方法处理 Item。例如,我们可以进行数据处理或者将数据写入数据库。它必须返回 Item 类型的值或抛出 DropItem 异常。
如果抛出 DropItem 异常,该项目将被丢弃并且不再被处理。 ImagesPipeline
,可以更高效地下载图像。 ImagesPipeline
具有以下功能:
避免重新下载最近下载的图像检测图像宽度/高度并确保它们满足最小约束ImagesPipeline
。然后,两个函数 eGet_Media_requestsItem_completed
实现 Get_media_requests 为每个函数生成请求。和
item_completed(self, results, item, info)
当单个项目中的所有图像请求完成时调用此方法。
2.path - 图片存储路径(类似IMAGES_STORE)
3.checksum - 图片内容的MD5哈希值# 可以避免下载最近已经下载的图片,90天的图片失效期限
IMAGES_EXPIRES = 90
IMAGES_STORE = '设置存放图片的路径'
# 如果需要也可以设置缩略图
# IMAGES_THUMBS = {
# 'small': (50, 50), # (宽, 高)
# 'big': (270, 270),
# }
# 配置自定义下载的图片管道, 默认是被注释的
ITEM_PIPELINES = {
# yourproject.middlewares(文件名).middleware类
'项目名.pipelines.xxImagePipeline': 数值,
}
Python Imaging Library (PIL)
图像库,所以这个库也必须事先安装。 案例
我们想要实现的是将图片的名称和下载地址存储在MongoDB中,并将图片下载到本地。由于我们之前没有使用过 MongoDB 或 Redis 等非关系型数据库进行存储,因此本例中我们将使用 MongoDB 存储。
scrapy startproject designerspics
scrapy genspider designer www.designerspics.com
所以我们的爬虫代码是(当然现在只爬第一页,如果爬多个页面就需要重写start_requests(self)方法):
import scrapy
from designerspics.items import DesignerspicsItem
class DesignerSpider(scrapy.Spider):
name = 'designer'
allowed_domains = ['www.designerspics.com']
start_urls = ['http://www.designerspics.com/']
def parse(self, response):
title = response.xpath('//div[@class="photograph-wrapper"]/div/h5[1]/text()').extract()
image_url = response.xpath('//div[@class="photograph-wrapper"]/div/div/a/img/@src').extract()
for index, t in enumerate(title):
item = DesignerspicsItem()
item['title'] = t[2:]
item['image_url'] = image_url[index]
yield item
第二页:http://www.designerspics。 com/page/2 /
第三页:http://www.designerspics.com/page/3/
...import scrapy
from scrapy import Request
from designerspics.items import DesignerspicsItem
class DesignerSpider(scrapy.Spider):
name = 'designer'
allowed_domains = ['www.designerspics.com']
# start_urls = ['http://www.designerspics.com/']
def start_requests(self):
# 爬取10页内容
for i in range(1, 11):
if i == 1:
url = "http://www.designerspics.com/"
yield Request(url, self.parse)
else:
url = 'http://www.designerspics.com/page/' + str(i)+"/"
yield Request(url, self.parse)
def parse(self, response):
title = response.xpath('//div[@class="photograph-wrapper"]/div/h5[1]/text()').extract()
image_url = response.xpath('//div[@class="photograph-wrapper"]/div/div/a/img/@src').extract()
for index, t in enumerate(title):
item = DesignerspicsItem()
item['title'] = t[2:]
item['image_url'] = image_url[index]
yield item
import scrapy
class DesignerspicsItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
collection = 'designerimages'
title = scrapy.Field()
image_url = scrapy.Field()
import pymongo
from scrapy import Request
from scrapy.exceptions import DropItem
from scrapy.pipelines.images import ImagesPipeline
class DesignerspicsPipeline:
def __init__(self, mongo_uri, mongo_db, mongo_port):
self.mongo_uri = mongo_uri
self.mongo_db = mongo_db
self.mongo_port = mongo_port
@classmethod
def from_crawler(cls, crawler):
return cls(mongo_uri=crawler.settings.get('MONGO_URI'),
mongo_db=crawler.settings.get('MONGO_DB'),
mongo_port=crawler.settings.get('MONGO_PORT')
)
def open_spider(self, spider):
self.client = pymongo.MongoClient(host=self.mongo_uri, port=self.mongo_port)
self.db = self.client[self.mongo_db]
def process_item(self, item, spider):
self.db[item.collection].insert(dict(item))
return item
def close_spider(self, spider):
self.client.close()
class ImagePipeline(ImagesPipeline):
def file_path(self, request, response=None, info=None):
url = request.url
file_name = url.split('/')[-1]
return file_name
def item_completed(self, results, item, info):
image_paths = [x['path'] for ok, x in results if ok]
if not image_paths:
raise DropItem('Image Downloaded Failed')
return item
def get_media_requests(self, item, info):
yield Request(item['image_url'])
MONGO_URI = '127.0.0.1'
MONGO_DB = 'designerimages'
MONGO_PORT = 27017
# 需要设置存储图片的路径
IMAGES_STORE = './images'
scrapy crawl designer
显示Mongo数据库的数据:
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。