""" Проверка наличия ссылки на Политику конфиденциальности. Согласно 152-ФЗ, оператор обязан опубликовать документ, определяющий его политику в отношении обработки персональных данных. """ from __future__ import annotations import re from urllib.parse import urljoin from playwright.async_api import Page from scanner.checks.base import BaseCheck from scanner.models import CheckResult, RiskLevel class PrivacyLinkCheck(BaseCheck): """Проверяет наличие и доступность ссылки на Политику конфиденциальности.""" name = "privacy_link" title = "Ссылка на Политику конфиденциальности" description = "Проверяет, есть ли на сайте ссылка на политику конфиденциальности" risk_on_fail = RiskLevel.HIGH default_weight = 15 PRIVACY_PATTERNS = [ r"privacy", r"политик[аые]", r"конфиденциальн[аыо]", r"персональные\s*данные", r"personal\s*data", r"data\s*policy", r"обработка\s*данных", r"user\s*privacy", ] async def check(self, page: Page, url: str) -> CheckResult: try: # Получаем все ссылки на странице links = await page.query_selector_all("a[href]") link_texts = [] for link in links: href = await link.get_attribute("href") or "" text = (await link.inner_text()).strip() if text: link_texts.append({"text": text, "href": href}) # Ищем ссылки на политику found_links = [] for lt in link_texts: combined = (lt["text"] + " " + lt["href"]).lower() if any(re.search(p, combined, re.UNICODE) for p in self.PRIVACY_PATTERNS): full_url = urljoin(url, lt["href"]) found_links.append({"text": lt["text"], "url": full_url}) if not found_links: return self._fail_result( message="Ссылка на Политику конфиденциальности не найдена.", details={"total_links": len(link_texts), "page_text_sample": link_texts[:3]}, ) # Проверяем, что ссылка ведет на рабочую страницу policy_url = found_links[0]["url"] try: await page.goto(policy_url, timeout=5000) policy_text = await page.evaluate("() => document.body.innerText") await page.goto(url, timeout=5000) # Возвращаемся на главную if len(policy_text) < 50: return self._fail_result( message=f"Страница политики ({policy_url}) слишком короткая ({len(policy_text)} символов).", details={"policy_url": policy_url, "char_count": len(policy_text)}, ) return self._pass_result( message=f"Найдена ссылка на Политику конфиденциальности ({policy_url})", details={ "policy_url": policy_url, "link_text": found_links[0]["text"], "char_count": len(policy_text), }, ) except Exception as e: return self._fail_result( message=f"Страница политики не доступна: {str(e)}", details={"policy_url": policy_url}, ) except Exception as e: return self._error_result(message=f"Ошибка при проверке ссылки на политику: {str(e)}")