Запрос Scrapy ‘Ошибка отступа: неожиданный отступ’ при обратном вызове синтаксического анализа

#python #python-3.x #web-scraping #scrapy

#python #python-3.x #очистка веб-страниц #scrapy

Вопрос:

Я использую CLI Scrapy и запускаю его на сервере ubuntu 18, я пытаюсь избежать жесткого кодирования множества URL-адресов в свойстве start_urls, но вместо этого вызываю ‘yield scrapy.Запрос () ‘ в нижней части моего синтаксического анализа. Веб-сайт, который я очищаю, довольно простой и имеет разные страницы за 2014-2030 годы. В нижней части моего кода у меня есть функция if () для проверки текущего года и перемещения скребка на страницу следующего года. Я новичок в scrapy в целом, поэтому я не уверен, вызываю ли я scrapy.Метод Request() корректен. Вот мой код:

 import scrapy

from .. import items

class EventSpider(scrapy.Spider):
    name = "event_spider"
    start_urls = [
        "http://www.seasky.org/astronomy/astronomy-calendar-2014.html",
    ]
    user_agent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1"
    start_year = 2014
    
    #response is the website
    def parse(self, response):
        CONTENT_SELECTOR = 'div#right-column-content ul li'
        
        for astro_event in response.css(CONTENT_SELECTOR):
            NAME_SELECTOR = "p span.title-text ::text"
            DATE_SELECTOR = "p span.date-text ::text"
            DESCRIPTION_SELECTOR = "p ::text"
            
            item = items.AstroEventsItem()
            
            item["title"] = astro_event.css(NAME_SELECTOR).extract_first()
            item["date"] = astro_event.css(DATE_SELECTOR).extract_first()
            item["description"] = astro_event.css(DESCRIPTION_SELECTOR)[-1].extract()
            
            yield item
               
        #Next page code:
        #Goes through years 2014 to 2030
        if(self.start_year < 2030):
            self.start_year = self.start_year   1
            new_url = "http://www.seasky.org/astronomy/astronomy-calendar-"   str(self.start_year)   ".html"
            print(new_url)
            yield scrapy.Request(new_url, callback = self.parse)
  

Вот ошибка, которую я получаю после того, как она успешно очищает первую страницу:

 2020-11-10 05:25:50 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://www.seasky.org/astronomy/astronomy-calendar-2015.html> (referer: http://www.seasky.org/astronomy/astronomy-calendar-2014.html)
2020-11-10 05:25:50 [scrapy.core.scraper] ERROR: Spider error processing <GET http://www.seasky.org/astronomy/astronomy-calendar-2015.html> (referer: http://www.seasky.org/astronomy/astronomy-calendar-2014.html)
Traceback (most recent call last):
  File "/home/jcmq6b/.local/lib/python3.6/site-packages/twisted/internet/defer.py", line 1418, in _inlineCallbacks
    result = g.send(result)
StopIteration: <200 http://www.seasky.org/astronomy/astronomy-calendar-2015.html>

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/scrapy/utils/defer.py", line 55, in mustbe_deferred
    result = f(*args, **kw)
  File "/usr/local/lib/python3.6/dist-packages/scrapy/core/spidermw.py", line 58, in process_spider_input
    return scrape_func(response, request, spider)
  File "/usr/local/lib/python3.6/dist-packages/scrapy/core/scraper.py", line 149, in call_spider
    warn_on_generator_with_return_value(spider, callback)
  File "/usr/local/lib/python3.6/dist-packages/scrapy/utils/misc.py", line 245, in warn_on_generator_with_return_value
    if is_generator_with_return_value(callable):
  File "/usr/local/lib/python3.6/dist-packages/scrapy/utils/misc.py", line 230, in is_generator_with_return_value
    tree = ast.parse(dedent(inspect.getsource(callable)))
  File "/usr/lib/python3.6/ast.py", line 35, in parse
    return compile(source, filename, mode, PyCF_ONLY_AST)
  File "<unknown>", line 1
    def parse(self, response):
    ^
IndentationError: unexpected indent

  

Я думаю, что, возможно, я не передаю правильные параметры для обратного вызова метода синтаксического анализа, но я не уверен. Любая помощь очень ценится! Дайте мне знать, если мне нужно опубликовать дополнительную информацию.

Комментарии:

1. в вашей ошибке говорится unexpected indent , что, возможно, у вас неправильное количество пробелов, прежде def чем в любом случае код, который вы опубликовали здесь, не выдает ошибки отступа. Я пробовал, и он компилируется

2. Странно то, что если я удаляю нижнюю часть своего кода, оператор if (), тогда он работает нормально, без ошибок отступа. Я все равно пройду и дважды проверю свой интервал и посмотрю, выполняется ли он

3. Я думаю, что ошибка отступа — это ошибка в scrapy. Вот связанная с этим проблема на GitHub: github.com/scrapy/scrapy/issues/4477 но конкретно для этой проблемы нет проблемы.

Ответ №1:

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

 import scrapy

from .. import items

class EventSpider(scrapy.Spider):
    name = "event_spider"
    start_urls = ["http://www.seasky.org/astronomy/astronomy-calendar-2014.html"]
    user_agent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1"
    start_year = 2014
    
    #Next page code:
    def parse(self, response):
        #Goes through years 2014 to 2030 from the href links at top of page
        for href in response.css("div#top-links div h3 a::attr(href)"):
            url = response.urljoin(href.extract())
            yield scrapy.Request(url, callback=self.parse_contents)

            
    
    #parses items for database
    def parse_contents(self, response):
        
        CONTENT_SELECTOR = 'div#right-column-content ul li'
        
        for astro_event in response.css(CONTENT_SELECTOR):
            NAME_SELECTOR = "p span.title-text ::text"
            DATE_SELECTOR = "p span.date-text ::text"
            DESCRIPTION_SELECTOR = "p ::text"
            
            item = items.AstroEventsItem()
            
            item["title"] = astro_event.css(NAME_SELECTOR).extract_first()
            item["date"] = astro_event.css(DATE_SELECTOR).extract_first()
            item["description"] = astro_event.css(DESCRIPTION_SELECTOR)[-1].extract()
            
            yield item
  

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