2011-05-31 45 views
13

对于我的scrapy项目,我目前使用ImagesPipeline。下载的图像是其网址的stored with a SHA1 hash作为文件名。Scrapy图像下载如何使用自定义文件名

如何使用自己的自定义文件名来存储文件?

如果我的自定义文件名需要包含来自同一项目的另一个刮取字段,该怎么办?例如使用item['desc']item['image_url']的图像的文件名。如果我理解正确,那将涉及以某种方式访问​​图像管道中的其他项目字段。

任何帮助将不胜感激。

回答

8

这就是我在Scrapy 0.10中解决问题的方法。 检查FSImagesStoreChangeableDirectory的persist_image方法。下载的图片的文件名是关键

class FSImagesStoreChangeableDirectory(FSImagesStore): 

    def persist_image(self, key, image, buf, info,append_path): 

     absolute_path = self._get_filesystem_path(append_path+'/'+key) 
     self._mkdir(os.path.dirname(absolute_path), info) 
     image.save(absolute_path) 

class ProjectPipeline(ImagesPipeline): 

    def __init__(self): 
     super(ImagesPipeline, self).__init__() 
     store_uri = settings.IMAGES_STORE 
     if not store_uri: 
      raise NotConfigured 
     self.store = FSImagesStoreChangeableDirectory(store_uri) 
+0

感谢您的支持。您是否有使用图像过期(http://doc.scrapy.org/topics/images.html#image-expiration)功能的经验,如果是这样的代码会影响它吗? – fortuneRice 2011-06-01 20:16:47

+0

我没有经验。我检查了scrapy源代码。到期应继续工作。如果您发现过期失效,请告诉我 – llazzaro 2011-06-02 01:38:07

12

在scrapy 0.12我解决了这样的事情

class MyImagesPipeline(ImagesPipeline): 

    #Name download version 
    def image_key(self, url): 
     image_guid = url.split('/')[-1] 
     return 'full/%s.jpg' % (image_guid) 

    #Name thumbnail version 
    def thumb_key(self, url, thumb_id): 
     image_guid = thumb_id + url.split('/')[-1] 
     return 'thumbs/%s/%s.jpg' % (thumb_id, image_guid) 

    def get_media_requests(self, item, info): 
     yield Request(item['images']) 
+3

小记: 'ImagesPipeline.image_key(url)'和'file_key(url)'方法已弃用,请使用'file_path(request,response = None,info =无)“。 'scrapy/contrib/pipeline/images.py' – sumid 2014-03-07 19:45:12

1

我做了一个讨厌的快速破解。就我而言,我将图像的标题存储在我的提要中。而且,每件商品只有1 image_urls,所以我写了下面的脚本。它基本上将/images/full/目录中的图像文件重命名为我以json存储的项目源中的相应标题。

import os 
import json 

img_dir = os.path.join(os.getcwd(), 'images\\full') 
item_dir = os.path.join(os.getcwd(), 'data.json') 

with open(item_dir, 'r') as item_json: 
    items = json.load(item_json) 

for item in items: 
    if len(item['images']) > 0: 
     cur_file = item['images'][0]['path'].split('/')[-1] 
     cur_format = cur_file.split('.')[-1] 
     new_title = item['title']+'.%s'%cur_format 
     file_path = os.path.join(img_dir, cur_file) 
     os.rename(file_path, os.path.join(img_dir, new_title)) 

这是讨厌的&不推荐。但是,这是一种天真替代的方法。

15

这就是答案scrapy 0.24(编者),其中image_key()已经过时

class MyImagesPipeline(ImagesPipeline): 

    #Name download version 
    def file_path(self, request, response=None, info=None): 
     #item=request.meta['item'] # Like this you can use all from item, not just url. 
     image_guid = request.url.split('/')[-1] 
     return 'full/%s' % (image_guid) 

    #Name thumbnail version 
    def thumb_path(self, request, thumb_id, response=None, info=None): 
     image_guid = thumb_id + response.url.split('/')[-1] 
     return 'thumbs/%s/%s.jpg' % (thumb_id, image_guid) 

    def get_media_requests(self, item, info): 
     #yield Request(item['images']) # Adding meta. Dunno how to put it in one line :-) 
     for image in item['images']: 
      yield Request(image) 
+2

'返回(请求(图片)图片的项目['images'])'为您的一行。 – tiao 2015-01-07 16:25:16

0

我重写代码,改变,在thumb_path闪避,只是实现 “响应”。按要求。”。如果不是,它将不起作用,因为“响应设置为无”。

class MyImagesPipeline(ImagesPipeline): 

    #Name download version 
    def file_path(self, request, response=None, info=None): 
     #item=request.meta['item'] # Like this you can use all from item, not just url. 
     image_guid = request.url.split('/')[-1] 
     return 'full/%s' % (image_guid) 

    #Name thumbnail version 
    def thumb_path(self, request, thumb_id, response=None, info=None): 
     image_guid = thumb_id + request.url.split('/')[-1] 
     return 'thumbs/%s/%s.jpg' % (thumb_id, image_guid) 

    def get_media_requests(self, item, info): 
     #yield Request(item['images']) # Adding meta. Dunno how to put it in one line :-) 
     for image in item['images']: 
      yield Request(image) 
5

我发现我的方式在2017年,scrapy 1.1.3

def file_path(self, request, response=None, info=None): 
    return request.meta.get('filename','') 

def get_media_requests(self, item, info): 
    img_url = item['img_url'] 
    meta = {'filename': item['name']} 
    yield Request(url=img_url, meta=meta) 

像上面的代码,你可以在get_media_requests()你想要的名字添加到请求元,并把它放回file_path()通过request.meta.get('yourname','')