Выход Scrapy / Python и продолжение обработки возможно? - PullRequest
0 голосов
/ 17 апреля 2019

Я пробую этот пример кода

from scrapy.spiders import Spider, Request  
import scrapy

class MySpider(Spider):

    name = 'toscrapecom'
    start_urls = ['http://books.toscrape.com/catalogue/page-1.html']

    urls = (
        'http://books.toscrape.com/catalogue/page-{}.html'.format(i + 1) for i in range(50)
    )

    def parse(self, response):
        for url in self.urls:
            return Request(url)

Он прекрасно сканирует все страницы.Однако, если я выдаю элемент до цикла for, он сканирует только первую страницу.(как показано ниже)

from scrapy.spiders import Spider, Request  
import scrapy

class MySpider(Spider):

    name = 'toscrapecom'
    start_urls = ['http://books.toscrape.com/catalogue/page-1.html']

    urls = (
        'http://books.toscrape.com/catalogue/page-{}.html'.format(i + 1) for i in range(50)
    )

    def parse(self, response):
        yield scrapy.item.Item()
        for url in self.urls:
            return Request(url)

Но я могу использовать yield Request(url) вместо return..., и он перемещает страницы назад от последней страницы к первой.

Я хотел бы понять, почемуreturn больше не работает после получения item?Может кто-нибудь объяснить это по-простому?

Ответы [ 2 ]

1 голос
/ 22 апреля 2019

Вы спрашиваете, почему второй код не работает, но я не думаю, что вы полностью понимаете, почему работает первый код:)

for цикл вашего первого кода повторяется только один раз .

То, что происходит:

  1. self.parse() вызывается для URL в self.start_urls.

  2. self.parse() получает первый (и только первый!) URL из self.urls и возвращает его, выходя из self.parse().

  3. Когда приходит ответ на этот первый URL, self.parse() вызывается снова, и на этот раз он возвращает запрос (только 1 запрос!) Для второго URL из self.urls, поскольку предыдущий вызов self.parse() уже использовал первый URL-адрес (self.urls - итератор ).

Последний шаг повторяется в цикле, но это не цикл for, который делает это.

Вы можете изменить исходный код на этот, и он будет работать так же:

def parse(self, response):
    try:
        return next(self.urls)
    except StopIteration:
        pass
0 голосов
/ 17 апреля 2019

Потому что для вызова пунктов / запросов это должна быть генератор функция.Вы даже не можете использовать yield и return в одной и той же функции с тем же «значением», это повысит SyntaxError: 'return' with argument inside generator.

. return (почти) эквивалентно повышению StopIteration.В этой теме Return и yield в той же функции вы можете найти очень подробное объяснение, со спецификацией ссылок.

...