2011-05-31 3 views
13

Pour mon projet scrapy J'utilise actuellement le ImagesPipeline. Les images téléchargées sont stored with a SHA1 hash de leurs URL en tant que noms de fichiers.Scrapy image comment utiliser le nom de fichier personnalisé

Comment puis-je stocker les fichiers en utilisant mes propres noms de fichiers personnalisés?

Que faire si mon nom de fichier personnalisé doit contenir un autre champ supprimé du même élément? par exemple. utilisez le item['desc'] et le nom de fichier de l'image avec item['image_url']. Si je comprends bien, cela impliquerait d'une manière ou d'une autre d'accéder aux champs d'autres éléments à partir du pipeline d'images.

Toute aide sera appréciée.

Répondre

8

C'est ainsi que j'ai résolu le problème dans Scrapy 0.10. Vérifiez la méthode persist_image de FSImagesStoreChangeableDirectory. Le nom de fichier de l'image téléchargée est la clé

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

Merci pour votre inscription. Avez-vous de l'expérience dans l'utilisation de la fonction Expiration de l'image (http://doc.scrapy.org/topics/images.html#image-expiration), et si tel est le cas, ce code l'affecte-t-il? – fortuneRice

+0

Je n'ai pas d'expérience. Je vérifie le code source scrapy. l'expiration devrait continuer à fonctionner. Si vous voyez que l'expiration ne fonctionne pas, veuillez me le signaler – llazzaro

12

En scrapy 0,12 Je résolu quelque chose comme ça

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

Une petite note: 'Les méthodes' ImagesPipeline.image_key (url) 'et' file_key (url) 'sont obsolètes, veuillez utiliser' file_path (request, response = None, info = Aucun) 'à la place. 'scrapy/contrib/pipeline/images.py' – sumid

1

Je l'ai fait un mauvais hack pour cela. Dans mon cas, j'ai stocké le titre de l'image dans mes flux. Et, j'avais seulement 1 image_urls par article, donc, j'ai écrit le script suivant. Il renomme essentiellement les fichiers image dans le répertoire /images/full/ avec le titre correspondant dans le flux d'éléments que j'avais stocké sous 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)) 

C'est méchant & non recommandé. Mais, c'est une approche naïve alternative.

15

Ceci est juste actualisation de la réponse pour scrapy 0,24 (ÉDITÉ), où le image_key() est dépréciée

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

'return (Demande (image) pour l'image dans l'élément ['images'])' pour votre one-liner. – tiao

0

Je réécris le code, en changeant, en thumb_path def, "réponse." sur demande.". Si non, cela ne fonctionnera pas car "la réponse est définie sur Aucune".

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

Je trouve mon chemin en 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) 

comme le code ci-dessus, vous pouvez ajouter le nom que vous souhaitez une demande méta dans get_media_requests(), et le récupérer dans file_path() par request.meta.get('yourname','').

Questions connexes