Подтвердить что ты не робот

Переименование загруженных изображений в Scrapy 0.24 с содержимым из поля элемента, избегая конфликтов имен файлов?

Я пытаюсь переименовать изображения, загружаемые моим пауком Scrapy 0.24. В настоящий момент загруженные изображения хранятся с хэшем SHA1 их URL-адресов в качестве имен файлов. Я хотел бы вместо этого называть их значением, которое я извлекаю с помощью item['model']. Этот вопрос с 2011 года описывает, что я хочу, но ответы на предыдущие версии Scrapy и не работают с последней версией.

Как только мне удастся выполнить эту работу, мне также нужно убедиться, что я учитываю, что разные изображения загружаются с тем же именем файла. Поэтому мне нужно загрузить каждое изображение в свою уникальную папку, предположительно основанную на исходном URL-адресе.

Вот копия кода, который я использую в моем конвейере. Я получил этот код из более позднего ответа по ссылке выше, но он не работает для меня. Ничего не происходит, и изображения загружаются как обычно. Похоже, что мой дополнительный код не влияет на имена файлов, поскольку они все еще отображаются как хэши SHA1.

pipelines.py

class AllenheathPipeline(object):
    def process_item(self, item, spider):
        return item

import scrapy
from scrapy.contrib.pipeline.images import ImagesPipeline
from scrapy.http import Request
from scrapy.exceptions import DropItem

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)

    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

settings.py

BOT_NAME = 'allenheath'

SPIDER_MODULES = ['allenheath.spiders']
NEWSPIDER_MODULE = 'allenheath.spiders'

ITEM_PIPELINES = {'scrapy.contrib.pipeline.images.ImagesPipeline': 1}

IMAGES_STORE = 'c:/allenheath/images'

products.py (мой паук)

import scrapy
import urlparse

from allenheath.items import ProductItem
from scrapy.selector import Selector
from scrapy.http import HtmlResponse

class productsSpider(scrapy.Spider):
    name = "products"
    allowed_domains = ["http://www.allen-heath.com/"]
    start_urls = [
        "http://www.allen-heath.com/ahproducts/ilive-80/",
        "http://www.allen-heath.com/ahproducts/ilive-112/"
    ]

    def parse(self, response):
        for sel in response.xpath('/html'):
            item = ProductItem()
            item['model'] = sel.css('#prodsingleouter > div > div > h2::text').extract() # The value I'd like to use to name my images.
            item['shortdesc'] = sel.css('#prodsingleouter > div > div > h3::text').extract()
            item['desc'] = sel.css('#tab1 #productcontent').extract()
            item['series'] = sel.css('#pagestrip > div > div > a:nth-child(3)::text').extract()
            item['imageorig'] = sel.css('#prodsingleouter > div > div > h2::text').extract()
            item['image_urls'] = sel.css('#tab1 #productcontent .col-sm-9 img').xpath('./@src').extract()
            item['image_urls'] = [urlparse.urljoin(response.url, url) for url in item['image_urls']]
            yield item

items.py

import scrapy

class ProductItem(scrapy.Item):
    model = scrapy.Field()
    itemcode = scrapy.Field()
    shortdesc = scrapy.Field()
    desc = scrapy.Field()
    series = scrapy.Field()
    imageorig = scrapy.Field()
    image_urls = scrapy.Field()
    images = scrapy.Field()

Здесь pastebin вывода, который я получаю из командной строки при запуске паука: http://pastebin.com/ir7YZFqf

Любая помощь будет принята с благодарностью!

4b9b3361

Ответ 1

Файл pipelines.py:

from scrapy.pipelines.images import ImagesPipeline
from scrapy.http import Request
from scrapy.exceptions import DropItem
from scrapy import log

class MyImagesPipeline(ImagesPipeline):

    #Name download version
    def file_path(self, request, response=None, info=None):
        image_guid = request.meta['model'][0]
        log.msg(image_guid, level=log.DEBUG)
        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]
        log.msg(image_guid, level=log.DEBUG)
        return 'thumbs/%s/%s.jpg' % (thumb_id, image_guid)

    def get_media_requests(self, item, info):
        yield Request(item['image_urls'][0], meta=item)

Вы используете settings.py неправильно. Вы должны использовать это:

ITEM_PIPELINES = {'allenheath.pipelines.MyImagesPipeline': 1}

Для работы с thumbnnails добавьте это в settings.py:

IMAGES_THUMBS = {
    'small': (50, 50),
    'big': (100, 100),
}

Ответ 2

Поскольку хеш URL-адреса будет удостоверяться, что вы получите уникальный идентификатор, вы можете просто написать отдельно в файл значение элемента и хеш-URL.

После того, как все сделано, вы можете просто перебрать этот файл и выполнить переименование (и использовать словарь счетчика, чтобы убедиться, что вы переименовываете их с добавленным числом в зависимости от количества элементов с равным значением).