Получение списка запрещенных сайтов Госкомнадзора

Данные скрипты предназначены для приема списка запрещенных Госкомнадзором сайтов. Могут быть полезными для IT-специалистов организаций (фирм), в обязанность которым вменено получение данного списка.
Некоторое время назад проблема получения данного списка встала перед нами в полный рост. В принципе сам список можно получать в ручном режиме с сайта vigruzki.rkn.gov.ru. Но так как программист скотина ленивая, немедленно было решено это все автоматизировать :) Формировать ежедневно вручную файлы запроса и подписи, а затем проходить процедуру запроса и получения файлов мне как-то не улыбалось. Немного покопавшись в этих ваших энторнетах я обнаружил на сайте [url]habrahabr.ru[/url] статейку по решению проблемы. Сделав все по рекомендациям в статье оказалось что программа немножко сильно не работает. Пришлось немножко напрячь мезушный ганглий и сваять на основе что-нибудь свое.

Первая проблема. Оказалось что скрипт написан на PERL. Я никогда не изучал PERL. В своей работе также его не использую. Поэтому пришлось немного времени потратить на его изучение. Специалисты по PERL скорей всего обнаружат далее кривой с их точки зрения код. "Кто так пишет??!!". В свою защиту скажу что я потратил не более часа времени. Разумеется многие ньюансы я упустил. Так что, "не стреляйте в пианиста! играет как умеет" :)

Итак. Для работы программы требуется:
1. Установить интерпретатор PERL. Я поставил ActivePerl 5.22.0.
1.1.К нему нужно найти и скОчать библиотечку для работы с SOAP. Если не ошибаюсь она называется SOAP::lite.
2. Установить и настроить КриптоПРО для работы с электронной подписью. Расписывать как настраивается КриптоПРО с вашей эл.подписью я не стану. Тем более получение эл.подписи от авторизованного представителя.

Файловая структура проекта имеет следующий вид (у меня). На диске C создана папка RKN. Внутри нее содержатся 3 папки:
logs - содержит лог работы программы
result- папка куда попадает архив принятого файла
source - папка со скриптами (собственно сама программа)

Пример файла логов:
08_04_2016_02:00:03: !!!START!!!
08_04_2016_02:00:03: gotovim failovuyu peremennuyu faila zaprosa
08_04_2016_02:00:03: gotovim failovuyu peremennuyu faila podpisi
08_04_2016_02:00:03: Poluchaem opisanie metodov raboty s servisom cherez wdsl-shemu
08_04_2016_02:00:10: soap: OperatorRequestService=HASH(0x4083044)
08_04_2016_02:00:10: Otpravlyaem zapros getLastDumpDateEx
08_04_2016_02:00:10: Otpravlyaem zapros getResult
08_04_2016_02:00:14: Actualnaya versiya formata vigruzki: 2.2
08_04_2016_02:00:14: Otpravlyaem zapros sendRequest
08_04_2016_02:00:18: Code vigruzki: 958aa2e7e752409b36d075f6c40d7f70
08_04_2016_02:00:18: Otpravlyaem zapros sendRequest
08_04_2016_02:00:18: Pauza 60 sekund
08_04_2016_02:01:18: Otpravlyaem zapros getResult
08_04_2016_02:01:18: Pauza 30 sekund
08_04_2016_02:01:48: Otpravlyaem zapros getResult
08_04_2016_02:01:54: Pauza 30 sekund
08_04_2016_02:02:24: Code otveta: 1
08_04_2016_02:02:24: Text otveta: OK
08_04_2016_02:02:24: Uspeshno prinyat file: C:\rkn\result\register-08_04_2016_02_00_03.zip
08_04_2016_02:02:24: !!!END!!!

А пачиму не по-русски спросите вы? Хаааароший вопрос! Потому что мне лень было заморачиваться разбираться как PERL работает с кодировкой. И чтобы не получать кракозябры вместо кириллицы оставил все так :)

Папка source содержит 3 файла:
start.bat - батник для запуска работы скриптов
make_request.pl - перловый скрипт для формирования файла запроса.
get_register.pl - перловый скрипт для приема файла-архива, содержащий список запрещенных сайтов

Содержимое start.bat:
@echo on

rem удаляем ранее созданные файлы запроса и подписи
DEL C:\rkn\source\request*.* /f/q
rem Запускаем скрипт формирования запросов
perl C:\rkn\source\make_request.pl
rem запускаем утилиту для создания подписи
"C:\Program Files\Crypto Pro\CSP\csptest.exe" -sfsign -sign -detached -add -in C:\rkn\source\request.xml -out C:\rkn\source\request.xml.sig -my santaclaus@mail.ru
rem запускаем скрипт для полученрия списка запрещенных сайтов
perl C:\rkn\source\get_register.pl

Тут думаю все понятно. Если вы свой проект реализуете в другом месте, тогда поправьте пути до него. Пути до КриптоПРО также надо проставить свои. Обратите внимание! Адрес электронной почты должен быть: а) правильный и б) тот что стоит у вас в электронной подписи. В смысле на того кого была зарегистрирована подпись. Иначе будут проблемы с получением

