Парсинг releases.1c.ru

2025-05-26

Пользователи давно не обновлявшие 1с, рано или поздно сталкиваются с необходимостью обновления конфигурации. И очень часто возникает вопрос - сколько релизов нужно установить чтобы обновиться до актуальной версии конфигурации? Или надо посмотреть дату выпуска конфигурации, да и вообще причины бывают всякие. И для ответов на эти вопросы нужно зайти на сайт releases.1c.ru.

Открываем сайт, почти всегда перекидывает на окно логина, будто там секретная информация, потом заходим все же открываем список конфигураций, открываем список релизов, поиском ищем номер, вобщем никакого удобства использования. Мне это все надоело и я решил написать парсер сайта releases.1c.ru, чтобы использовать данные было удобно и так как мне нужно.

Мало того, информацию о релизах я разместил здесь на сайте - release. Каждый желающий может воспользоваться этими данными, пока там нет функционала, но зато есть полная информация о датах, версиях, релизах без всяких авторизаций, т.к. эти данные всего лишь справочные и не содержат никаких ссылок на скачивание.

Алгоритм

  1. Открываем страницу https://releases.1c.ru/total.
  2. Если открылось окно логина - делаем вход.
  3. Если открылась страница, собираем данные обо всех конфигурациях и заносим в БД таблицу configurations поштучно.
  4. При каждой записи, открываем ссылку на релиз и парсим страницу с релизами, заносим записи поштучно с проверкой на дубли.
  5. Если открылось окно логина - делаем вход, и продолжаем обход конфигураций.
  6. Повторяем сначала через определенное время для актуальности.

Парсер releases.1c.ru я написал конечно же на php. Подключался к сайту релизов через Curl.
Кому инетересно заглянуть во внутренности парсера смотрим дальше, если хотите посмотреть на результаты его работы - заходите сюда.

Скрипт

Скрипт парсера не ахти какой красивый, но отрабатывает так как мне нужно. Для удобства в скрипте разместил комментарии.


file_put_contents(__DIR__ . '/log.txt', date('d.m.Y H:i:s') . PHP_EOL, FILE_APPEND);
$a=getpage($url);
getconfiglist($a);

function getpage($url){
	
file_put_contents(__DIR__ . '/log.txt', "Открываем страницу ".$url . PHP_EOL, FILE_APPEND);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_COOKIEJAR, __DIR__ .'/cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, __DIR__ .'/cookies.txt');
curl_setopt($ch, CURLOPT_COOKIESESSION, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
	'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:137.0) Gecko/20100101 Firefox/137.0',
	'Connection: Keep-Alive'
]);

$response = curl_exec($ch);
$info = curl_getinfo($ch);
//print_r($response);

if ($info['url'] != $url) { //Если запросили одну страницу, а открылась другая, то это скорее всего логин.
file_put_contents(__DIR__ . '/log.txt', "Хотели ".$url.",а получили ".$info['url'] . PHP_EOL, FILE_APPEND);
print_r($response);
$response = login($ch,$response,$info['url']);
return $response;
}
else {
return $response;
}	
	
}


function login($ch,$response,$url){

preg_match('~action="/login">(.*?)~is', $response, $m );
preg_match_all('~~Uis',$m[1],$a);

foreach($a[1] as $field) {

	if(preg_match('~name="(.*)"~Uis',$field,$name)){
		$name = $name[1];
	}else{
		$name = "";
	}
	if(preg_match('~value="(.*)"~Uis',$field,$val))
		{
		$val = $val[1];
	}else{
		$val = "";
	}
	$data[$name] = $val;

}
$data['username']=''; //Логин
$data['password']=''; //Пароль
$data['rememberMe']="on";

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, dirname(__FILE__) .'/cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, dirname(__FILE__) .'/cookies.txt');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/x-www-form-urlencoded',
	'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
	'Host: login.1c.ru',
	'Origin: https://login.1c.ru',
	'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:137.0) Gecko/20100101 Firefox/137.0',
	'Connection: Keep-Alive',
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));


$response = curl_exec($ch);
$ch_info = curl_getinfo($ch);

curl_close($ch);	
	file_put_contents(__DIR__ . '/log.txt', "Была переадресация, получили ответ от логина" . PHP_EOL, FILE_APPEND);

return $response;
}

