Когда и как следует использовать несколько пауков в одном проекте Scrapy

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

содержимое каталога проекта:

test/
├── scrapy.cfg
└── test
    ├── __init__.py
    ├── items.py
    ├── mybasespider.py
    ├── pipelines.py
    ├── settings.py
    ├── spider1_settings.py
    ├── spider2_settings.py
    └── spiders
        ├── __init__.py
        ├── spider1.py
        └── spider2.py

Чтобы уменьшить избыточность исходного кода, mybasespider.py имеет базовый паук MyBaseSpider, в нем есть исходный код 95%, все остальные пауки унаследованы от него, если у паука есть некоторые особые вещи, переопределить некоторые class methods, обычно нужно добавить несколько строк исходного кода, чтобы создать новый паук

Поместите все общие настройки в settings.py, специальные настройки для паука находятся в [spider name]_settings.py, например:

специальные настройки spider1 в spider1_settings.py:

from settings import *

LOG_FILE = 'spider1.log'
LOG_LEVEL = 'INFO'
JOBDIR = 'spider1-job'
START_URLS = [
    'http://test1.com/',
]

специальные настройки spider2 в spider2_settings.py:

from settings import *

LOG_FILE = 'spider2.log'
LOG_LEVEL = 'DEBUG'
JOBDIR = 'spider2-job'
START_URLS = [
    'http://test2.com/',
]

Scrapy использует LOG_FILE, LOG_LEVEL, JOBDIR перед запуском паука;

Все URL-адреса в START_URLS заполняются в MyBaseSpider.start_urls, у другого паука разное содержимое, но имя START_URLS, используемое в базовом пауке MyBaseSpider, не изменяется.

содержимое scrapy.cfg:

[settings]
default = test.settings
spider1 = spider1.settings
spider2 = spider2.settings

[deploy]
url = http://localhost:6800/
project = test

Чтобы запустить паук, например spider1:

  • export SCRAPY_PROJECT=spider1

  • scrapy crawl spider1

Но этот способ нельзя использовать для запуска пауков в scrapyd. Команда scrapyd-deploy всегда использует название проекта 'default' в разделе scrapy.cfg 'settings' для создания egg file и развертывает его в scrapyd

У вас есть несколько вопросов:

  • Является ли это способом использования нескольких пауков в одном проекте, если я не создаю проект на одного паука? Есть ли лучшие способы?

  • Как отделить специальные настройки паука, как указано выше, которые могут выполняться в scrapyd и уменьшить избыточность исходного кода

  • Если все пауки используют один и тот же JOBDIR, безопасно ли запускать всех пауков одновременно? Не повреждено ли постоянное состояние паука?

Любые идеи были бы оценены.

Ответы

Ответ 1

Поскольку все пауки должны иметь свой собственный класс, вы можете установить параметры для каждого паука с аргументом custom_settings class, поэтому что-то вроде:

Class MySpider1(Spider):
    name = "spider1"
    custom_settings = {'USER_AGENT': 'user_agent_for_spider1/version1'}

Class MySpider1(Spider):
    name = "spider1"
    custom_settings = {'USER_AGENT': 'user_agent_for_spider2/version2'}

этот custom_settings будет перезаписывать файлы в файле settings.py, чтобы вы могли установить некоторые глобальные.

Ответ 2

Я не знаю, ответит ли он на ваш первый вопрос, но я использую scrapy с несколькими пауками, а в прошлом я использую команду

scrapy crawl spider1 

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

scrapy runspider <your full spider1 path with the spiderclass.py> 

пример: "scrapy runpider home/Documents/scrapyproject/scrapyproject/spiders/spider1.py"

Надеюсь, это поможет:)

Ответ 3

Хорошая работа! Я не нашел лучшего способа управления несколькими пауками в документации.

Я не знаю о Скрайде. Но при запуске из командной строки вы должны установить переменную окружения для целевого проекта.

см. scrapy/utils/project.py

ENVVAR = 'SCRAPY_SETTINGS_MODULE'

...

def get_project_settings():
    if ENVVAR not in os.environ:
        project = os.environ.get('SCRAPY_PROJECT', 'default')
        init_env(project)