Содержимое make_request.pl
use POSIX qw(strftime);

my $date = strftime "%Y-%m-%d", localtime;
my $date2 = strftime "%H:%M:%S.000+10:00", localtime;

#Удаляем старые файлы с запросом и подписью если такие есть
unlink('C:\rkn\source\request.xml');
unlink('C:\rkn\source\request.xml.sig');

#Формируем xml запрос на сервер
$request='<?xml version="1.0" encoding="windows-1251"?><request><requestTime>'.$date.'T'.$date2.'</requestTime><operatorName>Нзвание моей организации</operatorName><inn>1234567890</inn><ogrn>1234567890123</ogrn><email>santaclaus@mail.ru</email></request>';

#Создаем в рабочей директории файл запроса
my $filename = 'C:\rkn\source\request.xml';
open(my $fh, '>', $filename) or die "Не могу открыть '$filename' $!";
print $fh $request;
close $fh;


Данный скрипт нужно подправить соответствующим образом, указав в нем реквизиты своей организации, как то: название организации, ИНН, ОГРН, электронная почта. Обратите внимание!! Опять нужна правильная электронная почта!! Как не трудно заметить скрипт динамически указывает время запроса. Это все в соответствии с требованиями Роскомнадзора.

Содержимое get_register.pl
use strict;
use warnings;
use SOAP::Lite;
use DBI;
use Data::Dumper;
use MIME::Base64;
use utf8;
use XML::Simple;
use URI;
use Digest::MD5 qw(md5 md5_hex md5_base64);
use Encode qw(encode_utf8);
use POSIX;
use POSIX qw(strftime);
use Time::Local;
use File::Basename;
use Switch;
use Net::Ping;

my ( $req, $sig, $buf );

my $req_file = 'C:\rkn\source\request.xml';
my $sig_file = 'C:\rkn\source\request.xml.sig';

my $now_string = strftime "%d_%m_%Y_%H_%M_%S", localtime;
my $now_date = strftime "%d_%m_%Y", localtime;

my $FileName = 'C:\rkn\result\register-'.$now_string.'.zip';

my $lof_file = 'C:\rkn\logs\work_'.$now_date.'.log';

sub insert_into_log{
my $in_str = $_[0];
my $now_string = strftime "%d_%m_%Y_%H:%M:%S", localtime;

if (-e $lof_file) {
#file exists
open FILE, '>>'.$lof_file;
print FILE $now_string.": ".$in_str."\n";
close FILE;

} else {
#file NOT exists
open FILE, '>'.$lof_file;
print FILE $now_string.": ".$in_str."\n";
close FILE;
}
}

#-----------------------------------------------------------------------

insert_into_log("!!!START!!!");

insert_into_log("gotovim failovuyu peremennuyu faila zaprosa");

# request
open F, '<'.$req_file || die $!;
binmode F;
while( (read F, $buf, 65536) != 0 ) {
$req .= $buf;
}
close F;

insert_into_log("gotovim failovuyu peremennuyu faila podpisi");

# signature
open F, '<'.$sig_file || die $!;
binmode F;
while( (read F, $buf, 65536) != 0 ) {
$sig .= $buf;
}
close F;

insert_into_log("Poluchaem opisanie metodov raboty s servisom cherez wdsl-shemu");
#----------------------------
#Получаем описание методов для работы с сервисом через wsdl-схему
my $soap = SOAP::Lite->service('http://vigruzki.rkn.gov.ru/services/OperatorRequest/?wsdl');

insert_into_log("soap: ".$soap);

insert_into_log("Otpravlyaem zapros getLastDumpDateEx");

my $answ = 0;
my $dfv = "";

while ($answ eq 0) {
insert_into_log("Otpravlyaem zapros getResult");
#Отправляем запрос на сервер
my @r = $soap->getLastDumpDateEx();

if($r[3] eq ""){
insert_into_log("Actualnaya versiya formata vigruzki poluchena ne byla!");
sleep 10;
}else{
$answ = 1;
#dumpFormatVersion
$dfv = $r[3];
insert_into_log("Actualnaya versiya formata vigruzki: ".$dfv);
}

}


$answ = 0;

my $code = "";

while ($answ eq 0) {
insert_into_log("Otpravlyaem zapros sendRequest");
#Отправляем запрос на сервер
my @r2 = $soap->sendRequest($req, $sig, $dfv);

if($r2[2] eq ""){
insert_into_log("Code vigruzki poluchen ne byl!");
sleep 10;
}else{
$answ = 1;
#dumpFormatVersion
$code = $r2[2];
insert_into_log("Code vigruzki: ".$code);
}

}

insert_into_log("Otpravlyaem zapros sendRequest");

binmode(STDOUT, ':utf8');

my $wait_interval = 60;

insert_into_log("Pauza ".$wait_interval." sekund");
sleep $wait_interval;
#sleep 1, print "$_\s" for 1..$wait_interval;

my $result;
my $resultCode = 0;
my @r3;

while ($resultCode eq 0) {
insert_into_log("Otpravlyaem zapros getResult");
@r3 = $soap->getResult($code);

$result = $r3[0];
$resultCode = $r3[2];

insert_into_log("Pauza 30 sekund");
sleep 30;
#sleep 1, print "$_\s" for 1..30;
}