//Парсим список конфигураций
function getconfiglist($data){
	
	$dom = new DOMDocument();
	$dom->loadHTML($data,LIBXML_NOERROR);
	$xpath = new DomXPath($dom);
	$trs = $xpath->query("//*[@id='actualTable']/tbody/tr");
	foreach ($trs as $tr) {
		unset($configdata);
		$tds = $tr->getElementsByTagName('td');
if ($tds->length<8){
		
	foreach ($tds as $td) {
		$configdata['category'] = trim($td->nodeValue," \n\r\t\v\x00");
	}	
	
}elseif ($tds->length==8){
$configdata['href']="";
$href = $tds[0]->getElementsByTagName('a');
if ($href->length>0)
$configdata['href'] = $href[0]->getAttribute('href');

$configdata['name'] = trim($tds[0]->nodeValue," \n\r\t\v\x00");
$configdata['version'] = trim($tds[1]->nodeValue," \n\r\t\v\x00");
$configdata['date'] = trim($tds[2]->nodeValue," \n\r\t\v\x00");	

//В ячейке с версией может быть указано больше одной версии с кучей пробелов
$configdata['version'] = preg_replace('~\\s+~', ' ',$configdata['version'], -1);
$configdata['date'] = preg_replace('~\\s+~', ' ',$configdata['date'], -1);

$getversion = insertupdate($configdata,"configurations");
if ($getversion){ //Если обновилась конфигурация, то получаем ее id и обновляем список релизов
file_put_contents(__DIR__ . '/log.txt', "Обновлена конфигурация ".$getversion[0]['configuration_id'] . PHP_EOL, FILE_APPEND);
if(!empty($getversion[0]['href'])){
	getversions($getversion[0]);
}
else
{ //Если ссылки нет, то запишем то что есть для статистики
	$configdata["configuration_id"] = $getversion[0]['configuration_id'];
	unset($configdata["name"]);
	unset($configdata["category"]);
	unset($configdata["href"]);
	insertupdate($configdata,"surreleases");
}
}
}

}

echo file_get_contents(__DIR__ . '/log.txt');

}
	
	
//Парсим список версий
function getversions($data){
	//print_r($data);
	$releasedata['configuration_id'] = $data['configuration_id'];
	$url = 'https://releases.1c.ru'.$data['href'].'?allUpdates=true';
	$data = getpage($url);
	$dom = new DOMDocument();
	$dom->loadHTML($data,LIBXML_NOERROR);
	$xpath = new DomXPath($dom);
	$trs = $xpath->query("//*[@id='versionsTable']/tbody/tr");
	foreach ($trs as $tr) {
		$tds = $tr->getElementsByTagName('td');
			foreach ($tds as $td) {
		$field = str_replace("Column","",$td->getAttribute('class'));
		$field = str_replace("minVersions","platform",$field);
		$releasedata[$field] = trim($td->nodeValue," \n\r\t\v\x00");
	}
$result = insertupdate($releasedata,$table = "releases");
if (!$result) break;

file_put_contents(__DIR__ . '/log.txt', "Добавлен ".$result[0]['version'] . PHP_EOL, FILE_APPEND);
	}
}
	
	
	
function insertupdate($configdata,$table){
include_once (__DIR__ . '/../Database.php');
$db = Database::DBconnect('releases');
//Для каждой записи запрашиваем есть такая или нет
$sql = $db->prepare("SELECT COUNT(*) FROM $table WHERE ".implode(' AND ', array_map(function($k) { return "$k = :$k"; }, array_keys($configdata))));
$sql->execute($configdata);

if ($sql->fetchColumn() == 0){//Если такой записи нет, то вставляем ее или обновляем ту что есть(для главной)
if ($table == "configurations")	
$sql = $db->query("SELECT COUNT(*) FROM $table WHERE name = '".$configdata['name']."'")->fetchColumn();

if($sql > 0){ //Если запись есть то обновляем

	$sql = $db->prepare("UPDATE $table SET ".implode(', ', array_map(function($k) { return "$k = :$k"; }, array_keys($configdata)))." WHERE name = :name");
	$sql->execute($configdata);
}

else
{	
	$sql = $db->prepare("INSERT INTO $table (".implode(', ', array_keys($configdata)).") VALUES (:".implode(', :', array_keys($configdata)).")");
	$sql->execute($configdata);
	
}
if ($table == "configurations") //Возвращаем id-конфигурации
$sql = $db->prepare("SELECT configuration_id, href FROM $table WHERE ".implode(' AND ', array_map(function($k) { return "$k = :$k"; }, array_keys($configdata))));
else //Возвращаем количество добавленных релизов
$sql = $db->prepare("SELECT version FROM $table WHERE ".implode(' AND ', array_map(function($k) { return "$k = :$k"; }, array_keys($configdata))));
$sql->execute($configdata);

return $sql->fetchALL(PDO::FETCH_ASSOC);
}

return false;


}