Настройка сканирования сайта через Screaming Frog
Screaming Frog SEO Spider — десктопный краулер, де-факто стандарт технического SEO-аудита. Умеет сканировать сотни тысяч URL, проверяет редиректы, дубли, broken links, мета-теги, структуру заголовков, hreflang, canonical, sitemap, robots.txt. Для повторяемых аудитов и интеграции в процессы важно уметь запускать его через CLI и обрабатывать результаты программно.
Установка и лицензия
Screaming Frog распространяется как Java-приложение. Бесплатная версия ограничена 500 URL — для реальных проектов нужна платная лицензия (~$259/год). На Linux/Mac/Windows устанавливается идентично.
# Ubuntu/Debian
wget https://download.screamingfrog.co.uk/products/seo-spider/screamingfrogseospider_21.0_all.deb
sudo dpkg -i screamingfrogseospider_21.0_all.deb
# Проверка
screamingfrogseospider --version
Запуск через CLI
Ключевое для автоматизации — режим --headless, позволяющий запускать краулер без графического интерфейса:
screamingfrogseospider \
--crawl https://example.com \
--headless \
--save-crawl \
--export-tabs "Internal:All,Response Codes:All,Page Titles:All,Meta Description:All,H1:All,Canonical:All,Directives:All,Hreflang:All,Structured Data:All,Links:All,Sitemaps:All" \
--output-folder /var/reports/example-com/$(date +%Y%m%d) \
--timestamped-output
Параметры:
-
--crawl— стартовый URL -
--headless— без GUI -
--save-crawl— сохранить.seospiderфайл для последующего открытия -
--export-tabs— список вкладок для экспорта в CSV -
--output-folder— директория для результатов
Конфигурация через файл настроек
Для стандартизации настроек между запусками — сохранить конфиг и передавать его при запуске:
screamingfrogseospider \
--crawl https://example.com \
--headless \
--config /etc/screaming-frog/standard-audit.seospiderconfig \
--output-folder /var/reports/$(date +%Y%m%d)
Файл конфигурации создаётся в GUI: File → Configuration → Save. Содержит настройки User-Agent, глубины краулинга, включённых проверок, custom extraction, JavaScript rendering.
Для JavaScript-сайтов включается рендеринг через встроенный Chromium:
screamingfrogseospider \
--crawl https://example.com \
--headless \
--config standard-audit.seospiderconfig \
--use-rendered \ # включить JavaScript рендеринг
--output-folder /var/reports/
Рендеринг увеличивает время краулинга в 3–5 раз, поэтому применяется только там, где критично.
Аутентификация для закрытых разделов
Для сканирования разделов, требующих авторизации, используется cookie-аутентификация:
screamingfrogseospider \
--crawl https://example.com/admin/ \
--headless \
--set-cookies "PHPSESSID=abc123; laravel_session=xyz789" \
--output-folder /var/reports/
Или через HTTP Basic Auth:
screamingfrogseospider \
--crawl https://example.com \
--headless \
--auth-details "user:password" \
--output-folder /var/reports/
Обработка CSV-результатов
Screaming Frog экспортирует отдельный CSV для каждой вкладки. Обработка Python:
import pandas as pd
import os
from pathlib import Path
def load_crawl_results(output_dir: str) -> dict[str, pd.DataFrame]:
results = {}
for csv_file in Path(output_dir).glob('*.csv'):
name = csv_file.stem.lower().replace(' ', '_')
try:
df = pd.read_csv(csv_file, encoding='utf-8-sig', low_memory=False)
results[name] = df
except Exception as e:
print(f'Could not load {csv_file}: {e}')
return results
def audit_summary(results: dict) -> dict:
summary = {}
# Internal pages
if 'internal_all' in results:
internal = results['internal_all']
summary['total_urls'] = len(internal)
summary['indexable'] = len(internal[internal.get('Indexability', '') == 'Indexable'])
# Response codes
if 'response_codes_all' in results:
codes = results['response_codes_all']
summary['2xx'] = len(codes[codes['Status Code'].astype(str).str.startswith('2')])
summary['3xx'] = len(codes[codes['Status Code'].astype(str).str.startswith('3')])
summary['4xx'] = len(codes[codes['Status Code'].astype(str).str.startswith('4')])
summary['5xx'] = len(codes[codes['Status Code'].astype(str).str.startswith('5')])
# Titles
if 'page_titles_all' in results:
titles = results['page_titles_all']
summary['missing_title'] = len(titles[titles['Title 1'].isna() | (titles['Title 1'] == '')])
summary['duplicate_title'] = titles['Title 1'].duplicated().sum()
summary['title_too_long'] = len(titles[titles['Title 1 Length'] > 60]) if 'Title 1 Length' in titles else 0
# H1
if 'h1_all' in results:
h1 = results['h1_all']
summary['missing_h1'] = len(h1[h1['H1-1'].isna() | (h1['H1-1'] == '')])
summary['multiple_h1'] = len(h1[h1['H1-1 Count'] > 1]) if 'H1-1 Count' in h1 else 0
return summary
Поиск конкретных проблем
def find_redirect_chains(results: dict, max_hops: int = 2) -> pd.DataFrame:
if 'response_codes_all' not in results:
return pd.DataFrame()
codes = results['response_codes_all']
redirects = codes[codes['Status Code'].astype(str).str.startswith('3')]
# Цепочки редиректов: статус redirect AND URL уже является целью другого редиректа
redirect_targets = set(redirects['Final URL'].dropna().tolist())
chains = redirects[redirects['Address'].isin(redirect_targets)]
return chains[['Address', 'Status Code', 'Redirect URL', 'Final URL']]
def find_orphan_pages(results: dict, sitemap_df: pd.DataFrame) -> list[str]:
"""Страницы в sitemap, не связанные внутренними ссылками"""
if 'internal_all' not in results:
return []
internal = results['internal_all']
crawled_urls = set(internal['Address'].tolist())
sitemap_urls = set(sitemap_df['Address'].tolist()) if not sitemap_df.empty else set()
# Страницы только в sitemap, не обнаруженные краулером через ссылки
return list(sitemap_urls - crawled_urls)
Автоматический еженедельный аудит через cron
#!/bin/bash
# /opt/scripts/weekly-crawl.sh
DOMAIN="example.com"
DATE=$(date +%Y%m%d)
OUTPUT="/var/reports/crawls/${DOMAIN}/${DATE}"
LOG="/var/log/seo-crawl.log"
mkdir -p "$OUTPUT"
echo "[$(date)] Starting crawl for ${DOMAIN}" >> "$LOG"
screamingfrogseospider \
--crawl "https://${DOMAIN}" \
--headless \
--config "/etc/screaming-frog/weekly.seospiderconfig" \
--output-folder "$OUTPUT" \
--export-tabs "Internal:All,Response Codes:All,Page Titles:All,Meta Description:All,H1:All,Canonical:All" \
>> "$LOG" 2>&1
# Запустить анализ результатов
python3 /opt/scripts/analyze_crawl.py --dir "$OUTPUT" --notify
echo "[$(date)] Crawl complete" >> "$LOG"
# Crontab: каждое воскресенье в 03:00
0 3 * * 0 /opt/scripts/weekly-crawl.sh
Потребление ресурсов
Screaming Frog требователен к RAM: для сайта в 50 000 URL с JavaScript-рендерингом — 4–8 GB. Без рендеринга — 1–2 GB. На серверах запускается с явным указанием кучи JVM:
# Увеличить heap до 4 GB
export JAVA_OPTS="-Xmx4g"
screamingfrogseospider --crawl ...
Скорость краулинга: без JS — 5–20 страниц/секунду (зависит от скорости сервера и настроек задержки). С JS-рендерингом — 1–3 страницы/секунду. Сайт в 10 000 URL без JS отсканируется за 10–30 минут.
Сроки
Настройка регулярного автоматического краулинга через CLI с обработкой результатов и алертами по email/Telegram — 2–3 рабочих дня. Настройка кастомных экстракций (XPath/RegEx для специфических данных), интеграции с хранилищем для трендов — 3–5 дней.







