Screaming Frog це основний краулер для більшості SEO-спеціалістів, але ви, напевно, вже натрапляли на його обмеження: ліміт 500 URL у безкоштовній версії, переповнення RAM на великих сайтах, або бажання автоматизувати краули без нагляду за GUI. Scrapy це фреймворк Python з відкритим кодом, який усуває ці обмеження.

Якщо ви можете запустити npm install або git clone, ви можете запустити Scrapy. Крива навчання реальна, але керована, особливо якщо ви вже освоюєтесь з CLI-інструментами через агентні робочі процеси кодування.

Чому Scrapy?

Ключові переваги

Screaming Frog чудово працює для швидких аудитів. Але має обмеження:

Обмеження Вплив
Безкоштовний ліміт 500 URL Потрібна ліцензія $259/рік для більших сайтів
Пожирає пам’ять Великі краули можуть споживати 8GB+ RAM
Залежність від GUI Важко автоматизувати або планувати
Обмежена кастомізація Параметри конфігурації фіксовані

Scrapy вирішує ці проблеми:

Scrapy Що ви отримуєте
Безкоштовний і з відкритим кодом Без лімітів URL, без ліцензійних зборів
Менший обсяг пам’яті Черги на диску тримають RAM під контролем
CLI-нативний Скриптований, cron-сумісний, готовий до CI/CD
Повна Python-кастомізація Екстрактуйте що потрібно, фільтруйте як хочете
Призупинення/Відновлення Зупиняйте та продовжуйте великі краули будь-коли
Scrapy не замінить Screaming Frog для всього. Швидкі аудити все ще швидші в GUI. Але для масштабних краулів, автоматизації та кастомної екстракції варто мати його у своєму інструментарії.

Встановлення

Налаштування

Scrapy працює на Python. Використовуйте віртуальне середовище, щоб тримати все в чистоті:

Debian/Ubuntu:

sudo apt install python3.11-venv
python3 -m venv venv
source venv/bin/activate
pip install scrapy

macOS:

python3 -m venv venv
source venv/bin/activate
pip install scrapy

Windows:

python -m venv venv
venv\Scripts\activate
pip install scrapy
Віртуальні середовища важливі
Завжди використовуйте venv. Глобальна установка спричиняє конфлікти залежностей і порушує відтворюваність.

Створення проекту

Зі встановленим Scrapy:

scrapy startproject myproject
cd myproject
scrapy genspider sitename example.com

Це створює:

myproject/
    scrapy.cfg
    myproject/
        __init__.py
        items.py
        middlewares.py
        pipelines.py
        settings.py
        spiders/
            __init__.py
            sitename.py

Код спайдера йде в spiders/sitename.py. Конфігурація знаходиться в settings.py.

Налаштування для ввічливого краулінгу

Критично

Налаштуйте settings.py перед запуском чого-небудь. Блокування витрачає більше часу, ніж повільний краулінг.

# Ввічливий краулінг
CONCURRENT_REQUESTS_PER_DOMAIN = 5
DOWNLOAD_DELAY = 1
ROBOTSTXT_OBEY = True

# AutoThrottle - регулює швидкість на основі відповіді сервера
AUTOTHROTTLE_ENABLED = True
AUTOTHROTTLE_START_DELAY = 5
AUTOTHROTTLE_MAX_DELAY = 60
AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
AUTOTHROTTLE_DEBUG = True

# Ліміти безпеки
CLOSESPIDER_PAGECOUNT = 10000

# Вивід
FEED_EXPORT_ENCODING = "utf-8"
З увімкненим AutoThrottle, 5 одночасних запитів, це розумна початкова точка. AutoThrottle автоматично відступить, якщо сервер має проблеми. Без AutoThrottle починайте нижче, з 1-3.

AutoThrottle

AutoThrottle моніторить час відповіді сервера та автоматично регулює швидкість краулу:

  • Швидкі відповіді → прискорює
  • Повільні відповіді → уповільнює
  • Помилки/таймаути → значно уповільнює

На відміну від фіксованих затримок Screaming Frog, він адаптується до реальних умов сервера.

Обробка кодів статусу

