Как сохранить несколько URL-адресов в виде файла на StartURL в Scrapy - Python?

1

У меня есть следующий код:

class VoteSpider(scrapy.Spider):
    name = "test"

    def start_requests(self):

        self.start_url = [
            "http://www.domain.de/URI.html?get=1&getX=2",
            "http://www.domain.de/URI.html?get=2&getX=3",
            "http://www.domain.de/URI.html?get=3&getX=4",
            "http://www.domain.de/URI.html?get=4&getX=5"            
        ]

        for url in self.start_url:
            self.a = 0
            self.url = url
            self.page = self.url.split("/")[-1]
            self.filename = '%s.csv' % self.page
            with open(self.filename, 'w') as f:
                f.write('URL:;'+self.url+'\n')

            yield scrapy.Request(url=self.url,callback=self.parse,dont_filter = True)

    def parse(self, response):
        sel = Selector(response)

        votes = sel.xpath('//div[contains(@class,"ratings")]/ul')

        with open(self.filename, 'a') as f:
            for vote in votes:
                self.a+=1
                f.write(str(self.a)+';'+vote.xpath('./li/text()').extract())

        if len(votes.xpath('//a[contains(@class,"next")]/@href').extract()) != 0:
            next_page = votes.xpath('//a[contains(@class,"next")]/@href').extract()[0]
            if next_page is not None:
                yield response.follow(next_page, callback=self.parse, dont_filter=True)

Моя проблема в том, что с этим кодом все будет сохранено в одном файле, который в приведенном выше примере будет:

URI.html?get=1&getX=2.csv

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

Почему этот код не создает новые файлы для каждого URL-адреса?

for url in self.start_url:
    self.a = 0
    self.url = url
    self.page = self.url.split("/")[-1]
    self.filename = '%s.csv' % self.page
    with open(self.filename, 'w') as f:
        f.write('URL:;'+self.url+'\n')

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

РЕДАКТИРОВАТЬ:

Проблема не в том, что файлы не создаются. Все содержание

with open(self.filename, 'a') as f:
            for vote in votes:
                self.a+=1
                f.write(str(self.a)+';'+vote.xpath('./li/text()').extract())

сохраняется в один файл, а не в 4 файла. Все будет сохранено в первый доступный StartURL

EDIT2:

Идея хорошая! Но из моего примера это не сработает, чтобы заменить:

file_name = '%s.csv' % response.url.split("/")[-1]

потому что URI изменяется, и для каждого нового URI создается новый файл.

startURL 1     - "http://www.domain.de/URI.html?get=1&getX=2"
response.url 2 - "http://www.domain.de/URI.html?get=2&getX=2"
response.url 3 - "http://www.domain.de/URI.html?get=3&getX=2"

Я просто хочу сохранить все в startURL.

startURL 1     saved to "http://www.domain.de/URI.html?get=1&getX=2.csv"
response.url 2 saved to "http://www.domain.de/URI.html?get=1&getX=2.csv"
response.url 3 saved to "http://www.domain.de/URI.html?get=1&getX=2.csv"

ненадежным решением является сопоставление имени по условию, но это нецелесообразно, если количество startURL увеличивается или изменяется структура URL-адреса стартового URL-адреса:

if response.url.find("getX=2"):
    filename = self.start_url[0].split('/')[-1]
if response.url.find("getX=3"):
    filename = self.start_url[1].split('/')[-1]
if response.url.find("getX=4"):
    filename = self.start_url[2].split('/')[-1]
...

Я не понимаю, почему self.filename не передается правильно self.parse()? Есть ли какая-то многопроцессорность, поэтому self.filename всегда перезаписывается первым элементом? Как я могу перенаправить правильное имя файла без использования объекта ответа?

РЕШЕНИЕ:

Я передаю значение через request.meta:

class VoteSpider(scrapy.Spider):
    name = "test2"

    def start_requests(self):

        self.start_url = [
            "http://www.domain.de/URI.html?get=1&getX=2",
            "http://www.domain.de/URI.html?get=2&getX=3",
            "http://www.domain.de/URI.html?get=3&getX=4",
            "http://www.domain.de/URI.html?get=4&getX=5"          
        ]

        for url in self.start_url:
            self.a = 0
            self.url = url
            self.page = self.url.split("/")[-1]
            self.filename = '%s.csv' % self.page
            with open(self.filename, 'w') as f:
                f.write('URL:;'+self.url+'\n')
            request = scrapy.Request(url=self.url,callback=self.parse,dont_filter = True)
            request.meta['url'] = url
            yield request

    def parse(self, response):
        sel = Selector(response)

        votes = sel.xpath('//div[contains(@class,"ratings")]/ul')

        self.file = response.meta['url']
        filename = self.file.split("/")[-1]+'.csv'
        with open(filename, 'a') as f:
            for vote in votes:
                self.a+=1
                f.write(str(self.a)+';'+votes.xpath('./li/text()').extract()[0])

        if len(votes.xpath('//a[contains(@class,"next")]/@href').extract()) != 0:
            next_page = votes.xpath('//a[contains(@class,"next")]/@href').extract()[0]
            if next_page is not None:
                request = response.follow(next_page, callback=self.parse, dont_filter=True)
                request.meta['url'] = self.file
                yield request 
Теги:
python-3.x
web-scraping
scrapy
web-crawler

1 ответ

1

вместо:

with open(self.filename, 'a') as f:
    ...

попробуйте использовать это, file_name будет текущим request.url например: URI.html?get=1&getX=2.csv

file_name = '%s.csv' % response.url.split("/")[-1]
with open(file_name, 'a') as f:
    ...
  • 1
    Ваш комментарий дал мне идею :) Спасибо за ваши усилия!
  • 0
    извини, я на работе, я могу помочь тебе сейчас (
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню