2025-09-26 10:43:05 +03:00
|
|
|
|
<?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 {
|
2025-10-17 19:45:11 +03:00
|
|
|
|
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $user, $password);
|
2025-09-26 10:43:05 +03:00
|
|
|
|
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
2025-10-17 19:45:11 +03:00
|
|
|
|
$pdo->exec("SET NAMES utf8mb4");
|
2025-09-26 10:43:05 +03:00
|
|
|
|
log_message("Успешное подключение к базе данных '$dbname'.");
|
|
|
|
|
|
} catch (PDOException $e) {
|
|
|
|
|
|
log_message("Ошибка подключения к базе данных: " . $e->getMessage());
|
2025-10-17 19:45:11 +03:00
|
|
|
|
die(json_encode(["status" => "error", "message" => "Ошибка подключения: " . $e->getMessage()], JSON_UNESCAPED_UNICODE));
|
2025-09-26 10:43:05 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Получаем параметры
|
|
|
|
|
|
$status = $_POST['status'] ?? null;
|
|
|
|
|
|
$link = $_POST['link1'] ?? ($_POST['link2'] ?? $_POST['link3'] ?? null);
|
|
|
|
|
|
$case_number = $_POST['case_number'] ?? null;
|
|
|
|
|
|
$uid = $_POST['uid'] ?? null;
|
2025-10-17 19:45:11 +03:00
|
|
|
|
$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'));
|
2025-09-26 10:43:05 +03:00
|
|
|
|
|
|
|
|
|
|
if (!$status || !$link || !$case_number) {
|
|
|
|
|
|
echo json_encode(["status" => "error", "message" => "Ошибка: Не все необходимые параметры переданы."]);
|
|
|
|
|
|
exit;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-17 19:45:11 +03:00
|
|
|
|
log_message("========================================");
|
|
|
|
|
|
log_message("Режим парсера: " . ($use_new_parser ? "НОВЫЙ (универсальный)" : "СТАРЫЙ (legacy)"));
|
|
|
|
|
|
if ($skip_duplicate_check) {
|
|
|
|
|
|
log_message("⚠️ ТЕСТОВЫЙ РЕЖИМ: Проверка дубликатов ОТКЛЮЧЕНА");
|
2025-09-26 10:43:05 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$last_event = null;
|
|
|
|
|
|
|
2025-10-17 19:45:11 +03:00
|
|
|
|
// ========================================
|
|
|
|
|
|
// НОВЫЙ ПАРСЕР (с поддержкой московских судов)
|
|
|
|
|
|
// ========================================
|
|
|
|
|
|
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; // Переключаемся на старый парсер
|
2025-09-26 10:43:05 +03:00
|
|
|
|
}
|
2025-10-17 19:45:11 +03:00
|
|
|
|
}
|
2025-09-26 10:43:05 +03:00
|
|
|
|
|
2025-10-17 19:45:11 +03:00
|
|
|
|
// ========================================
|
|
|
|
|
|
// СТАРЫЙ ПАРСЕР (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,
|
|
|
|
|
|
];
|
2025-09-26 10:43:05 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-17 19:45:11 +03:00
|
|
|
|
// Формируем ответ (ЕДИНЫЙ ФОРМАТ для обоих парсеров)
|
2025-09-26 10:43:05 +03:00
|
|
|
|
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');
|
2025-10-17 19:45:11 +03:00
|
|
|
|
|
|
|
|
|
|
$response = [
|
2025-09-26 10:43:05 +03:00
|
|
|
|
"status" => "success",
|
|
|
|
|
|
"message" => "Парсинг завершен.",
|
|
|
|
|
|
"last_event" => [
|
2025-10-17 19:45:11 +03:00
|
|
|
|
// Кириллические ключи (для обратной совместимости)
|
2025-09-26 10:43:05 +03:00
|
|
|
|
"Наименование" => $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'],
|
2025-10-17 19:45:11 +03:00
|
|
|
|
"Дата размещения" => $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
|
2025-09-26 10:43:05 +03:00
|
|
|
|
]
|
2025-10-17 19:45:11 +03:00
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
// Логируем ответ для отладки
|
|
|
|
|
|
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);
|
2025-09-26 10:43:05 +03:00
|
|
|
|
} else {
|
2025-10-17 19:45:11 +03:00
|
|
|
|
// Всегда возвращаем last_event, даже если он пустой (для совместимости с workflow)
|
|
|
|
|
|
$response = [
|
2025-09-26 10:43:05 +03:00
|
|
|
|
"status" => "success",
|
2025-10-17 19:45:11 +03:00
|
|
|
|
"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);
|
2025-09-26 10:43:05 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
log_message("Парсинг завершен.");
|
|
|
|
|
|
?>
|