За замовчуванням HttpErrorMiddleware Scrapy тихо відкидає відповіді не-2xx. Це означає, що 404, 301, 500 відкидаються до того, як досягнуть вашого callback. Ваш краул може показувати 100% кодів статусу 200, не тому, що сайт ідеальний, а тому, що помилки фільтруються.

Додайте це до вашого класу спайдера, щоб захоплювати всі коди статусу:

handle_httpstatus_list = [200, 301, 302, 403, 404, 500, 502, 503]

Screaming Frog за замовчуванням захоплює всі коди статусу. Це налаштування приводить Scrapy у відповідність з цією поведінкою.

Продуктивність у реальному світі

Бенчмарки

Реальні цифри з тестового краулу з 5 одночасними запитами та увімкненим AutoThrottle:

Прогрес краулу Сторінок/Хвилина Примітки
0-200 сторінок 14-22 Розгін
200-500 сторінок 10-12 Стабілізація
500-1000 сторінок 7-10 AutoThrottle регулює
1000+ сторінок 5-7 Стабільний стан
Швидкість vs. Надійність
Ці швидкості виглядають повільними. В цьому суть. AutoThrottle надає пріоритет здоров'ю сервера над сирою швидкістю. Блокування та перезапуск витрачають більше часу, ніж методичний краул.

Порівняння функцій

Функція Screaming Frog Scrapy
Вартість Безкоштовно <500 URL, ~$259/рік Безкоштовно, відкритий код
Макс. розмір краулу Обмежено пам’яттю Черги на диску
Кастомізація Обмежені опції конфігурації Повний Python-код
Планування Вручну або сторонні Нативний CLI, cron-сумісний
Призупинення/Відновлення Так Так (з JOBDIR)
Крива навчання Низька (GUI) Середня (код)
Обмеження швидкості Базові фіксовані затримки AutoThrottle (адаптивний)
Рендеринг JavaScript Опціонально (Chrome) Опціонально (playwright/splash)
Коди статусу Всі за замовчуванням Потребує налаштування
Фільтрація піддоменів GUI чекбокси Код (гнучкий regex)
Формати експорту CSV, Excel тощо JSON, CSV, XML, кастомний
CI/CD інтеграція Складна Нативна

Фільтрація URL

Точний контроль

Screaming Frog використовує чекбокси. Scrapy використовує код. Компроміс: крива навчання за точність.

Виключення міжнародних шляхів:

import re
from urllib.parse import urlparse

class MySiteSpider(scrapy.Spider):
    name = "mysite"
    allowed_domains = ["example.com", "www.example.com"]
    start_urls = ["https://www.example.com/"]

    # Пропускаємо міжнародні шляхи типу /uk/, /fr/, /de/
    EXCLUDED_PATTERNS = re.compile(
        r"/(in|au|th|es|hk|sg|ph|my|ca|cn|uk|kr|id|fr|vn|de|jp|nl|it|tw)/"
    )

    def filter_links(self, links):
        filtered = []
        for link in links:
            hostname = urlparse(link.url).hostname or ""
            if hostname not in ("example.com", "www.example.com"):
                continue
            if self.EXCLUDED_PATTERNS.search(link.url):
                continue
            filtered.append(link)
        return filtered

Ви можете фільтрувати за URL-патернами, параметрами запиту, заголовками відповіді, вмістом сторінки або будь-якою комбінацією.

Призупинення та відновлення

Необхідно

Для краулів понад 1000 сторінок увімкніть призупинення/відновлення з JOBDIR:

scrapy crawl myspider -o output.json -s JOBDIR=crawl_state

Scrapy зберігає стан у crawl_state/. Натисніть Ctrl+C для призупинення. Запустіть ту саму команду для відновлення.

Завжди використовуйте JOBDIR для продакшн краулів. Захищає від мережевих проблем, перезапусків системи або просто необхідності зупинитись на день.

Стан включає URL в очікуванні, переглянуті URL та чергу запитів. Це надійніше, ніж функція збереження/завантаження Screaming Frog, оскільки базується на файлах і витримує перезапуски системи.

