Работает обработка ссылок на таблицы с численностью
This commit is contained in:
@ -8,21 +8,7 @@ enum Color : string
|
||||
case RED = "\033[91m";
|
||||
case BLUE = "\033[94m";
|
||||
|
||||
public static function create(string $color) : Color
|
||||
{
|
||||
switch ($color) {
|
||||
case 'green':
|
||||
return self::GREEN;
|
||||
case 'red':
|
||||
return self::RED;
|
||||
case 'blue':
|
||||
return self::BLUE;
|
||||
default:
|
||||
return self::WHITE;
|
||||
}
|
||||
}
|
||||
|
||||
public function tostring() : string
|
||||
public function tostring(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
@ -9,6 +9,8 @@ use PDO;
|
||||
final class Database
|
||||
{
|
||||
private PDO $pdo;
|
||||
public const FILE_ADD_RECORDING ='not-recorded-in-db.yaml';
|
||||
private const ERR_NO_CONNECT = "HY000";
|
||||
private static $logfile = 'log/database.log';
|
||||
private DatabaseConfig $databaseConfig;
|
||||
private DatabaseLogger $logger;
|
||||
@ -48,13 +50,11 @@ final class Database
|
||||
}
|
||||
/**
|
||||
* Выборка данных из базы
|
||||
* @param string $sql
|
||||
* SQL-запрос
|
||||
* @param array $params
|
||||
* Параметры запроса
|
||||
* @param string $sql SQL-запрос
|
||||
* @param array $params Параметры запроса
|
||||
* @return array
|
||||
*/
|
||||
public function select(string $sql, array $params = []) : array
|
||||
public function select(string $sql, array $params = []): array
|
||||
{
|
||||
try {
|
||||
$stmt = $this->pdo->prepare($sql);
|
||||
@ -74,13 +74,11 @@ final class Database
|
||||
}
|
||||
/**
|
||||
* Добавление данных в базу
|
||||
* @param string $sql
|
||||
* SQL-запрос
|
||||
* @param array $params
|
||||
* Параметры запроса
|
||||
* @param string $sql SQL-запрос
|
||||
* @param array $params Параметры запроса
|
||||
* @return void
|
||||
*/
|
||||
public function insert(string $sql, array $params)
|
||||
public function insert(string $sql, array $params): void
|
||||
{
|
||||
try {
|
||||
$stmt = $this->pdo->prepare($sql);
|
||||
@ -100,21 +98,23 @@ final class Database
|
||||
$message = "Ошибка запроса:" . $e->getMessage();
|
||||
$this->logger->log($message);
|
||||
// При ошибке запроса сохраняем валидные данные в yaml-файл
|
||||
if ($e->getCode() === "HY000") {
|
||||
if ($e->getCode() === self::ERR_NO_CONNECT) {
|
||||
$yaml = Yaml::dump($params);
|
||||
file_put_contents('not-recorded-in-db.yaml', $yaml, FILE_APPEND);
|
||||
file_put_contents(
|
||||
self::FILE_ADD_RECORDING,
|
||||
$yaml,
|
||||
FILE_APPEND
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Обновление данных в базе
|
||||
* @param string $sql
|
||||
* SQL-запрос
|
||||
* @param array $params
|
||||
* Параметры запроса
|
||||
* @param string $sql SQL-запрос
|
||||
* @param array $params Параметры запроса
|
||||
* @return void
|
||||
*/
|
||||
public function update(string $sql, array $params)
|
||||
public function update(string $sql, array $params): void
|
||||
{
|
||||
try {
|
||||
$stmt = $this->pdo->prepare($sql);
|
||||
|
@ -24,7 +24,7 @@ final class DatabaseConfig
|
||||
$this->_password = $config['DB_PASSWORD'];
|
||||
}
|
||||
|
||||
private function getDataEnv(string $db) : array
|
||||
private function getDataEnv(string $db): array
|
||||
{
|
||||
$envVars = parse_ini_file('.env', true);
|
||||
$db = strtoupper($db);
|
||||
@ -42,7 +42,7 @@ final class DatabaseConfig
|
||||
return $this->_dbname;
|
||||
}
|
||||
|
||||
public function getDsn() : string
|
||||
public function getDsn(): string
|
||||
{
|
||||
return $this->_driver.":host=".$this->_host
|
||||
.";dbname=".$this->_dbname
|
||||
@ -50,12 +50,12 @@ final class DatabaseConfig
|
||||
.";port=".$this->_port;
|
||||
}
|
||||
|
||||
public function getUsername() : string
|
||||
public function getUsername(): string
|
||||
{
|
||||
return $this->_username;
|
||||
}
|
||||
|
||||
public function getPassword() : string
|
||||
public function getPassword(): string
|
||||
{
|
||||
return $this->_password;
|
||||
}
|
||||
|
@ -3,11 +3,12 @@ namespace ContingentParser\Database;
|
||||
|
||||
use NilPortugues\Sql\QueryBuilder\Builder\GenericBuilder;
|
||||
|
||||
class DatabaseFacade
|
||||
final class DatabaseFacade
|
||||
{
|
||||
private GenericBuilder $builder;
|
||||
private Database $opendata;
|
||||
private Database $niimko;
|
||||
public const FILE_ADD_RECORDING = Database::FILE_ADD_RECORDING;
|
||||
private array $specialties;
|
||||
private array $universities;
|
||||
/**
|
||||
@ -24,7 +25,7 @@ class DatabaseFacade
|
||||
* Извлечение URL сайтов из базы данных niimko
|
||||
* @return array
|
||||
*/
|
||||
public function getSitesFromNiimko() : array
|
||||
public function getSitesFromNiimko(): array
|
||||
{
|
||||
/*
|
||||
SELECT kod AS org_id, site FROM niimko.s_vuzes
|
||||
@ -53,7 +54,7 @@ class DatabaseFacade
|
||||
* Сайты, у которых устаревшие URL
|
||||
* @return array
|
||||
*/
|
||||
public function getSitesFromMiccedu(array $params) : array
|
||||
public function getSitesFromMiccedu(array $params): array
|
||||
{
|
||||
/*
|
||||
SELECT site, vuzkod AS org_id FROM opendata.miccedu_monitoring
|
||||
@ -86,7 +87,7 @@ class DatabaseFacade
|
||||
* Массив записей численности по специальностям
|
||||
* @return void
|
||||
*/
|
||||
public function insertContingent(array $contingent) : void
|
||||
public function insertContingent(array $contingent): void
|
||||
{
|
||||
/*
|
||||
INSERT INTO sveden_education_contingent
|
||||
@ -116,7 +117,7 @@ class DatabaseFacade
|
||||
* Публичное получение специальностей
|
||||
* @return array
|
||||
*/
|
||||
public function specialties() : array
|
||||
public function specialties(): array
|
||||
{
|
||||
return $this->specialties ? $this->specialties : [];
|
||||
}
|
||||
@ -124,7 +125,7 @@ class DatabaseFacade
|
||||
* Публичное получение id вузов, занесенных в базу opendata
|
||||
* @return array
|
||||
*/
|
||||
public function universities() : array
|
||||
public function universities(): array
|
||||
{
|
||||
return $this->universities ? $this->universities : [];
|
||||
}
|
||||
@ -132,7 +133,7 @@ class DatabaseFacade
|
||||
* Извлечение кодов специальности из базы данных niimko
|
||||
* @return array
|
||||
*/
|
||||
private function getSpecialties() : array
|
||||
private function getSpecialties(): array
|
||||
{
|
||||
/*
|
||||
SELECT id AS spec_id, kod AS spec_code FROM niimko.s_specs
|
||||
@ -155,7 +156,7 @@ class DatabaseFacade
|
||||
* Извлечение id вузов, занесенных в базу opendata
|
||||
* @return array
|
||||
*/
|
||||
private function getUniversities() : array
|
||||
private function getUniversities(): array
|
||||
{
|
||||
/*
|
||||
SELECT DISTINCT org_id FROM sveden_education_contingent
|
||||
@ -180,7 +181,7 @@ class DatabaseFacade
|
||||
* Массив [['org_id' => val1, 'site' => val1,],...]
|
||||
* @return void
|
||||
*/
|
||||
public function updateSitesOpendata(array $params) : void
|
||||
public function updateSitesOpendata(array $params): void
|
||||
{
|
||||
/*
|
||||
UPDATE niimko.s_vuzes
|
||||
|
@ -7,7 +7,7 @@ use ContingentParser\Http\UrlBuilder;
|
||||
use ContingentParser\Logger\HtmlLogger;
|
||||
use ContingentParser\Parser\ContingentFacade;
|
||||
|
||||
class Facade
|
||||
final class Facade
|
||||
{
|
||||
private DatabaseFacade $databaseFacade;
|
||||
private HttpClientFacade $httpClientFacade;
|
||||
@ -27,13 +27,12 @@ class Facade
|
||||
}
|
||||
/**
|
||||
* Получить массив сайтов
|
||||
* @param array $params
|
||||
* Массив сайтов, у которых нужны обновиленные URL
|
||||
* @param array $params Массив сайтов, у которых нужны обновиленные URL
|
||||
* @return array
|
||||
*/
|
||||
public function getSites(array $params = []) : array
|
||||
public function getSites(array $params = []): array
|
||||
{
|
||||
if (empty($params)) {
|
||||
if (!$params) {
|
||||
return $this->databaseFacade->getSitesFromNiimko();
|
||||
} else {
|
||||
return $this->databaseFacade->getSitesFromMiccedu($params);
|
||||
@ -42,65 +41,72 @@ class Facade
|
||||
/**
|
||||
* Cобирает из микроразметки данные таблицы
|
||||
* "Информация о численности обучающихся" в разделе "Образование"
|
||||
* @param array $site
|
||||
* Сайт содержащий id организации и URL
|
||||
* @param array $site Сайт содержащий id организации и URL
|
||||
* @return void
|
||||
*/
|
||||
public function collectDataFromContingent(array $site) : void
|
||||
public function collectDataFromContingent(array $site): void
|
||||
{
|
||||
list('org_id' => $orgId, 'site' => $url) = $site;
|
||||
// Нет URL сайта вуза
|
||||
if (empty($site)) {
|
||||
// $httpLogger->log($orgId);
|
||||
return;
|
||||
}
|
||||
// Уже в базе
|
||||
if (in_array($orgId, $this->databaseFacade->universities())) {
|
||||
if ($this->isExit($site)) {
|
||||
return;
|
||||
}
|
||||
$url = $this->urlBuilder->build($url);
|
||||
Printer::println(implode(' ', $site), 'green');
|
||||
$html = $this->httpClientFacade->processEducationContingentSites(
|
||||
Printer::println(implode(' ', $site), Color::GREEN);
|
||||
|
||||
$html = $this->httpClientFacade->getContentOfSite(
|
||||
$url,
|
||||
$site
|
||||
);
|
||||
|
||||
$uri = $this->contingentFacade->getLink($html);
|
||||
if ($uri) {
|
||||
$pattern = '/^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*)$/';
|
||||
if (preg_match($pattern, $uri)) {
|
||||
$html = $this->httpClientFacade->getContentOfSite(
|
||||
$url,
|
||||
$site
|
||||
);
|
||||
} else if ($this->urlBuilder->checkUri($uri)) {
|
||||
$html = $this->httpClientFacade->getContentOfSite(
|
||||
$url,
|
||||
$site,
|
||||
$uri
|
||||
);
|
||||
}
|
||||
}
|
||||
// Получаем данные таблицы численности
|
||||
$contingent = $this->contingentFacade->getContingent(
|
||||
$html,
|
||||
$this->databaseFacade->specialties(),
|
||||
$orgId
|
||||
$site['org_id']
|
||||
);
|
||||
|
||||
if ($contingent) {
|
||||
// $contingent = $this->contingentFacade->getContingentFromLink($html);
|
||||
// if ($contingent) {
|
||||
Printer::println("No result", 'red');
|
||||
$this->htmlLogger->log("$orgId $url");
|
||||
// }
|
||||
if ($this->contingentFacade->isValidContingent($contingent)
|
||||
&& $contingent
|
||||
) {
|
||||
// Заносим в базу
|
||||
Printer::print_r($contingent, Color::BLUE);
|
||||
$this->databaseFacade->insertContingent($contingent);
|
||||
} else {
|
||||
if ($this->contingentFacade->isValidContingent($contingent)) {
|
||||
// Заносим в базу
|
||||
Printer::print_r($contingent, 'blue');
|
||||
$this->databaseFacade->insertContingent($contingent);
|
||||
} else {
|
||||
$this->htmlLogger->log("$orgId $url");
|
||||
Printer::println("No result", 'red');
|
||||
}
|
||||
Printer::println("No result", Color::RED);
|
||||
$this->htmlLogger->log("$orgId $url");
|
||||
}
|
||||
Printer::println();
|
||||
}
|
||||
|
||||
public function getExclusionSites(string $path) : array
|
||||
/**
|
||||
* Условие выхода
|
||||
* @param array $site
|
||||
* @return bool
|
||||
*/
|
||||
private function isExit(array $site): bool
|
||||
{
|
||||
$logs = file($path);
|
||||
$result = [];
|
||||
foreach ($logs as $log) {
|
||||
$data = explode(' ', $log);
|
||||
$result[] = [
|
||||
'org_id' => $data[2],
|
||||
'site' => $data[3] ? $data[3] : ''
|
||||
];
|
||||
// Нет URL сайта вуза
|
||||
if (!$site['site']) {
|
||||
return true;
|
||||
}
|
||||
return $result;
|
||||
// Уже в базе
|
||||
if (in_array($site['org_id'], $this->databaseFacade->universities())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace ContingentParser\Http;
|
||||
|
||||
use ContingentParser\Color;
|
||||
use ContingentParser\Logger\HttpLogger;
|
||||
use ContingentParser\Printer;
|
||||
use CurlHandle;
|
||||
@ -12,16 +13,17 @@ final class CurlHelper
|
||||
private CurlHandle|bool $curl;
|
||||
private string $url;
|
||||
private array $site;
|
||||
private int $countRedirect;
|
||||
private const MAX_REDIRECT = 5;
|
||||
/**
|
||||
* Коснтруктор
|
||||
* Инициализация сессии
|
||||
* @param string $url
|
||||
* URL сайта
|
||||
* @param array $site
|
||||
* Идентификатор организации и базовый URL сайта
|
||||
* @param string $url URL сайта
|
||||
* @param array $site Идентификатор организации и базовый URL сайта
|
||||
*/
|
||||
public function __construct(string $url, array $site)
|
||||
{
|
||||
$this->countRedirect = 0;
|
||||
$this->url = $url;
|
||||
$this->site = $site;
|
||||
|
||||
@ -49,21 +51,25 @@ final class CurlHelper
|
||||
* Получить html-разметку
|
||||
* @return string
|
||||
*/
|
||||
public function getContent() : string
|
||||
public function getContent(): string
|
||||
{
|
||||
curl_setopt($this->curl, CURLOPT_URL, $this->url);
|
||||
$html = curl_exec($this->curl);
|
||||
if ($this->checkLocation($this->url, $html)) {
|
||||
$html = $this->getContent();
|
||||
if ($this->countRedirect < self::MAX_REDIRECT) {
|
||||
curl_setopt($this->curl, CURLOPT_URL, $this->url);
|
||||
$html = curl_exec($this->curl);
|
||||
if ($this->checkLocation($this->url, $html)) {
|
||||
$this->countRedirect++;
|
||||
$html = $this->getContent();
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
return $html;
|
||||
return '';
|
||||
}
|
||||
/**
|
||||
* Summary of checkLocation
|
||||
* @param string $html
|
||||
* @return bool
|
||||
*/
|
||||
private function checkLocation(string &$url, string $html) : bool
|
||||
private function checkLocation(string &$url, string $html): bool
|
||||
{
|
||||
preg_match('/location:(.*?)\n/i', $html, $matches);
|
||||
if (empty($matches)) return false;
|
||||
@ -77,14 +83,14 @@ final class CurlHelper
|
||||
* Сообщить об ошибке
|
||||
* @return void
|
||||
*/
|
||||
public function reportError() : void
|
||||
public function reportError(): void
|
||||
{
|
||||
$httpLogger = new HttpLogger('log/http-curl.log');
|
||||
|
||||
$httpCode = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);
|
||||
|
||||
if ($httpCode != 200 && $httpCode != 0) {
|
||||
Printer::println("HTTP-code: $httpCode", 'red');
|
||||
Printer::println("HTTP-code: $httpCode", Color::RED);
|
||||
$message = implode(' ', $this->site) . ' HTTP-code(' . $httpCode.')';
|
||||
$httpLogger->log($message, $httpCode);
|
||||
} else if ($httpCode == 0) {
|
||||
@ -93,7 +99,7 @@ final class CurlHelper
|
||||
$message .= " cURL error ({$errno}): ".curl_strerror($errno);
|
||||
$httpLogger->log($message);
|
||||
} else {
|
||||
Printer::println("HTTP-code: $httpCode", 'blue');
|
||||
Printer::println("HTTP-code: $httpCode", Color::BLUE);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace ContingentParser\Http;
|
||||
|
||||
use ContingentParser\Color;
|
||||
use ContingentParser\Printer;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\TransferStats;
|
||||
@ -17,10 +18,11 @@ final class HttpClientFacade
|
||||
* @param array $site Идентификатор организации, и базовый URL
|
||||
* @return string
|
||||
*/
|
||||
public function processEducationContingentSites(
|
||||
public function getContentOfSite(
|
||||
string $url,
|
||||
array $site
|
||||
) : string {
|
||||
array $site,
|
||||
string $uri = "sveden/education/"
|
||||
): string {
|
||||
try {
|
||||
$client = $this->createClient($url);
|
||||
// Запрос по базовому uri
|
||||
@ -30,18 +32,18 @@ final class HttpClientFacade
|
||||
}
|
||||
]);
|
||||
Printer::println("Redirect $url -> $redirectUrl");
|
||||
$url .= substr($url, -1) == '/' ? '':'/';
|
||||
$url .= "sveden/education/study";
|
||||
$url .= substr($url, -1) == '/' ? '' : '/';
|
||||
$url .= substr($uri, 0, 1) == '/' ? substr($uri, 1) : $uri;
|
||||
Printer::println("Parsing for $url");
|
||||
|
||||
$response = $client->get($url);
|
||||
$httpCode = $response->getStatusCode();
|
||||
Printer::println("HTTP-code: $httpCode", 'blue');
|
||||
Printer::println("HTTP-code: $httpCode", Color::BLUE);
|
||||
|
||||
$html = $response->getBody()->getContents();
|
||||
} catch (\Exception $e
|
||||
) {
|
||||
Printer::println("HTTP-code: ".$e->getCode(), 'red');
|
||||
Printer::println("HTTP-code: ".$e->getCode(), Color::RED);
|
||||
$html = $this->handleException($url, $site);
|
||||
} finally {
|
||||
return $html;
|
||||
@ -75,7 +77,7 @@ final class HttpClientFacade
|
||||
* Конфигурация клиента
|
||||
* @return array
|
||||
*/
|
||||
private function config() : array
|
||||
private function config(): array
|
||||
{
|
||||
return [
|
||||
'force_ip_resolve' => 'v4',
|
||||
@ -87,7 +89,7 @@ final class HttpClientFacade
|
||||
'protocols' => ['http', 'https'],
|
||||
'track_redirects' => true
|
||||
],
|
||||
'connect_timeout' => 300.0,
|
||||
'connect_timeout' => 90.0,
|
||||
'verify' => false,
|
||||
'headers' => [
|
||||
'User-Agent' => 'Mozilla/5.0 (X11; Linux x86_64) '
|
||||
|
@ -1,16 +1,15 @@
|
||||
<?php
|
||||
namespace ContingentParser\Http;
|
||||
|
||||
class UrlBuilder
|
||||
final class UrlBuilder
|
||||
{
|
||||
public function __construct() {}
|
||||
/**
|
||||
* Строит валидный URL сайта
|
||||
* @param string $url
|
||||
* Изначальный URL
|
||||
* @param string $url Изначальный URL
|
||||
* @return string
|
||||
*/
|
||||
public function build(string $url) : string
|
||||
public function build(string $url): string
|
||||
{
|
||||
// Строит -> https://<base_uri>
|
||||
$url = trim(strtolower($url));
|
||||
@ -18,13 +17,26 @@ class UrlBuilder
|
||||
$url = str_replace("www/", "www.", $url);
|
||||
$url = str_replace("http:\\\\", "", $url);
|
||||
if (!preg_match('#^https?://#', $url)) {
|
||||
$url = "http://$url";
|
||||
$url = "https://$url";
|
||||
}
|
||||
// $url = str_replace("http://", "https://", $url);
|
||||
$url = str_replace("http://", "https://", $url);
|
||||
$arr = parse_url($url);
|
||||
$url = $arr['scheme'] . '://' . $arr['host'] . '/';
|
||||
// $url = str_replace("www.", "", $url);
|
||||
$url = str_replace("www.", "", $url);
|
||||
$url = str_replace("_", "/", $url);
|
||||
|
||||
return trim($url);
|
||||
}
|
||||
|
||||
public function checkUri(string $uri): bool
|
||||
{
|
||||
if (str_ends_with($uri, ".pdf")
|
||||
|| str_ends_with($uri, ".docx")
|
||||
|| str_ends_with($uri, ".doc")
|
||||
|| str_starts_with($uri, "javascript")
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@ namespace ContingentParser\Logger;
|
||||
|
||||
final class DatabaseLogger extends Logger
|
||||
{
|
||||
public function log(string $message) : void
|
||||
public function log(string $message): void
|
||||
{
|
||||
$date = date('Y-m-d H:i:s');
|
||||
$logMessage = "[$date] $message\n";
|
||||
|
@ -1,9 +1,9 @@
|
||||
<?php
|
||||
namespace ContingentParser\Logger;
|
||||
|
||||
class HtmlLogger extends Logger
|
||||
final class HtmlLogger extends Logger
|
||||
{
|
||||
public function log(string $message) : void
|
||||
public function log(string $message): void
|
||||
{
|
||||
$date = date('Y-m-d H:i:s');
|
||||
$logMessage = "[$date] $message\n";
|
||||
|
@ -55,7 +55,7 @@ final class HttpLogger extends Logger
|
||||
510 => 'Not Extended',
|
||||
511 => 'Network Authentication Required'
|
||||
);
|
||||
public function log(string $message, int $httpCode = null) : void
|
||||
public function log(string $message, int $httpCode = null): void
|
||||
{
|
||||
$date = date('Y-m-d H:i:s');
|
||||
if (empty($httpCode)) {
|
||||
|
@ -1,23 +1,20 @@
|
||||
<?php
|
||||
namespace ContingentParser\Parser;
|
||||
|
||||
class ContingentFacade
|
||||
final class ContingentFacade
|
||||
{
|
||||
/**
|
||||
* Получить данные о численности
|
||||
* @param string $html
|
||||
* Разметка сайта вуза
|
||||
* @param mixed $specialties
|
||||
* Массив специальностей
|
||||
* @param int $orgId
|
||||
* Идентификатор организации
|
||||
* @param string $html Разметка сайта вуза
|
||||
* @param mixed $specialties Массив специальностей
|
||||
* @param int $orgId Идентификатор организации
|
||||
* @return array
|
||||
*/
|
||||
public function getContingent(
|
||||
string $html,
|
||||
array $specialties,
|
||||
int $orgId
|
||||
) : array {
|
||||
): array {
|
||||
$parser = new ContingentParser($html);
|
||||
$contingent = $parser->getDataTable();
|
||||
$this->addSpecId($contingent, $specialties);
|
||||
@ -27,11 +24,10 @@ class ContingentFacade
|
||||
}
|
||||
/**
|
||||
* Проверка на валидность записи численнести
|
||||
* @param array $contingent
|
||||
* Массив численности по специальностям
|
||||
* @param array $contingent Массив численности по специальностям
|
||||
* @return bool
|
||||
*/
|
||||
public function isValidContingent(array $contingent) : bool
|
||||
public function isValidContingent(array $contingent): bool
|
||||
{
|
||||
$count = 0;
|
||||
foreach ($contingent as $value) {
|
||||
@ -41,13 +37,11 @@ class ContingentFacade
|
||||
}
|
||||
/**
|
||||
* Добавить идентификатор специальности в запись численности
|
||||
* @param array $contingent
|
||||
* Массив численности по специальностям
|
||||
* @param array $specialties
|
||||
* Массив специальностей
|
||||
* @param array $contingent Массив численности по специальностям
|
||||
* @param array $specialties Массив специальностей
|
||||
* @return void
|
||||
*/
|
||||
private function addSpecId(array &$contingent, array $specialties) : void
|
||||
private function addSpecId(array &$contingent, array $specialties): void
|
||||
{
|
||||
$specIdMap = array_column($specialties, 'spec_id', 'spec_code');
|
||||
foreach ($contingent as $key => $con) {
|
||||
@ -56,10 +50,8 @@ class ContingentFacade
|
||||
}
|
||||
/**
|
||||
* Добавить идентификатор организации в запись численности
|
||||
* @param array $contingent
|
||||
* Массив численности по специальностям
|
||||
* @param int $orgId
|
||||
* Идентифиактор организации
|
||||
* @param array $contingent Массив численности по специальностям
|
||||
* @param int $orgId Идентифиактор организации
|
||||
* @return void
|
||||
*/
|
||||
private function addOrgId(array &$contingent, int $orgId): void
|
||||
@ -69,13 +61,13 @@ class ContingentFacade
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Summary of getContingentFromLink
|
||||
*
|
||||
* @param string $html
|
||||
* @return array
|
||||
* @return string
|
||||
*/
|
||||
// public function getContingentFromLink(string $html): array
|
||||
// {
|
||||
// $parser = new ContingentParser($html);
|
||||
// $
|
||||
// }
|
||||
public function getLink(string $html): string
|
||||
{
|
||||
$parser = new ContingentParser($html);
|
||||
return $parser->getLink();
|
||||
}
|
||||
}
|
@ -1,10 +1,14 @@
|
||||
<?php
|
||||
/**
|
||||
* Парсер информации об образовательной организации
|
||||
* с её сайта с использованием микроразметки
|
||||
*/
|
||||
namespace ContingentParser\Parser;
|
||||
|
||||
use DOMDocument;
|
||||
use DOMXPath;
|
||||
|
||||
class ContingentParser
|
||||
final class ContingentParser
|
||||
{
|
||||
private ?DOMXPath $xpath;
|
||||
private DOMDocument $dom;
|
||||
@ -33,7 +37,7 @@ class ContingentParser
|
||||
}
|
||||
}
|
||||
|
||||
private function setEncoding(string &$html) : void
|
||||
private function setEncoding(string &$html): void
|
||||
{
|
||||
$encoding = mb_detect_encoding($html, 'UTF-8, windows-1251');
|
||||
if ($encoding != self::ENCODING) {
|
||||
@ -46,7 +50,7 @@ class ContingentParser
|
||||
}
|
||||
$html = mb_convert_encoding($html,'HTML-ENTITIES','UTF-8');
|
||||
}
|
||||
public function getDataTable() : array
|
||||
public function getDataTable(): array
|
||||
{
|
||||
if (empty($this->xpath)) return [];
|
||||
|
||||
@ -77,7 +81,7 @@ class ContingentParser
|
||||
return $records;
|
||||
}
|
||||
|
||||
private function parseContingent() : array
|
||||
private function parseContingent(): array
|
||||
{
|
||||
$data = [];
|
||||
foreach (self::FIELDS as $field => $tag) {
|
||||
@ -100,8 +104,15 @@ class ContingentParser
|
||||
|
||||
public function getLink(): string
|
||||
{
|
||||
$needle = "Информация о численности обучающихся";
|
||||
$data = $this->dom->getElementsByTagName('a');
|
||||
var_dump($data->item(0)->getAttribute('href'));
|
||||
for ($i = 0; $i < $data->length; $i++) {
|
||||
$haystack = $data->item($i)->textContent;
|
||||
$isInformationOfContingent = strpos($haystack, $needle) !== false;
|
||||
if ($isInformationOfContingent) {
|
||||
return $data->item($i)->getAttribute('href');
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
namespace ContingentParser\Parser;
|
||||
|
||||
class ContingentRow
|
||||
final class ContingentRow
|
||||
{
|
||||
public function __construct(
|
||||
private string $eduCode,
|
||||
@ -20,7 +20,7 @@ class ContingentRow
|
||||
$this->contingent = $contingent;
|
||||
}
|
||||
|
||||
public function getData() : array
|
||||
public function getData(): array
|
||||
{
|
||||
return [
|
||||
"spec_code" => $this->eduCode,
|
||||
|
@ -1,26 +1,29 @@
|
||||
<?php
|
||||
namespace ContingentParser;
|
||||
|
||||
class Printer
|
||||
final class Printer
|
||||
{
|
||||
public static function print(string $text = '', string $color = '') : void
|
||||
{
|
||||
$color = Color::create($color);
|
||||
public static function print(
|
||||
int|string $text = '',
|
||||
Color $color = Color::WHITE
|
||||
): void {
|
||||
print($color->tostring().$text.Color::WHITE->tostring());
|
||||
}
|
||||
|
||||
public static function println(string $text = '', string $color = '') : void
|
||||
{
|
||||
$color = Color::create($color);
|
||||
public static function println(
|
||||
int|string $text = '',
|
||||
Color $color = Color::WHITE
|
||||
): void {
|
||||
print($color->tostring().$text.Color::WHITE->tostring());
|
||||
print(PHP_EOL);
|
||||
}
|
||||
|
||||
public static function print_r(mixed $value, string $color = '') : void
|
||||
{
|
||||
$color = Color::create($color);
|
||||
public static function print_r(
|
||||
mixed $value,
|
||||
Color $color = Color::WHITE
|
||||
): void {
|
||||
print($color->tostring());
|
||||
print_r($value);
|
||||
print(Color::WHITE->tostring());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user