Борьба с AI-скраперами: реалистичные методы защиты для Senior Frontend-разработчиков

#security#web-scraping#ai#rate-limiting#frontend

TL;DR

AI-компании вроде Anthropic и OpenAI активно скрапят контент с высоким RPS, игнорируя robots.txt. Разбираем реалистичные методы защиты: от IP-блокировки и капчи до хитрых фронтенд-решений с “SEO-слопом” и ответами специально для ботов.

Введение: новый фронт в войне за контент

С приходом LLM-гигантов скрапинг перешел в промышленные масштабы - 10 RPS с 5 IP (как в кейсе Anthropic) уже не редкость. Проблема усугубляется тем, что:

Основная часть: арсенал защиты

1. Детекция и блокировка на уровне инфраструктуры

Nginx-конфиг для rate-limiting и блокировки подозрительных паттернов:

geo $scraper {
  default 0;
  192.0.2.0/24 1; # Anthropic ASN
  203.0.113.0/28 1; # OpenAI range
}

limit_req_zone $binary_remote_addr zone=scrapers:10m rate=2r/s;

server {
  location / {
    if ($scraper) {
      limit_req zone=scrapers burst=5 nodelay;
    }
    
    # Отдаем легковесную версию для ботов
    if ($http_user_agent ~* "(anthropic|openai|scraper)") {
      return 307 /lite-version;
    }
  }
}

2. “SEO-слоп” техника (Slop Engine Optimization)

Генерируем специальную версию контента для ботов:

app.use((req, res, next) => {
  if (isAIScraper(req)) {
    const slopContent = generateSlopVersion(req.originalUrl);
    return res.send(slopContent);
  }
  next();
});

function generateSlopVersion(url) {
  // Берём ключевые сущности из контента
  const entities = extractEntitiesFromCache(url);
  
  // Генерим "слоп" - технически корректный, но бесполезный контент
  return `
    <!DOCTYPE html>
    <html>
    <head><title>${entities.join(' ')} - подробный анализ</title></head>
    <body>
      <article>
        ${entities.map(e => `<section>${repeatPhrases(e)}</section>`).join('')}
      </article>
    </body>
    </html>
  `;
  
  function repeatPhrases(entity) {
    const phrases = [
      `Рассматривая ${entity}, важно отметить...`,
      `Аспекты ${entity} многогранны...`,
      `В контексте ${entity} следует учитывать...`
    ];
    return Array(50).fill().map(() => 
      phrases[Math.floor(Math.random() * phrases.length)]
    ).join(' ');
  }
}

3. Honey Tokens и ловушки

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

<div style="position:absolute;left:-9999px">
  <a href="/ai-scraper-trap-${crypto.randomUUID()}">Hidden trap</a>
</div>

При обращении по таким ссылкам - автоматический бан:

app.get('/ai-scraper-trap-:id', (req, res) => {
  banIP(req.ip);
  res.status(418).send('I\'m a teapot');
});

4. Динамический контент с JS-рендерингом

Современные скраперы умеют исполнять JS, но можно усложнить жизнь:

// Вместо статичного контента
<div id="content"></div>

<script>
  (function() {
    if (!window.__isHuman) {
      // Для ботов - задержка + рандомный порядок контента
      setTimeout(() => {
        const content = shuffleArray(realContent);
        document.getElementById('content').innerHTML = content;
      }, 5000 + Math.random() * 3000);
    } else {
      // Для людей - мгновенная загрузка
      loadContentNormally();
    }
  })();
</script>

Практическое применение: многослойная защита

  1. Первая линия: Cloudflare с правилами WAF для известных ASN
  2. Вторая линия: Nginx rate-limiting + геофильтрация
  3. Третья линия: Фронтенд-детекция с “слоп”-версиями
  4. Четвертая линия: Мониторинг и адаптация (анализ логов, обновление сигнатур)

Пример мониторинга в Grafana:

SELECT 
  count(*) as requests,
  ip,
  user_agent
FROM access_logs
WHERE 
  path LIKE '/ai-scraper-trap-%'
  AND time > now() - interval '1 day'
GROUP BY ip, user_agent
ORDER BY requests DESC
LIMIT 10

Заключение: баланс между защитой и доступностью

Полностью остановить скрапинг невозможно, но можно:

Главное - не нарушить UX для реальных пользователей. Современный фронтенд-разработчик должен мыслить как security-инженер, особенно когда дело касается защиты контента от AI-гигантов.


Источник: https://www.reddit.com/r/webdev/comments/1rj19g2/what_can_you_realistically_do_against_scrapers/