Рендеринг JavaScript

Scrapy отримує лише сирий HTML. Він не рендерить JavaScript. Це те саме, що повертає curl.

Для більшості SEO-краулів це нормально:

  • Мета-теги, canonical та h1 зазвичай в початковому HTML
  • Пошукові системи переважно індексують серверний контент
  • Більшість e-commerce та контент-сайтів рендеряться на сервері

Якщо ваш цільовий сайт рендерить контент на стороні клієнта, є варіанти:

Пакет Примітки
scrapy-playwright Використовує Chromium/Firefox/WebKit. Рекомендовано для сучасних JS-сайтів
scrapy-splash Легкий, Docker-based рендерер
scrapy-selenium Старіший підхід, все ще працює

JS-рендеринг значно повільніший та більш ресурсомісткий. Додавайте лише якщо сайт цього потребує.

Screaming Frog має подібний компроміс. Увімкнення рендерингу JavaScript використовує Chrome під капотом і значно уповільнює краули.

Управління пам’яттю

На ~1300 сторінках з повною екстракцією полів:

  • Пам’ять: ~265 МБ
  • CPU: ~4%

Використання JOBDIR переносить черги запитів на диск, тримаючи пам’ять низькою. Для дуже великих краулів (100k+ URL) додайте ці налаштування:

MEMUSAGE_LIMIT_MB = 1024
MEMUSAGE_WARNING_MB = 800
SCHEDULER_DISK_QUEUE = 'scrapy.squeues.PickleFifoDiskQueue'
SCHEDULER_MEMORY_QUEUE = 'scrapy.squeues.FifoMemoryQueue'

Це обмежує використання пам’яті та примушує дискові черги для планувальника.

Вивід даних

Налаштовуваний

Базовий вивід спайдера:

{
    "url": "https://www.example.com/page/",
    "title": "Заголовок сторінки тут",
    "status": 200
}

Для SEO-краулів вам потрібні поля, подібні до того, що експортує Screaming Frog:

def parse_page(self, response):
    yield {
        "url": response.url,
        "status": response.status,
        "title": response.css("title::text").get(),
        "meta_description": response.css("meta[name='description']::attr(content)").get(),
        "meta_robots": response.css("meta[name='robots']::attr(content)").get(),
        "h1": response.css("h1::text").get(),
        "canonical": response.css("link[rel='canonical']::attr(href)").get(),
        "og_title": response.css("meta[property='og:title']::attr(content)").get(),
        "og_description": response.css("meta[property='og:description']::attr(content)").get(),
        "word_count": len(response.text.split()) if response.status == 200 else None,
        "content_type": response.headers.get("Content-Type", b"").decode("utf-8", errors="ignore"),
    }

Додавайте або видаляйте поля залежно від потреб. CSS-селектори працюють для будь-якого елемента на сторінці.

Формати експорту: JSON (-o output.json), JSON Lines (-o output.jsonl), CSV (-o output.csv), XML (-o output.xml).

JSON Lines найкращий для великих краулів. Файли валідні рядок за рядком під час краулу, тому ви можете моніторити за допомогою tail -f. Стандартний JSON не валідний, поки краул не завершиться.

Screaming Frog → Scrapy

Посібник з перекладу

Відображення робочих процесів SF на Scrapy:

Дія Screaming Frog Еквівалент Scrapy
Почати новий краул scrapy crawl spidername
Встановити затримку краулу DOWNLOAD_DELAY у налаштуваннях
Обмежити одночасні потоки CONCURRENT_REQUESTS_PER_DOMAIN
Дотримуватись robots.txt ROBOTSTXT_OBEY = True
Експортувати в CSV -o output.csv
Зберегти/Завантажити краул -s JOBDIR=crawl_state
Фільтрувати піддомени Код у спайдері (regex)
Кастомна екстракція CSS/XPath селектори в parse()

Зміни мислення:

  1. Конфігурація це код. Редагуйте settings.py замість клікання чекбоксів.
  2. Екстракція явна. Ви пишете, які дані захоплювати.
  3. Планування нативне. Додавайте команди до cron або CI/CD.
  4. Дебагінг це логи. Увімкніть AUTOTHROTTLE_DEBUG, щоб бачити, що відбувається.

