Магазин Scrapy возвращал элементы в переменных для использования в основном скрипте

Я новичок в Scrapy и хочу попробовать следующее: извлечь некоторые значения из веб-страницы, сохранить их в переменной и использовать в моем основном скрипте. Поэтому я следовал их руководству и изменил код для своих целей:

import scrapy
from scrapy.crawler import CrawlerProcess


class QuotesSpider(scrapy.Spider):
    name = "quotes"
    start_urls = [
        'http://quotes.toscrape.com/page/1/'
    ]

    custom_settings = {
        'LOG_ENABLED': 'False',
    }

    def parse(self, response):
        global title # This would work, but there should be a better way
        title = response.css('title::text').extract_first()

process = CrawlerProcess({
    'USER_AGENT': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)'
})

process.crawl(QuotesSpider)
process.start() # the script will block here until the crawling is finished

print(title) # Verify if it works and do some other actions later on...

До сих пор это работало бы, но я уверен, что это не очень хороший стиль или даже имеет некоторые плохие побочные эффекты, если я определю переменную title как глобальную. Если я пропущу эту строку, то получу ошибку "неопределенная переменная", конечно:/ Поэтому я ищу способ вернуть переменную и использовать ее в своем основном скрипте.

Я читал о конвейере предметов, но не смог заставить его работать.

Любая помощь / идеи высоко ценятся:) Заранее спасибо!

2 ответа

Решение

С помощью global как вы знаете, это не очень хороший стиль, особенно если вам нужно расширить спрос.

Я предлагаю сохранить заголовок в файл или список и использовать его в вашем основном процессе, или, если вы хотите обработать заголовок в другом скрипте, просто откройте файл и прочитайте заголовок в вашем скрипте.

(Примечание: пожалуйста, игнорируйте проблему с отступами)

spider.py

import scrapy
from scrapy.crawler import CrawlerProcess

namefile = 'namefile.txt'
current_title_session = []#title stored in current session
file_append = open(namefile,'a',encoding = 'utf-8')

try:
    title_in_file = open(namefile,'r').readlines()
except:
    title_in_file = open(namefile,'w')

class QuotesSpider(scrapy.Spider):
    name = "quotes"
    start_urls = [
        'http://quotes.toscrape.com/page/1/'
    ]

    custom_settings = {
        'LOG_ENABLED': 'False',
    }

    def parse(self, response):
        title = response.css('title::text').extract_first()
        if title +'\n' not in title_in_file  and title not in current_title_session:
             file_append.write(title+'\n')
             current_title_session.append(title)
if __name__=='__main__':
    process = CrawlerProcess({
        'USER_AGENT': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)'
    })

    process.crawl(QuotesSpider)
    process.start() # the script will block here until the crawling is finished

Делая переменную global должен работать на то, что вам нужно, но, как вы упомянули, это не очень хороший стиль.

На самом деле я бы порекомендовал использовать другой сервис для связи между процессами, например Redis, чтобы у вас не возникало конфликтов между вашим пауком и любым другим процессом.

Он очень прост в настройке и использовании, в документации приведен очень простой пример.

Создайте соединение redis внутри паука и снова о главном процессе (подумайте о них как об отдельных процессах). Паук устанавливает переменные, и основной процесс читает (или getс) информация.

Другие вопросы по тегам