Перезапись Scrapy Image для пользовательского имени изображения из поля элемента - PullRequest
0 голосов
/ 26 мая 2019

Используя scrapy, я пытаюсь загрузить изображение, используя элементы и пользовательский конвейер изображений. Паук должен собрать источник изображения и сохранить его в поле элемента, а затем перейти на следующую страницу, следуя той же ссылке. Он работает, как и ожидалось, и загружает все изображения, которые мне нужны, называя их стандартным поведением конвейера изображения 'checkum.png'. Что касается других подобных вопросов, я попытался сделать свой собственный конвейер изображений, перекрывающий некоторые методы, код копирования-вставки, но лучшее, что я получил, - это перетаскиваемый элемент без изображения внутри.

Это неделя, когда я застрял здесь. pipe.py - беспорядок со всем кодом, который я пробовал до сих пор ... Спасибо за любую помощь.

В старых вопросах stackoverflow есть код, который больше не действителен из-за устаревших версий, или я мог бы правильно реализовать его в своем проекте.

код паука:

import scrapy
from .. import items

class ImmortaleSpider(scrapy.Spider):
    name = 'immortale'
    allowed_domains = ['www.mangaeden.com']
    start_urls = ['https://www.mangaeden.com/en/it-manga/limmortale/0/1/']

def parse(self, response):
    item = items.MangascraperItem()
    urls_list = []
    name_list = []
    for url in response.xpath('//img[@id="mainImg"]/@src').extract():
        urls_list.append("https:" + url)
    item['image_urls'] = urls_list
    name_list.append(response.url.split("/")[-3] + "-" + response.url.split("/")[-2])
    item['image_names'] = name_list
    yield item

    next_page = response.xpath('//a[@class="ui-state-default next"]/@href').extract()
    if next_page:
        next_href = next_page[0]
        next_page_url = response.urljoin(next_href)
        request = scrapy.Request(url=next_page_url)
        yield request

settings.py:

ITEM_PIPELINES = {
# 'scrapy.pipelines.images.ImagesPipeline': 2,
'mangascraper.pipelines.MyImagesPipeline': 1,
}
IMAGES_STORE = 'images/immortale/'

items.py:

import scrapy

class MangascraperItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    image_urls = scrapy.Field()
    images = scrapy.Field()
    image_names = scrapy.Field()

pipeline.py:

import scrapy
from scrapy.pipelines.images import ImagesPipeline
from scrapy.exceptions import DropItem

class MyImagesPipeline(ImagesPipeline):
#     def get_media_requests(self, item, info):
#         for img_url in item['image_urls']:
# #            meta = {'filename': item['image_name']}
#             meta = {'item':item}
#             yield scrapy.Request(url=img_url, meta=meta)

    # def file_path(self, request, response=None, info=None):
    #     return scrapy.Request.meta.get('filename','')
    #
    # def get_media_requests(self, item, info):
    #     return [scrapy.Request(url, meta={'filename':item.get('image_name')}) for url in item.get(self.images_urls_field, [])]

    # def file_path(self, request, response=None, info=None):
    #     print "\n" + scrapy.Request.meta['filename'] + "\n"
    #     return scrapy.Request.meta['filename']
    #
    # def get_media_requests(self, item, info):
    #     img_url = item['image_urls'][0]
    #     meta = {'filename': item['image_names']}
    #     yield scrapy.Request(url=img_url, meta=meta)
    #
    # 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['images'] = image_paths
    #     return item

    def get_media_requests(self, item, info):
        for image_url in item['image_urls']:
           yield scrapy.Request(url=image_url, meta={'item': item})
    #
    # def file_path(self, request, response=None, info=None):
    #     item = scrapy.Request.meta['item']
    #     image_guid = item['image_names']
    #     print image_guid
    #     return 'full/%s.jpg' % (image_guid)
    #
    def file_path(self, request, response=None, info=None):
        image_guid = scrapy.response.url.split("/")[-3] + "-" + response.url.split("/")[-2]
        return 'full/%s.jpg' % (image_guid)

    # def get_media_requests(self, item, info):
    #     yield scrapy.Request(item['image_urls'])

    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")
        return item

Я ожидал, что мои изображения будут загружены и сохранены с именем файла, хранящимся в поле элемента "image_names", которое заполняется таким образом, чтобы получить формат страницы-главы (1-25,1-26,1-27, 2- 1,2-2 и т. Д.) Для поддержания порядка страниц.

Будет полезно для меня, если у вас есть какая-либо ссылка на рабочий процесс или пошаговое объяснение различных этапов элементов внутри конвейера.

ОБНОВЛЕНИЕ 1: найдено решение с использованием os.rename

pipeline.py:

import scrapy
from scrapy.pipelines.images import ImagesPipeline
from scrapy.utils.project import get_project_settings
import os

class MyImagesPipeline(ImagesPipeline):

    IMAGES_STORE = get_project_settings().get("IMAGES_STORE")

    def item_completed(self, result, item, info):
        image_path = [x["path"] for ok, x in result if ok]
        os.rename(self.IMAGES_STORE + "/" + image_path[0], self.IMAGES_STORE + "/full/" + item["image_names"][0] + ".jpg")
        return item
# TODO: try to override file_path instead of os.rename
...