Список с несколькими абсолютными URL-адресами "urljoin'ed" - PullRequest
0 голосов
/ 31 октября 2019

Я хочу загрузить все файлы из первого поста, из нескольких тем форума определенной страницы форума . У меня есть собственный файловый конвейер, настроенный на прием элементов file_url, file_name и source (название темы), чтобы сохранить их в папке ./source/file_name.

Однако файлссылки являются относительными, и мне нужно использовать абсолютный путь. Я попытался response.urljoin, и это дает мне string абсолютного URL, но только из последнего файла сообщения.

Запуск паука дает мне ошибку ValueError: Missing scheme in request url: h Это происходит потому, что абсолютный URL - это string, а не list

Вот мой код:

import scrapy
from ..items import FilespipelineItem


class MTGSpider (scrapy.Spider):
    name = 'mtgd'
    base_url = 'https://www.slightlymagic.net/forum'
    subforum_url = '/viewforum.php?f=48'
    start_urls = [base_url + subforum_url]

    def parse(self, response):
        for topic_url in response.css('.row dl dt a.topictitle::attr(href)').extract():
            yield response.follow(topic_url, callback=self.parse_topic)

    def parse_topic(self, response):
        item = FilespipelineItem()

        item['source'] = response.xpath('//h2/a/text()').get()
        item['file_name'] = response.css('.postbody')[0].css('.file .postlink::text').extract()

        # Problematic code
        for file_url in response.css('.postbody')[0].css('.file .postlink::attr(href)').extract():
            item['file_url'] = response.urljoin(file_url)

        yield item

Если это поможет, вот код конвейера:

import re
from scrapy.pipelines.files import FilesPipeline
from scrapy import Request


class MyFilesPipeline(FilesPipeline):

    def get_media_requests(self, item, info):
        for file_url in item['file_url']:
            yield Request(file_url,
                          meta={
                              'name': item['file_name'],
                              'source': item['source']
                          })

    # Rename files to their original name and not the hash
    def file_path(self, request, response=None, info=None):
        file = request.meta['name']
        source = request.meta['source']
        # Get names from previous function meta

        source = re.sub(r'[?\\*|"<>:/]', '', source)
        # Clean source name for windows compatible folder name

        filename = u'{0}/{1}'.format(source, file)
        # Folder storage key: {0} corresponds to topic name; {1} corresponds to filename

        return filename

Так что мой вопрос:

В теме с более чем 1 файлом, который нужно загрузить, как я могу сохранить несколько абсолютныхURL в элементе file_url? Цикл for не работает должным образом, так как он сохраняет только URL последнего файла.

Нужна ли петля for для этой проблемы? Если так, что это должно быть?

1 Ответ

0 голосов
/ 31 октября 2019

In:

    for file_url in response.css('.postbody')[0].css('.file .postlink::attr(href)').extract():
        item['file_url'] = response.urljoin(file_url)

Вы перезаписываете item['file_url'] каждый раз новым URL, и в результате значение последнего остается значением, которое остается.

ИспользованиеПонимание списка Python вместо цикла for:

    file_urls = response.css('.postbody')[0].css('.file .postlink::attr(href)').extract():
    item['file_urls'] = [response.urljoin(file_url) for file_url in file_urls]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...