{q.title}
\n{q.description}
\n {q.category}\n{q.description}
\n {q.category}\nОтвет сгенерирован нейросетью и может содержать ошибки
В современных веб-приложениях часто требуется различать запросы от поисковых роботов (Googlebot, Yandexbot) и обычных пользователей. Это необходимо для оптимизации SEO, защиты от скрейпинга и кэширования контента.
Первый шаг - определить, откуда идет запрос, проверив User-Agent заголовок:
// middleware/detectBot.js
const BOT_USER_AGENTS = [
"googlebot",
"bingbot",
"slurp",
"duckduckgo",
"baiduspider",
"yandexbot",
"ahrefs",
"semrush",
"mj12bot"
];
function isBot(userAgent) {
if (!userAgent) return false;
const lowerUA = userAgent.toLowerCase();
return BOT_USER_AGENTS.some(bot => lowerUA.includes(bot));
}
export function detectBotMiddleware(req, res, next) {
req.isBot = isBot(req.get("user-agent"));
req.userAgent = req.get("user-agent");
next();
}
В Express/FastAPI приложении можно отправлять разные данные в зависимости от типа клиента:
// routes/questions.js
import express from "express";
import { detectBotMiddleware } from "../middleware/detectBot.js";
const router = express.Router();
router.use(detectBotMiddleware);
router.get("/questions", async (req, res) => {
try {
const questions = await getQuestionsFromDB();
// Для SEO-роботов отправляем полную версию с метаданными
if (req.isBot) {
return res.json({
type: "bot-response",
questions: questions.map(q => ({
id: q.id,
title: q.title,
description: q.description,
category: q.category,
createdAt: q.createdAt,
tags: q.tags,
difficulty: q.difficulty
})),
meta: {
total: questions.length,
crawlTime: new Date().toISOString()
}
});
}
// Для пользователей - только необходимые данные
return res.json({
type: "user-response",
questions: questions.slice(0, 10).map(q => ({
id: q.id,
title: q.title,
category: q.category
})),
hasMore: questions.length > 10
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
export default router;
При SSR, рендерите полный HTML для роботов:
// pages/questions.js (Next.js)
export default function QuestionsPage({ questions, isBot }) {
return (
<div>
<Head>
{/* Meta теги для SEO */}
<title>Вопросы на собеседование</title>
<meta name="description" content="Лучшие вопросы с собеседований" />
{isBot && (
<>
<meta name="robots" content="index, follow" />
<script type="application/ld+json">
{JSON.stringify({
"@context": "https://schema.org",
"@type": "CollectionPage",
name: "Вопросы на собеседование",
itemListElement: questions.map((q, i) => ({
"@type": "ListItem",
position: i + 1,
name: q.title,
url: `https://prepbro.ru/questions/${q.id}`
}))
})}
</script>
</>
)}
</Head>
{isBot ? (
// Полная версия для роботов
<div className="questions-list-full">
{questions.map(q => (
<article key={q.id}>
<h1>{q.title}</h1>
<p>{q.description}</p>
<span>{q.category}</span>
</article>
))}
</div>
) : (
// Компактная версия для пользователей
<QuestionsList questions={questions.slice(0, 10)} />
)}
</div>
);
}
export async function getServerSideProps({ req, res }) {
const isBot = detectBot(req.headers["user-agent"]);
// Увеличиваем кэш для робота запросов
if (isBot) {
res.setHeader("Cache-Control", "public, s-maxage=3600, stale-while-revalidate=86400");
}
const questions = await getQuestionsFromDB({
limit: isBot ? 100 : 10
});
return {
props: {
questions,
isBot
}
};
}
Роботам часто требуется больше данных, но медленнее. Используйте разные стратегии кэширования:
// middleware/cacheStrategy.js
export function cacheMiddleware(req, res, next) {
const isBot = req.isBot;
if (isBot) {
// Для роботов: долгий кэш (24 часа)
res.setHeader(
"Cache-Control",
"public, s-maxage=86400, stale-while-revalidate=604800"
);
} else {
// Для пользователей: короткий кэш (5 минут)
res.setHeader(
"Cache-Control",
"public, s-maxage=300, stale-while-revalidate=3600"
);
}
next();
}
// routes/robots.js
export function getRobotsText() {
return `User-agent: *
Allow: /
Disallow: /api/
Disallow: /admin/
Disallow: /auth/
User-agent: Googlebot
Allow: /
User-agent: Baiduspider
Allow: /
Crawl-delay: 1
Sitemap: https://prepbro.ru/sitemap.xml
`;
}
// routes/sitemap.js
export async function getSitemap() {
const questions = await getQuestionsFromDB();
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${questions.map(q => `
<url>
<loc>https://prepbro.ru/questions/${q.id}</loc>
<lastmod>${q.updatedAt}</lastmod>
<priority>0.8</priority>
</url>
`).join("")}
</urlset>`;
return xml;
}
// middleware/botLogger.js
export function logBotActivity(req, res, next) {
const isBot = req.isBot;
// Логируем боты отдельно для аналитики
if (isBot) {
console.log({
timestamp: new Date().toISOString(),
type: "BOT_REQUEST",
userAgent: req.userAgent,
path: req.path,
method: req.method,
ip: req.ip
});
} else {
// Для пользователей используем другой уровень логирования
console.log({
timestamp: new Date().toISOString(),
type: "USER_REQUEST",
path: req.path,
method: req.method,
ip: req.ip
});
}
next();
}
Это позволит поисковым системам эффективно индексировать ваш сайт, пока пользователи получат быстрый, оптимизированный ответ.