Files
crm.clientright.ru/parscourt.php
Fedor 3db9d06c86 feat: Интеграция уведомлений для событий судов
- Добавлена поддержка project_id в parscourt.php для создания уведомлений
- Создана система парсеров судов (BaseCourtParser, MoscowCourtParser, RegionalCourtParser)
- Интегрирован Browserless для парсинга московских судов (mos-sud.ru, mos-gorsud.ru)
- Добавлены уведомления VDNotifierPro при обнаружении новых событий судов
- Создан ParseAndCreateEvent.php для интеграции с CRM workflow
- Создан CreateCourtEvent_v2.php для прямого создания событий в календаре CRM
- Поддержка проверки дубликатов событий (можно отключить для тестирования)
- Автоматическое определение типа суда и выбор подходящего парсера

Функции:
- Парсинг региональных судов (*.sudrf.ru) через HTML
- Парсинг московских судов через Browserless API
- Создание событий в CRM календаре с привязкой к проектам
- Уведомления ответственных пользователей о новых событиях
- Сохранение событий в таблицу subject для истории
2025-10-17 19:45:11 +03:00

236 lines
12 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
set_time_limit(0); // Снимаем ограничение по времени работы скрипта
// Устанавливаем заголовок для JSON-ответа
header('Content-Type: application/json');
// Функция для записи логов
function log_message($message) {
$date = date('Y-m-d H:i:s');
file_put_contents('logs/parser.log', "[$date] $message" . PHP_EOL, FILE_APPEND);
}
// Подключение к базе данных
$host = 'localhost'; // хост
$dbname = 'court'; // имя базы данных
$user = 'court_usr'; // пользователь
$password = 'yOrjA9HdgwXO4JGJ'; // пароль
try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $user, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec("SET NAMES utf8mb4");
log_message("Успешное подключение к базе данных '$dbname'.");
} catch (PDOException $e) {
log_message("Ошибка подключения к базе данных: " . $e->getMessage());
die(json_encode(["status" => "error", "message" => "Ошибка подключения: " . $e->getMessage()], JSON_UNESCAPED_UNICODE));
}
// Получаем параметры
$status = $_POST['status'] ?? null;
$link = $_POST['link1'] ?? ($_POST['link2'] ?? $_POST['link3'] ?? null);
$case_number = $_POST['case_number'] ?? null;
$uid = $_POST['uid'] ?? null;
$project_id = $_POST['project_id'] ?? null; // ID проекта для уведомлений
$use_new_parser = isset($_POST['use_new_parser']) ? (bool)$_POST['use_new_parser'] : true; // По умолчанию используем новый парсер
$skip_duplicate_check = isset($_POST['skip_duplicate_check']) ? (bool)$_POST['skip_duplicate_check'] : false; // Для тестирования: отключить проверку дубликатов
// Отладка: логируем входящие параметры
log_message("Входящие параметры: status=$status, case_number=$case_number, uid=$uid, project_id=$project_id, skip_duplicate_check=" . ($skip_duplicate_check ? '1' : '0'));
if (!$status || !$link || !$case_number) {
echo json_encode(["status" => "error", "message" => "Ошибка: Не все необходимые параметры переданы."]);
exit;
}
log_message("========================================");
log_message("Режим парсера: " . ($use_new_parser ? "НОВЫЙ (универсальный)" : "СТАРЫЙ (legacy)"));
if ($skip_duplicate_check) {
log_message("⚠️ ТЕСТОВЫЙ РЕЖИМ: Проверка дубликатов ОТКЛЮЧЕНА");
}
$last_event = null;
// ========================================
// НОВЫЙ ПАРСЕР (с поддержкой московских судов)
// ========================================
if ($use_new_parser) {
try {
require_once 'parsers/CourtParserFactory.php';
$parser = CourtParserFactory::getParser($link, $pdo, $case_number, $uid, $skip_duplicate_check, $project_id);
if ($parser === null) {
log_message("ПРЕДУПРЕЖДЕНИЕ: Не найден подходящий парсер для URL: $link. Используем fallback на старый парсер.");
$use_new_parser = false; // Переключаемся на старый парсер
} else {
$parserClass = get_class($parser);
log_message("Выбран парсер: $parserClass");
$last_event = $parser->parse($link, $status);
}
} catch (Exception $e) {
log_message("ОШИБКА в новом парсере: " . $e->getMessage());
log_message("Переключаемся на старый парсер (fallback)...");
$use_new_parser = false; // Переключаемся на старый парсер
}
}
// ========================================
// СТАРЫЙ ПАРСЕР (LEGACY - для обратной совместимости)
// ========================================
if (!$use_new_parser) {
log_message("Старт парсинга $case_number для статуса: $status (СТАРЫЙ ПАРСЕР)");
log_message("Парсим данные из ссылки: $link");
// Загружаем HTML-контент страницы дела
$html = @file_get_contents($link);
if ($html === false) {
log_message("Ошибка: не удалось загрузить страницу по ссылке: $link");
echo json_encode(["status" => "error", "message" => "Ошибка: не удалось загрузить страницу по ссылке: $link"]);
exit;
}
log_message("Страница успешно загружена. Начинаем парсинг...");
// Парсим HTML с помощью DOMDocument и XPath
$dom = new DOMDocument();
// Важно: указываем кодировку UTF-8 для корректного парсинга
@$dom->loadHTML('<?xml encoding="UTF-8">' . $html);
$xpath = new DOMXPath($dom);
// Определяем div для парсинга
$div_id = ($status === 'представительство в суде 1й инстанции' ||
$status === 'выдача листа' ||
$status === 'исполнительное производство' ||
$status === 'заявление на лист') ? 'cont2' : 'cont3';
$rows = $xpath->query("//div[@id='$div_id']//tr");
log_message("Найдено строк (tr) в div с id '$div_id': " . $rows->length);
// Обрабатываем каждую строку таблицы
foreach ($rows as $row) {
$event_name = trim($xpath->query('./td[1]', $row)->item(0)->nodeValue ?? '');
$event_date = trim($xpath->query('./td[2]', $row)->item(0)->nodeValue ?? '');
$event_time = trim($xpath->query('./td[3]', $row)->item(0)->nodeValue ?? '');
$location = trim($xpath->query('./td[4]', $row)->item(0)->nodeValue ?? '');
$event_result = trim($xpath->query('./td[5]', $row)->item(0)->nodeValue ?? '');
$event_basis = trim($xpath->query('./td[6]', $row)->item(0)->nodeValue ?? '');
$note = trim($xpath->query('./td[7]', $row)->item(0)->nodeValue ?? '');
$publication_date = trim($xpath->query('./td[8]', $row)->item(0)->nodeValue ?? '');
// Логируем каждую строку
log_message("Найдено событие: $event_name, Дата: $event_date, Время: $event_time, Место: $location, Результат: $event_result, Основание: $event_basis, Примечание: $note, Дата размещения: $publication_date");
// Пропускаем записи, если название события не указано или дата неверная
if (empty($event_name) || empty($event_date) || $event_date === '1970-01-01') {
log_message("Пропущено событие: название или дата не указаны.");
continue; // Пропустить итерацию
}
// Форматируем даты
$formatted_date = date('Y-m-d', strtotime($event_date));
$current_datetime = date('Y-m-d H:i:s');
$formatted_publication_date = date('Y-m-d', strtotime($publication_date));
// Проверяем на дублирование
$checkQuery = "SELECT COUNT(*) FROM subject WHERE event_name = ? AND event_date = ? AND publication_date = ?";
$checkStmt = $pdo->prepare($checkQuery);
$checkStmt->execute([$event_name, $formatted_date, $formatted_publication_date]);
$exists = $checkStmt->fetchColumn() > 0;
if ($exists) {
log_message("Дубликат найден для события: $event_name, пропускаем запись.");
continue; // Пропустить запись
}
// Запись данных в таблицу subject
$insertQuery = "INSERT INTO subject (case_number, uid, event_name, event_date, event_time, location, event_result, event_basis, note, publication_date, update_datetime) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$insertStmt = $pdo->prepare($insertQuery);
$insertStmt->execute([$case_number, $uid, $event_name, $formatted_date, $event_time, $location, $event_result, $event_basis, $note, $formatted_publication_date, $current_datetime]);
log_message("Данные успешно записаны в таблицу subject для события: $event_name");
$last_event = [
'event_name' => $event_name,
'event_date' => $formatted_date,
'event_time' => $event_time,
'location' => $location,
'event_result' => $event_result,
'event_basis' => $event_basis,
'note' => $note,
'publication_date' => $formatted_publication_date,
];
}
}
// Формируем ответ (ЕДИНЫЙ ФОРМАТ для обоих парсеров)
if ($last_event) {
// Преобразуем форматы дат
$formatted_event_date = DateTime::createFromFormat('Y-m-d', $last_event['event_date'])->format('d.m.Y');
$formatted_publication_date = DateTime::createFromFormat('Y-m-d', $last_event['publication_date'])->format('d.m.Y');
$response = [
"status" => "success",
"message" => "Парсинг завершен.",
"last_event" => [
// Кириллические ключи (для обратной совместимости)
"Наименование" => $last_event['event_name'],
"Дата" => $formatted_event_date,
"Время" => $last_event['event_time'],
"Место" => $last_event['location'],
"Результат" => $last_event['event_result'],
"Основание" => $last_event['event_basis'],
"Примечание" => $last_event['note'],
"Дата размещения" => $formatted_publication_date,
// Дублируем латинскими ключами (для надежности)
"name" => $last_event['event_name'],
"date" => $formatted_event_date,
"time" => $last_event['event_time'],
"location" => $last_event['location'],
"result" => $last_event['event_result'],
"basis" => $last_event['event_basis'],
"note" => $last_event['note'],
"publication_date" => $formatted_publication_date
]
];
// Логируем ответ для отладки
log_message("JSON ответ: " . json_encode($response, JSON_UNESCAPED_UNICODE));
log_message("Событие: " . $last_event['event_name'] . " (" . $formatted_event_date . " " . $last_event['event_time'] . ")");
echo json_encode($response, JSON_UNESCAPED_UNICODE);
} else {
// Всегда возвращаем last_event, даже если он пустой (для совместимости с workflow)
$response = [
"status" => "success",
"message" => "Парсинг завершен, но нет новых событий.",
"last_event" => [
"Наименование" => "",
"Дата" => "",
"Время" => "",
"Место" => "",
"Результат" => "",
"Основание" => "",
"Примечание" => "",
"Дата размещения" => "",
// Латинские ключи тоже пустые
"name" => "",
"date" => "",
"time" => "",
"location" => "",
"result" => "",
"basis" => "",
"note" => "",
"publication_date" => ""
]
];
log_message("JSON ответ (нет новых событий): " . json_encode($response, JSON_UNESCAPED_UNICODE));
echo json_encode($response, JSON_UNESCAPED_UNICODE);
}
log_message("Парсинг завершен.");
?>