在scrapy中,为了爬取图片,可以将要爬取的图片的url放在image_urls字段中,在item从spider返回时,ImagePipeline会自动高优先级抓取这些url,于此同时,item会被锁定直到图片抓取完毕才被解锁。图片下载成功结束后,图片下载路径、url等信息会被填充到images字段中。
要想图片被成功抓取,需要做以下操作:
(1) 在items.py中添加image_urls和images字段,代码如下:
image_urls = Field()
images = Field()
(2) Enable ImagePipeline,在segttings.py中添加以下代码:
ITEM_PIPELINES = [’scrapy.contrib.pipeline.images.ImagesPipeline’]
IMAGES_STORE = ’/path/to/valid/dir’ #设置图片下载路径
(3) 图片存储
图片会根据原始url计算SHA1 hash值后进行存储;
如url:http://www.example.com/image.jpg
SHA1 哈希值为:3afec3b4765f8f0a07b78f98c07b83f013567a0a
被存储为:
(4) 避免重复抓取
近期抓取过的图片不会再重抓,可以在settings.py中设置多少天内抓过的不被重抓。
IMAGES_EXPIRES = 90 #90天内抓取的都不会被重抓
(5) 图片压缩
IMAGES_THUMBS = {
’small’: (50, 50),
’big’: (270, 270),
}
压缩后存放在:
(6) 图片过滤
可以设置过滤下图片,设置方法如下:
IMAGES_MIN_HEIGHT = 110
IMAGES_MIN_WIDTH = 110
(7) 自定义ImagePipeline
可重载的函数:
get_media_requests(item, info):
ImagePipeline根据image_urls中指定的url进行爬取,可以通过get_media_requests为每个url生成一个Request。如:
def get_media_requests(self, item, info):
for image_url in item[’image_urls’]:
yield Request(image_url)
图片下载完毕后,处理结果会以二元组的方式返回给item_completed()函数。这个二元组定义如下:
(success, image_info_or_failure)
其中,第一个元素表示图片是否下载成功;第二个元素是一个字典,含义如下:
-url:图片url
-path:图片存储地址,跟IMAGE_STORE相关
-checksum:图片内容hash
get_media_requests函数返回示例如下:
[(True,
{’checksum’: ’2b00042f7481c7b056c4b410d28f33cf’,
’path’: ’full/7d97e98f8af710c7e7fe703abc8f639e0ee507c4.jpg’,
’url’: ’http://www.example.com/images/product1.jpg’}),
(True,
{’checksum’: ’b9628c4ab9b595f72f280b90c4fd093d’,
’path’: ’full/1ca5879492b8fd606df1964ea3c1e2f4520f076f.jpg’,
’url’: ’http://www.example.com/images/product2.jpg’}),
(False,
Failure(...))]
item_completed(results, items, info):
所有图片处理完毕后(不管下载成功或失败),会调用item_completed进行处理;示例程序如下:(默认情况下,item_completed会返回全部items)
from scrapy.exceptions import DropItem
def item_completed(self, results, item, info):
image_paths = [x[’path’] for ok, x in results if ok]
if not image_paths:
raise DropItem("Item contains no images")
item[’image_paths’] = image_paths
return item
(8) 自定义ImagePipeline示例:
from scrapy.contrib.pipeline.images import ImagesPipeline
from scrapy.exceptions import DropItem
from scrapy.http import Request
class MyImagesPipeline(ImagesPipeline):
def get_media_requests(self, item, info):
for image_url in item[’image_urls’]:
yield Request(image_url)
def item_completed(self, results, item, info):
image_paths = [x[’path’] for ok, x in results if ok]
if not image_paths:
raise DropItem("Item contains no images")
item[’image_paths’] = image_paths
return item
通过在setting.py
文件中通过给IMAGES_STORE
赋值,就可以指定图片的保存路径。
并且默认情况下,文件名是通过对url使用SHA1 hash得来的。
现在我想以原来的图片名进行保存.
查看下ImagePipeline的源码,发现可以重写file_path函数以修改图片名称,例如:
def file_path(self, request, response=None, info=None): image_guid = request.url.split('/')[-1] file_name= image_guid.split('.')[0]+'.jpg' return 'full/%s' % (file_name)
这样保存的图片就是原图片名,但是thumbs里面的还是哈希名,这个可能要修改
def thumb_path(self, request, thumb_id, response=None, info=None):
函数才行