一、关于scrapy
中pipleline
的基本认识
Item Pipeline
又称之为管道,顾名思义就是对数据的过滤处理,其主要的作用包括如下:
- 清理
HTML
数据。 - 验证爬取数据,检查爬取字段。
- 查重并丢弃重复内容。
- 将爬取结果保存到数据库。
二、几个核心的方法
创建一个项目的时候都会自带
pipeline
其中就实现了process_item(item, spider)
方法
- 1、
open_spider(spider)
就是打开spider
时候调用的 - 2、
close_spider(spider)
关闭spider
时候调用 - 3、
from_crawler(cls, crawler)
一般用来从settings.py
中获取常量的 - 4、
process_item(item, spider)
是必须实现的,别的都是选用的
三、几个常用方法的介绍
- 1、
process_item(item, spider)
参数介绍item
是要处理的item
对象spider
当前要处理的spider
对象
- 2、
process_item(item, spider)
返回值- 返回
item
就会继续给优先级低的item pipeline
二次处理 - 如果直接抛出
DropItem
的异常就直接丢弃该item
- 返回
- 3、
open_spider(spider)
是在开启spider
的时候触发的,常用于初始化操作(常见开启数据库连接,打开文件) - 4、
close_spider(spider)
是在关闭spider
的时候触发的,常用于关闭数据库连接 - 5、
from_crawler(cls, crawler)
是一个类方法(需要使用@classmethod
装饰器标识),常用于从settings.py
获取配置信息
关于上面几个方法的使用情况可以参考传送门
四、使用item pipeline
爬取网上图片下载到本地介绍
Scrapy提供了专门处理下载的Pipeline,包括文件下载和图片下载。下载文件和图片的原理与抓取页面的原理一样,因此下载过程支持异步和多线程,下载十分高效。下面我们来看看具体的实现过程。官方文档
- 基本原理
内置
ImagesPipeline
会默认读取item
中图片的url
字段,并加入队列中,然后取出没一个url
进行图片的下载
五、实现下载图片到本地
-
1、需要抓取的网页图片
https://image.so.com/z?ch=photography
,是返回的json
,所以我们要抓取的是json
数据 -
2、搭建一个项目
# 创建一个项目 scrapy startproject images360 # 创建一只爬虫 scrapy genspider images images.so.com # 在配置文件中设置 ROBOTSTXT_OBEY = False # 设置编码 FEED_EXPORT_ENCODING = 'utf-8' # 关闭cookie COOKIES_ENABLED = False # 配置图片存储位置 IMAGES_STORE = './images'
-
3、管道的书写
from scrapy import Request from scrapy.exceptions import DropItem from scrapy.pipelines.images import ImagesPipeline 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['url'])
-
4、上面方法的介绍
- 4.1、继承了
ImagePipeline
(ImagePipeline
是scrapy
内置) - 4.2、
get_media_requests(item, info)
-
item
参数是爬取生成的item
对象,从中提取url
字段,然后加入到调用队列中,等待下载。 -
info
看源码也没解释,打印出来的是<scrapy.pipelines.media.MediaPipeline.SpiderInfo object at 0x110e501d0>
-
- 4.3、
file_path(request, response=None, info=None)
request
表示当前下载对应的request
对象(request.__dict__
查看属性),该方法用来保存文件名response
返回的是None
info
一样的返回是一个对象(info.__dict__
查看)
- 4.4、
item_completed(results, item, info)
它是当单个Item完成下载时的处理方法,不是每一张图片都能下载成功,所有要处理-
results
表示下载的结果,返回的是一个列表[(True, {'url': 'https://p0.ssl.qhimgs1.com/t01a098025e4214bacc.jpg', 'path': 't01a098025e4214bacc.jpg', 'checksum': '7adb29c836cde7a422c740aac3f86234'})]
-
- 4.5、定义的管道要在
settings.py
中配置
- 4.1、继承了
五、对下载的图片重命名
-
1、现在抓取的图片地址是
-
2、在
spiders
里面使用分页技术 -
3、
item pipeline
中使用meta
把参数携带到request
中 -
4、在
file_path
函数中重命名 -
5、具体的代码
# 定义一个下载pic图片的管道 class PicPipeline(ImagePipeline): def file_path(self, request, response=None, info=None): print('=======', request.__dict__) url = request.url # 防止有中文重名的特意加上时间鹾 return '{0}-{1}.{2}'.format(request.meta['title'], str(time.time()).split('.')[0], url.split('.')[-1]) 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(url=item['url'], meta={'title': item['title']})
六、总结
-
1、使用
urllib
包组装get
请求的url
from urllib.parse import urlencode params = urlencode(data)
-
2、抓取的是
json
数据的处理result = json.loads(response.text) ...接下来跟之前的一样处理