Настройка автоматической проверки битых ссылок на сайте

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.
Разработка и обслуживание любых видов сайтов:
Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Настройка автоматической проверки битых ссылок на сайте
Простая
от 1 рабочего дня до 3 рабочих дней
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1214
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    852
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    823
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    815

Автоматическая проверка битых ссылок

Битые ссылки (404, 500, таймауты) вредят SEO и ухудшают пользовательский опыт. Автоматическая проверка запускается по расписанию и отправляет отчёт о проблемах до того, как их заметят пользователи.

Реализация проверщика

# broken_link_checker.py
import asyncio
import aiohttp
from urllib.parse import urlparse, urljoin
from bs4 import BeautifulSoup
from collections import defaultdict

class BrokenLinkChecker:
    def __init__(self, base_url: str, concurrency: int = 20):
        self.base_url  = base_url
        self.domain    = urlparse(base_url).netloc
        self.semaphore = asyncio.Semaphore(concurrency)
        self.visited:  set[str] = set()
        self.broken:   list[dict] = []

    async def check(self) -> list[dict]:
        async with aiohttp.ClientSession(
            timeout=aiohttp.ClientTimeout(total=15),
            headers={'User-Agent': 'LinkChecker/1.0'},
        ) as session:
            await self.crawl(session, self.base_url, referrer='root')
        return self.broken

    async def crawl(self, session: aiohttp.ClientSession, url: str, referrer: str):
        if url in self.visited:
            return
        self.visited.add(url)

        async with self.semaphore:
            try:
                async with session.get(url, allow_redirects=True) as resp:
                    status = resp.status
                    if status >= 400:
                        self.broken.append({'url': url, 'status': status, 'referrer': referrer})
                        return

                    # Парсим только HTML страницы своего домена
                    if urlparse(url).netloc == self.domain and 'text/html' in resp.headers.get('Content-Type', ''):
                        html = await resp.text()
                        links = self.extract_links(url, html)
                        tasks = [self.crawl(session, link, url) for link in links if link not in self.visited]
                        await asyncio.gather(*tasks, return_exceptions=True)

            except asyncio.TimeoutError:
                self.broken.append({'url': url, 'status': 'timeout', 'referrer': referrer})
            except Exception as e:
                self.broken.append({'url': url, 'status': str(e), 'referrer': referrer})

    def extract_links(self, base: str, html: str) -> list[str]:
        soup = BeautifulSoup(html, 'lxml')
        links = []
        for tag in soup.find_all(['a', 'link', 'img', 'script'], href=True):
            href = tag.get('href') or tag.get('src')
            if href:
                absolute = urljoin(base, href)
                parsed = urlparse(absolute)
                if parsed.scheme in ('http', 'https'):
                    links.append(absolute.split('#')[0])
        return list(set(links))

Планировщик и уведомления

# scheduler.py (Celery Beat)
from celery import Celery
from broken_link_checker import BrokenLinkChecker
import asyncio
import requests

app = Celery('tasks', broker='redis://localhost:6379/0')

@app.task
def check_broken_links():
    checker = BrokenLinkChecker('https://example.com', concurrency=15)
    broken  = asyncio.run(checker.check())

    if not broken:
        return {'status': 'ok', 'checked': len(checker.visited)}

    # Отправляем отчёт в Slack
    message = f"🔗 Найдено {len(broken)} битых ссылок:\n"
    for item in broken[:10]:  # Первые 10
        message += f"• `{item['status']}` {item['url']}\n  ← {item['referrer']}\n"
    if len(broken) > 10:
        message += f"...и ещё {len(broken) - 10}. Полный отчёт в CSV.\n"

    requests.post(os.env['SLACK_WEBHOOK'], json={'text': message})

    # Сохраняем в БД для истории
    BrokenLinkReport.objects.create(
        checked_at  = timezone.now(),
        total_links = len(checker.visited),
        broken_count = len(broken),
        details     = broken,
    )

    return {'broken': len(broken)}
# Расписание: каждый день в 6:00
app.conf.beat_schedule = {
    'daily-link-check': {
        'task':     'scheduler.check_broken_links',
        'schedule': crontab(hour=6, minute=0),
    },
}

Сроки

Асинхронный краулер с Celery-расписанием и Slack-уведомлениями: 1–2 рабочих дня.