Повний робочий процес

Зі стандартними налаштуваннями вище ви можете мати Scrapy встановленим і краулити менш ніж за 15 хвилин:

python3 -m venv venv
source venv/bin/activate  # venv\Scripts\activate на Windows
pip install scrapy
scrapy startproject urlcrawler
cd urlcrawler
scrapy genspider mysite example.com
# Відредагуйте settings.py з конфігурацією ввічливого краулу
# Відредагуйте spiders/mysite.py з вашою логікою parse
scrapy crawl mysite -o urls.jsonl -s JOBDIR=crawl_state

Scrapy Shell

Створюючи кастомні конфігурації, використовуйте Scrapy Shell для інтерактивного тестування селекторів та налаштувань:

scrapy shell "https://example.com"

Це відкриває інтерактивну Python-консоль з уже завантаженою відповіддю. Тестуйте CSS та XPath селектори в реальному часі перед додаванням їх до спайдера:

>>> response.css('title::text').get()
'Example Domain'
>>> response.xpath('//h1/text()').get()
'Example Domain'

Scrapy Shell значно скорочує час ітерації. Валідуйте логіку екстракції без запуску повних краулів.

Повний шаблон спайдера

Готовий до продакшн спайдер з фільтрацією URL, обробкою кодів статусу та повною екстракцією SEO-полів:

import re
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from urllib.parse import urlparse


class SEOSpider(CrawlSpider):
    name = "seospider"
    allowed_domains = ["example.com"]
    start_urls = ["https://www.example.com"]

    # Capture all HTTP status codes, not just 2xx
    handle_httpstatus_list = [200, 301, 302, 403, 404, 500, 502, 503]

    # URL patterns to exclude
    EXCLUDED_PATTERNS = re.compile(
        r"/(in|au|th|es|hk|sg|ph|my|ca|cn|uk|kr|id|fr|vn|de|jp|nl|it|tw)/"
    )

    rules = (
        Rule(
            LinkExtractor(allow=()),
            callback="parse_page",
            follow=True,
            process_links="filter_links",
        ),
    )

    def filter_links(self, links):
        filtered = []
        for link in links:
            parsed = urlparse(link.url)
            hostname = parsed.hostname or ""

            if hostname not in ("example.com", "www.example.com"):
                continue

            if self.EXCLUDED_PATTERNS.search(link.url):
                continue

            filtered.append(link)
        return filtered

    def parse_page(self, response):
        yield {
            "url": response.url,
            "status": response.status,
            "title": response.css("title::text").get(),
            "meta_description": response.css("meta[name='description']::attr(content)").get(),
            "meta_robots": response.css("meta[name='robots']::attr(content)").get(),
            "h1": response.css("h1::text").get(),
            "canonical": response.css("link[rel='canonical']::attr(href)").get(),
            "og_title": response.css("meta[property='og:title']::attr(content)").get(),
            "og_description": response.css("meta[property='og:description']::attr(content)").get(),
            "word_count": len(response.text.split()) if response.status == 200 else None,
            "content_type": response.headers.get("Content-Type", b"").decode("utf-8", errors="ignore"),
        }

Замініть example.com на ваш цільовий домен. Налаштуйте EXCLUDED_PATTERNS для структури URL вашого сайту.

Коли що використовувати

Screaming Frog:

Scrapy:

  • Сайти понад 10 000 URL
  • Автоматизовані, заплановані краули
  • Потреби в кастомній екстракції
  • CI/CD інтеграція
  • Обмеження пам’яті
  • Версіоновані конфігурації

Підсумок

Scrapy має крутішу криву налаштування, ніж Screaming Frog, але усуває практичні обмеження, які накладають GUI-краулери. Без лімітів URL, без ліцензійних зборів, нижче використання пам’яті та нативна автоматизація.

Почніть з малого. Прокраульте сайт, який знаєте. Використовуйте консервативні налаштування. Порівняйте вивід зі Screaming Frog. Дані збігатимуться, але у вас буде інструмент, який масштабується.