Налаштування автоматичної перевірки битих посилань на сайті

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

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

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Налаштування автоматичної перевірки битих посилань на сайті
Проста
від 1 робочого дня до 3 робочих днів
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Автоматична перевірка розірваних посилань

Розірвані посилання (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 робочих дні.