Платформа 8.3.10, УФ.
Понадобилось для своей конфигурации тупо посмотреть, сколько рабочих дней было в месяце. Заводить из-за этого свой или подключать БСП-шный календарь, графики рабочего времени с учётом переносов выходных и праздников, обеспечивать их актуальность — 8 килограмм проблем — лень.
Вот и решил сделать такую простенькую функцию, которая ходила бы на сайт ИТС и оттуда бы забирала эти данные, благо они в открытом доступе…
Функция делает простое обращение по https к сайту ИТС (its.1c.ru) и забирает оттуда информацию, связанную с календарём бухгалтера. Так как эта информация лежит в открытом доступе, логин и пароль к сайту ИТС не требуется. В качестве страницы, к которой происходит обращение, указывается путь /calendar/YYMM. Выполняется простой парсинг полученного ответа: находятся строки, содержащие текст "Календарных дней", "Рабочих дней", "Рабочих часов", "Выходных и праздничных дней". Если на сайте нет информации о каком-либо месяце, то и ответ будет невразумительный. Например, на сегодняшний день (22.11.2024) доступны сведения о календаре бухгалтера с декабря 2011 года по декабрь 2024 года. Видимо, более ранних сведений просто нет, а календарь на следующий год ИТС-ники пока не удосужились ввести на сайт. В этом случае функция выдаст ошибку, в возвращаемой структуре будут нули. Чтобы избежать ошибок, если они существуют на сайте (да-да, челофактор повсюду!), сделаны простенькие проверки. Ну, сами посмотрите, всё прозрачно.
Косячки немножко есть, знаю — фукнцию можно легко оптимизнуть, не судите строго.
Пользуйтесь на здоровье, мало ли кому пригодится.
Вот как-то так:
// Сведения о нужном месяце с сайта ИТС.
// Параметр - сам месяц в формате даты (год тоже нужен).
// Возвращаемое - структура с числовыми полями:
// КолвоКалендарных
// КолвоРабочих
// КолвоВыходных
// КолвоРабочихЧасов
// если что-то не так, - в возвращаемых значениях "0".
&НаКлиенте
Функция ПолучитьКалендарныеДанныеСайтаИТС(Мес)
// Соединение устанавливаем по HTTPS, иначе не работает:
Соед = Новый HTTPСоединение("its.1c.ru", 443,,,,, Новый ЗащищенноеСоединениеOpenSSL(Новый СертификатКлиентаWindows(СпособВыбораСертификатаWindows.Авто), Новый СертификатыУдостоверяющихЦентровWindows()),);
// Сформируем нужную папку для запроса, добавим в правильном формате месяц и год:
ВебЗапр = Новый HTTPЗапрос("calendar/"+Формат(Мес,"ДФ=yyMM"));
// Пробуем достучаться до сервера:
Попытка
Результат = Соед.Получить(ВебЗапр);
Исключение
Сообщить("Ошибка соединения: Что-то не так с обращением к сайту its.1c.ru. Возможно, сервер недоступен. Или что-то с интернетом.");
ВызватьИсключение; // Ну пусть пока так будет...
КонецПопытки;
// До сервера может и достучалось, но какие-то проблемы со страницей:
Если Результат.КодСостояния >= 300 Тогда
Сообщить("Ошибка: Что-то не так с обращением к странице. Возможно, календарь бухгалтера для этого месяца не определён.");
ДанныеМесяца = новый структура;
ДанныеМесяца.Вставить("КолвоКалендарных", 0);
ДанныеМесяца.Вставить("КолвоРабочих", 0);
ДанныеМесяца.Вставить("КолвоВыходных", 0);
ДанныеМесяца.Вставить("КолвоРабочихЧасов", 0);
Возврат ДанныеМесяца;
КонецЕсли;
// Пока всё норм, получаем текст страницы. Просто для удобства:
Резуль = Результат.ПолучитьТелоКакСтроку();
// Находим нужные позиции (они могут идти и не в такой последовательности!!!):
ПозКД = СтрНайти(Резуль, "Календарных дней"); // Календарных дней
ПозРД = СтрНайти(Резуль, "Рабочих дней"); // Рабочих дней
ПозВД = СтрНайти(Резуль, "Выходных и праздничных дней"); // Выходных дней
ПозРЧ = СтрНайти(Резуль, "Рабочих часов"); // Рабочих часов при 40-часовой рабочей неделе - убить их мало: то ошибку в строке сделают, то дефис забудут... Ну... Чем богаты.
// Периодически они после цифр втыкали лишний пробел, поэтому на всякий случай "СокрЛП", см., напр, март 2024. Считаем концом строки текст "<br>":
Если ПозКД Тогда КвоКД = СокрЛП(Сред(Резуль, ПозКД+19, СтрНайти(Резуль, "<br>", , ПозКД) - (ПозКД + 19))); Иначе КвоКД = "0"; КонецЕсли;
Если ПозРД Тогда КвоРД = СокрЛП(Сред(Резуль, ПозРД+15, СтрНайти(Резуль, "<br>", , ПозРД) - (ПозРД + 15))); Иначе КвоРД = "0"; КонецЕсли;
Если ПозВД Тогда КвоВД = СокрЛП(Сред(Резуль, ПозВД+30, СтрНайти(Резуль, "<br>", , ПозВД) - (ПозВД + 30))); Иначе КвоВД = "0"; КонецЕсли;
Если ПозРЧ Тогда КвоРЧ = СокрЛП(Сред(Резуль, ПозРЧ+46, СтрНайти(Резуль, "<br>", , ПозРЧ) - (ПозРЧ + 46))); Иначе КвоРЧ = "0"; КонецЕсли;
// Ну пробуем, чо:
Попытка ККД = Число(КвоКД); Исключение ККД = 0; КонецПопытки;
Попытка КРД = Число(КвоРД); Исключение КРД = 0; КонецПопытки;
Попытка КВД = Число(КвоВД); Исключение КВД = 0; КонецПопытки;
Попытка КРЧ = Число(КвоРЧ); Исключение КРЧ = 0; КонецПопытки;
// Структура с данными:
ДанныеМесяца = новый структура;
ДанныеМесяца.Вставить("КолвоКалендарных", ККД);
ДанныеМесяца.Вставить("КолвоРабочих", КРД);
ДанныеМесяца.Вставить("КолвоВыходных", КВД);
ДанныеМесяца.Вставить("КолвоРабочихЧасов", КРЧ);
// Возвращаем:
Возврат ДанныеМесяца;
КонецФункции
В обработке в качестве примера всё реализовано целиком.
На вскидку небольшие придирки:
// Эта функция делает блаблабла
// Возращает блаблабла
// Параметры:
// Мес — (дата) обязательный
// месяц на который надо получить праздники
Функция ПолучитьКалендарныеДанныеСайтаИТС(Знач Мес) Экспорт
При попытка исключение лучше в исключение добавлять Сообщить(«Что-то пошло не так блаблабла» + Символы.ПС + ОписаниеОшибки()), тогда в последствии будет гораздо меньше гемороя при выяснении, что не работает.
Вот так покрасивее было бы на мой взгляд:
Результат = Результат.ПолучитьТелоКакСтроку();
Так делать не очень красиво:
Попытка ККД = Число(КвоКД); Исключение ККД = 0; КонецПопытки;
(1) Также очень бы рекомендовал разбирать HTML страницу через DOM, это будет и быстрее и точнее и не будет: «// убить их мало».
Если не умеете, то советую быстренько пройти последние модули по JS на SoloLearn (все бесплатно, есть приложение на ведроид), займет час максимум, но качество возрастет в разы. Я этому научился сидя на, пардон, унитазе со смартфона :3 В общем это просто необходимый момент для парсинга. И таким образом можно было бы разобрать не примечание снизу, а сам календарь-таблицу, получая описания для каждого дня.
(2)
Спасибо, посмотрю.
На предыдущий коммент — Вы, наверно, абсолютно правы во всех придирках, но функция представляется очень малозначимой, поэтому пост править не буду, пусть уж так.
(4) Если очень кратенько, то вам жизнено необходимо научиться делать примерно так:
Потренироваться можно нажав F12 в браузере и открыв вкладку с консолью и элементами страницы. Разбирать лучше всеже так, при этом представляя, что вы разработчик того сайта готовый прям сейчас поменять контент и предугадывая какие тэги, классы и id остануться без изменений.
Еще есть такое:
Показать
Ну и все в таком духе :3
PS: мог в синтаксисе гденить немног абшибиться, но идея в целом такая)
1с не так силен в парсинге-скрапинге, как скажем, Python библиотека lxml. Но в целом и им можно добиться очень неплохих результатов и разобрать очень многое.
(5)
Спасибо.