Загрузка изображения Scrapy, как использовать пользовательское имя файла
Для моего проекта scrapy я в настоящее время использую ImagesPipeline. Загруженные изображения хранятся с хешем SHA1 их URL-адресов в качестве имен файлов.
Как сохранить файлы с помощью собственных имен файлов?
Что, если мое собственное имя файла должно содержать другое очищенное поле из того же элемента? например используйте item['desc']
и имя файла для изображения с item['image_url']
. Если я правильно понимаю, это потребует некоторого доступа к другим полям элементов из Image Pipeline.
Любая помощь будет оценена.
Ответы
Ответ 1
Так я решил проблему в Scrapy 0.10.
Проверьте метод persist_image в FSImagesStoreChangeableDirectory. Имя загруженного изображения является ключевым.
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)
Ответ 2
Это просто актуализация ответа для scrapy 0.24 (EDITED), где 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)
Ответ 3
В 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'])
Ответ 4
Я нашел свой путь в 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','')
.
Ответ 5
Я сделал противный быстрый взлом для этого. В моем случае я сохранил заголовок изображения в своих фидах. И у меня было всего 1 image_urls
за элемент, поэтому я написал следующий script. Он в основном переименовывает файлы изображений в каталоге /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))
Это неприятно и не рекомендуется. Но это наивный альтернативный подход.
Ответ 6
Я переписываю код, меняя, в thumb_path def, "response". по запросу. ". Если нет, это не сработает, потому что" ответ установлен на None".
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)