insert_into_log("Code otveta: ".$resultCode);

switch ($resultCode) {
case -1 { insert_into_log("Text otveta: Neverniy algoritm podpisi") }
case -2 { insert_into_log("Text otveta: Neverniy format podpisi") }
case -3 { insert_into_log("Text otveta: Nedeistvitelniy sertifikat podpisi") }
case -4 { insert_into_log("Text otveta: Nekorrektnoe znachenie podpisi") }
case -5 { insert_into_log("Text otveta: Oshibka proverki serificata podpisi") }
case -6 { insert_into_log("Text otveta: U zayavutelya otsustvuet licensia na uslugi dostupa v Internet") }
case -7 { insert_into_log("Text otveta: Otsutstvuet ID zaprosa") }
case -8 { insert_into_log("Text otveta: Neverniy format ID zaprosa") }
case -9 { insert_into_log("Text otveta: Ne naiden zapros po ukazannomu ID") }
case -10 { insert_into_log("Text otveta: Povtorite zapros pozdnee") }
case 0 { insert_into_log("Text otveta: Zapros obrabativaetsa") }
case 1 { insert_into_log("Text otveta: OK") }
else { insert_into_log("Text otveta: Neopredelennaya oshibka") }
}

if($resultCode eq 1){
my $zip = decode_base64($r3[1]);

open F, '>'.$FileName || die "Can't open arch.zip for writing!\n".$! ;
binmode F;
print F $zip;
close F;
insert_into_log("Uspeshno prinyat file: ".$FileName);
}else{
insert_into_log("Prinyat file ne udalos");
}

insert_into_log("!!!END!!!");


Ну собственно вот и оно :)

Как не трудно заметить каждое действие предваряет внесение в лог записи о начале этого действия. А после действия в лог вносится сведения об успешности его. Если на каком-то этапе программа не сработает, тогда будет понятно в логе где копать.

Про почему не на русском я уже говорил.

Мне не правится обращение к элементам массива по их порядковым номерам. Но вариант с обращением по имени почему-то не сработал, глубоко копаться в PERL я не стал. Поэтому код такой корявый.

Программа работает в большинстве случаев. Но иногда виснет когда по какой-то причине не прошел запрос. ну там сайт не работает, энторнета не было или что-то еще. Я не стал дописывать скрипт внося соответствующие проверки. Бог в помощь если кто могёт! :)

Ну вообщем батник start.bat вешаете на запуск по расписанию и радуемся! :)
  • просмотров: ~1064
  • рейтинг: ?

Комментарии (4)

Вы - anonymous, войти ?

можно использовать bbcode-теги
[b]жирный текст[/b]
[i]курсив[/i]
[u]underline[/u]
[s]зачеркнутый текст[/s]
[size=20px]размер шрифта[/size]
всякие изменения текста
[left][/left]
[right][/right]
[center][/center]
позиционирование элементов: картинки, текст и т.д
[url][/url]
[email][/email]
внутри тега [url] помещайте ссылки, а внутри [email] адрес электронной почты;
так же [url] можно использовать в виде:
[url=http://example.com]пример[/url],
[url=http://test.ru][img]http://flickr.com/givemeimg.png[/img][/url]
[code][/code]
[quote][/quote]
внутри тега [code] можно помещать программный код (подстветка попытается включиться автоматически); для выделения цитат используйте [quote]
также можно напрямую указать язык [code=cpp]int i;[/code]
[list][/list]
создаем списки, каждый элемент пишется после [*].

Можно указывать маркер - [list=marker].
возможные маркеры 1(decimal), i(lower-roman), I(upper-roman), a(lower-alpha), A(upper-alpha). Примеры:

[list][*]1 элемент[*]2 элемент[*]3 элемент[/list]
[list=1][*]1 элемент[*]2 элемент[*]3 элемент[/list]
[list=A][*]1 элемент[*]2 элемент[*]3 элемент[/list]
[table][/table]
оформляем таблицу, используя внутренние теги [tr] и [td].
[tr] - строка, [td] - поле в строке,
[table=100%] - можно задавать ширину в процентах, по-умолчанию ширина 100%
[td=2] - можно задавать сколько столбцов входит в это поле. Пример:

[table=50%][tr][td]столбец 1[/td][td]столбец 2[/td][/tr][tr][td]значение 1[/td][td]значение 2[/td][/tr][tr][td=2]сразу 2 столбца[/td][/tr][/table]
[img][/img]
тег для вставки фото или картинок, мы любим картинки. Примеры использования:

[img]http://ya.ru/logo.png[/img],
[img=100x100px]http://ya.ru/logo.png[/img]
[img=fullimg.url]thumbimg.url[/img],
Пожалуйста загружайте картинки на наш сайт, либо вставляйте с бекбоновских ресурсов.
[video][/video]
Проигрывает видео, внутрь вставляем ссылки на видео, поддерживается Play.Ykt.Ru(нужно вставить ссылку на страницу с видео) и tv.ykt.ru(нужно вставить ссылку на адрес файла)