Як ми парсили декларації про доходи за допомогою відкритих даних

Вже другий рік я займаюся державними відкритими даними РФ і роботою з держорганами і пора б починати розповідати цікаві історії про те, як з'являються дані. Проте сьогодні мова піде про більш звичної для розробника області — парсингу даних для проекту «Декларатор» і про те, яку несподівану користь можуть принести відкриті дані.



«Декларатор» — це постійно поповнювана база декларацій про доходи та майно публічних посадових осіб: депутатів, чиновників, суддів, представників регіональної та муніципальної влади, інших органів, держкорпорацій і держкомпанією. Проект працює як інформаційно-довідкова база для ЗМІ, активістів, які займаються громадським контролем, і дослідників.
У Росії відомості про доходи повинні публікувати більше мільйона чоловік.

Цікавий факт: існують єдині правила для держсайтів за розміщення декларацій про доходи (зокрема, вони завжди знаходяться у розділі «Протидія корупції») і відповідає за всю цю тему Міністерство праці та соціального захисту РФ. Масове розміщення декларацій відбувається в травні. Далі у Мінпраці є всього місяць на те, щоб провести моніторинг по всіх без винятку сайтів, зобов'язаним розміщувати інформацію. Моніторинг проводиться вручну.

Є кілька проблем, пов'язаних з публікацією декларацій:

  • кожне відомство робить це на власному сайті;
  • не існує єдиного стандарту для публікації декларацій;
  • інформацію можуть видалити незабаром після публікації;
  • будучи загальнодоступними за законом, декларації досі не публікуються в машиночитаемом вигляді.
МатчастинуЗгідно з пунктом 2 Порядку розміщення відомостей про доходи, витрати, про майно і зобов'язання майнового характеру окремих категорій осіб і членів їх сімей на офіційних сайтах федеральних державних органів, органів державної влади суб'єктів Російської Федерації і організацій і надання цих відомостей загальноросійським засобам масової інформації для опублікування, затвердженого Указом Президента Російської Федерації від 8 липня 2013 р. № 613 «Питання протидії корупції», федеральні державні органи влади, Центральний банк Російської Федерації, Пенсійного фонду Російської Федерації, Фонд соціального страхування Російської Федерації, Федеральний фонд обов'язкового медичного страхування, державні корпорації (компанії), інші організації, створені на підставі федеральних законів, зобов'язані публічно розміщувати відомості про доходи за минулий календарний рік.

Зацікавлені можуть прочитати подробиці наказі Мінпраці 530н, а якщо коротко: розділ «Протидія корупції» повинен знаходитися в одному кліці від головної сторінки і містити кілька обов'язкових підрозділів з жорстко заданими назвами, серед яких нас цікавить одна – «Відомості про доходи, витрати, про майно і зобов'язання майнового характеру». Саме в ньому, без обмеження доступу, в табличній формі, в тому числі у форматах .doc, .docx, .excel .rtf (п. 15 Вимог), розміщуються декларації про доходи держчиновників.

При цьому, як прямо зазначено в документі, «повинна бути забезпечена можливість пошуку по тексту файла і копіювання фрагментів тексту» — ось це і робить можливим створення парсера.

Про деклараціях
Декларація про доходи кожного чиновника містить інформацію про об'єкти нерухомості, що перебувають у власності, користуванні, відомості про транспортні засоби, відомості про доходи та джерела доходів. У декларації перераховані не тільки чиновники, але і члени їх сімей. Якщо пощастить, зведений файл створюється за запропонованим Минтрудом шаблону форми відомостей про доходи, що сильно полегшує завдання написання універсального парсера.



Першим об'єктом інтересу стало Міністерство освіти і науки. Пробний парсер, декларацій про доходи федеральних державних службовців за 2014 рік на 306 осіб, був написаний швидко і досить безболісно. Після цього ми вирішили перейти до того, що зазвичай викликає найбільшу кількість запитів дослідників – відомостями про доходи ректорів вузів. І тут-то почалися складнощі з деклараціями за 2014 рік підвідомчих установ Міносвіти.

Швидкий аналіз показав, що тільки ректорів у цьому файлі 272 людини та їх явно треба якось згрупувати. Групувати вирішили по регіонах. Проте в декларації зазначається лише посада і назва установи.



Майже три сотні унікальних вищих навчальних закладів розшукувати руками зовсім не хотілося. Ось тут і знадобилися відкриті дані Рособрнадзора під назвою «Зведений реєстр ліцензій на здійснення освітньої діяльності». Реєстр дуже інформативний, але має досить складний формат і заслуговує окремої статті. До честі Рособрнадзора, він представлений у форматі xml замість традиційного для держорганів csv, і не містить помилок у структурі, тому його вдалося використати в якості бази даних без будь-якої попередньої обробки. (посилання станом на 16.05.2016 тимчасово не працює, тому реєстр поки можна взяти тут).

завдання
Отже, вихідна задача: витягнути з декларації про доходи дані по ректорам, визначити для них регіон і згенерувати файли xml спеціального формату для плагіна Заполнятор, через який відбувається завантаження даних на сайт Декларатора.



Плагін імітує дії користувача на сайті, автоматично заповнюючи форми. І як з'ясувалося в процесі тестування, у нього є обмеження на кількість записів, які він здатний обробити за один раз…

На вході маємо файл формату .doc, містить у собі дані про доходи 1561 чиновників. Так як нам потрібні дані не тільки чиновників, але і членів їх сімей, за фактом ми повинні обробити інформацію по 3347 людям.

Реалізація
Деталі реалізації програми декларацій дивіться на гітхабі, скажу тільки, що знадобилося багато попередньої обробки для видалення зайвих і часто несподіваних символів: @"[\r\n\a\b\u000b]", а також шаманство з транспортними засобами, досі не закінчене через таких ось випадків (це одна клітинка таблиці в MS Word):



Реєстр
Переходимо до основної задачі – матчингу назв вузів декларацій та реєстру Рособрнадзора. Її рішення з підбором регулярних виразів в результаті зайняло значно більше часу, ніж написання самого парсера. Хоча коду там вийшло набагато менше.

Записи для кожної ліцензії в реєстрі Рособрнадзора мають (у дуже скороченому вигляді) таку структуру:

<Certificate>
<RegionName>р. Москва</RegionName>
<RegionCode>77</RegionCode>
<EduOrgFullName>федеральне державне бюджетне освітня установа вищої професійної освіти «Московський державний університет дизайну і технології»</EduOrgFullName>
<EduOrgShortName>ФГБОУ ВПО «МГУДТ»</EduOrgShortName>
<ActualEducationOrganization>
<Id>58302c2c-16f2-0772-3cf1-ebacbde89ecd</Id>
<FullName>федеральне державне бюджетне освітня установа вищої професійної освіти «Московський державний університет дизайну і технології»</FullName>
<ShortName>ФГБОУ ВПО «МГУДТ»</ShortName>
<RegionName>р. Москва</RegionName>
<RegionCode>77</RegionCode>
</ActualEducationOrganization>
<ActualEducationOrganization>
...
</ActualEducationOrganization>
</Certificate>

EduOrgFullName — це відомості про ліцензії, для головної організації. У тегах ActualEducationOrganization міститься інформація про всіх установах, підпорядкованих головній організації (а їх може бути дуже багато — інститути у складі університету, філії та багато іншого). Тому рішення виглядало просто і очевидно: знайти відповідності назв з декларацій для тега FullName або ShortName реєстру і з'ясувати, який регіон їм відповідає.

Особливості реєстру: як лапок використовуються виключно «ялинки», найменування установи («федеральне державне...») в теге FullName записується повністю в нижньому регістрі.

Препроцессинг
Однак, мабуть, формат написання назв вузів у деклараціях був обмежений лише фантазією тих, хто подавав декларації. У підсумку маємо різноманітність регістрів і написань, від Федеральне державне бюджетна установа вищої освіти «Московський державний університет технологій та управління імені К. Р. Розумовського (ПКУ)» ФГАОУ ВПО «Національний дослідницький ядерний університет „МІФІ“ до ФГАОУ „ВПО БФУ ІМ.І.КАНТА“ (причому в іншому місці декларації він був записаний вже як ФГАОУ ВПО „Балтійський федеральний університет імені Іммануїла Канта“). Свій вуз я довго не могла знайти парсером. Не дивно ФГБОУ ВПО „МГУДТ“

Велика різноманітність спостерігалося в написанні лапок. В основному в деклараціях записані прямі «англійські» лапки замість звичних російських ялинок, самий вбивчий варіант для парсингу був »Санкт-Петербурзький державний електротехнічний університет «ЛЕТІ» ім. В. І. Ульянова (Леніна)" (схоже, його не подужав і парсер хабра). Двічі зустрілися екзотичні """" (Волгоград, Москва), а в Ростові додумалися до варіанту ФГБОУ ВПО <<Ростовський державний економічний університет (РІНХ)>> (між іншим, 10 примірників у декларації).

Так от, виявилося, що XPath в xml шукає дуже швидко, вміє знаходити часткові відповідності, але на жаль – тільки в повній відповідності з регістром літер. Якщо перевизначити функцію пошуку, проблема зникає, і з нею заодно зникає і швидкість.

Насамперед довелося прибрати повторювану частина — тип установи — і залишити тільки фактичне назву. І тут чекало відкриття: крім ФГБОУ (а також ФГАОУ, ФГБУ) ВПО, ДПО ПІД виявилося, що є ще закладу «інклюзивної вищої освіти», тобто ФГБОУИ… А стандартне формулювання «федеральне державне бюджетне освітня установа вищої професійної освіти» може замінюватися на «федеральне державне бюджетна установа вищої професійної освіти» — зможете знайти відмінність?

В результаті вийшла ось така конструкція на регулярних виразах:

orgname = Regex.Replace(orgname, @"(.*)(ФР(Б|А)ОУ\s)((В|Д)П?О)?", "");
orgname = Regex.Replace(orgname,
@"(федеральн[а-яе]*\s|Федеральн[а-яе]*\s)?(государственн[а-яе]*\s|Государственн[а-яе]*\s)?(.*)?(учрежден[а-яе]*\s|Учрежден[а-яе]*\s)(инклюзивн[а-яе]*\s|инклюзивн[а-яе]*\s)?(дополнит[а-яе]*\s|Дополнит[а-яе]*\s|высше[а-яе]*\s|Высше[а-яе]*\s)(профессиональн[а-яе]*\s|Профессиональн[а-яе]*\s)?(образован[а-яе]*|Образован[а-яе]*)", "");
orgname = Regex.Replace(orgname, @"(федеральн[а-яе]*\s|Федеральн[а-яе]*\s)?(государственн[а-яе]*\s|Государственн[а-яе]*\s)?(.*)?(учрежден[а-яе]*\s|Учрежден[а-яе]*\s)", ""); 

Причому порядок команд тут має велике значення. Ну і боротьба з лапками:

if (orgname.Contains("<<")) 
orgname = Regex.Replace(orgname, @"(.*<<)(.+)(>>.*)", "$2");
if (orgname.Contains('«'))
orgname = Regex.Replace(orgname, @"(.*«)(.+)(».*)", "$2");
if (orgname.Contains('“'))
orgname = Regex.Replace(orgname, @"(.*“)(.+)(".*)", "$2");

Велика проблема була з вузами, які були названі в чиюсь честь, так як:

  • могли зустрітися варіанти «їм.» та «ім'я» та в різних регістрах;
  • саме ім'я могло бути написано будь-яким варіантом в будь-якому регістрі і з будь-якою кількістю пробілів (або без них), наприклад: ІМ.І.КАНТА, імені Івана Федорова, їм. В. І. Ульянова (Леніна), ім.Н.І.Лобачевського.
Через непередбачуваність написання було простіше прибрати «імені когось» цілком:

orgname = Regex.Replace(orgname, "(імені.*)", "");
orgname = Regex.Replace(orgname, @"(ім\..*)", "");

На щастя, назва вузу при цьому не втрачало в унікальності.

І все одно залишалися «вперті» випадки, які не хотіли бути ніяким чином. Це були вузи, назви яких складалися з абревіатур: LETI, НІНХ, СТАНКИН і знову мій улюблений МГУДТ. Рішення:

Match tempmatch = Regex.Match(orgname, @"[А-ЯЕ]{2,}");
tempname = orgname.Substring(tempmatch.Index, tempmatch.Length);

Як не дивно, навіть після цього в непізнані потрапило декілька десятків вузів. Аналіз показав, що частина з них були написані з помилками, в основному із-за пропуску або перестановки літер. Лідером стала помилка «Москвоский». А в Кузбасі, судячи з капсулами bialetti, дуже люблять свій вуз, але ось грамотність у них підкачала: «Федеральне державне бюджетне освітня установа вищої професійної освіти КУЗБАССКИЙ ДЕРЖАВНИЙ ТЕХНІЧНИЙ УНІВЕРСИТЕТ ІМЕНІ Т. Ф. ГОРБАЧОВА».

Багато проблем було з пробілами:

  • у реєстрі Рособрнадзора в деяких назви трапляються здвоєні прогалини;
  • у назвах деяких внз є тире. І ці тире абсолютно по-різному могли поєднуватися з пробілами. Наприклад, у декларації прописаний «Волгодонський інженерно — технічний інститут — філія федерального державного автономного освітнього закладу вищої професійної освіти «Національний дослідницький ядерний університет „МІФІ“», в реєстрі те ж саме назва виглядає як «Волгодонський інженерно-технічний інститут...». При цьому був і такий випадок: «Федеральне державне бюджетне освітня установа вищої професійної освіти „Державний університет — навчально-науково-виробничий комплекс“».
Але кількість невпізнаних вузів чомусь не поспішала скорочуватися. І справа була зовсім несподіваною проблемі, яка в підсумку призвела до модифікації алгоритму пошуку. Виявилося, що ліцензія на освітню діяльність могла бути зареєстрована на одну назву установи, а офіційна назва вузу трохи, але відрізнялася. Наприклад, були пари «академія – університет», «інститут – університет».

У реєстрі це виглядало так:

<EduOrgFullName>федеральне державне бюджетне освітня установа вищої професійної освіти «Брянська державна інженерно-технологічна академія»</EduOrgFullName>
<EduOrgShortName>ФГБОУ ВПО «БГИТА»</EduOrgShortName>)

і
<FullName>федеральне державне бюджетне освітня установа вищої освіти «Брянський державний інженерно-технологічний університет»</FullName>
<ShortName>ФГБОУ ВО «Брянський державний інженерно-технологічний університет», ФГБОУ ВО «БГИТУ», БГИТУ</ShortName>

Причому в декларації могло бути зазначено будь-яке з них. Декілька вузів з невідомої поки причини взагалі не мали тегів FullName і ShortName.

Окремо про Крим: »федеральне державне автономне освітній заклад вищої освіти «Кримський федеральний університет імені в. І. Вернадського» взагалі не мало в реєстрі вказівки на регіон.

Остаточна на даний момент версія алгоритму парсинга видає ось такі результати.

Приклад готового файл для Заполнятора (внз для р. Москва).

Трохи статистики
У декларації подведов Міносвіти 1561 працівників організацій, разом з членами їх сімей 3347 осіб, у файлі 770 сторінок, несподівано 32 таблиці.

272 ректора, тобто понад 272 унікальних вузів, з них 8 вузів написані з помилками чи помилками.

4 внз взагалі не значаться в реєстрі Рособрнадзора. Це:

  • Федеральне державне бюджетне освітня установа вищої освіти «Арктичний державний інститут культури і мистецтв»;
  • Федеральне державне бюджетне освітня установа додаткової професійної освіти «Державний інститут нових форм навчання»;
  • Федеральне державне бюджетне освітня установа додаткової професійної освіти «Інститут безперервної освіти дорослих»;
  • Федеральне державне бюджетне освітня установа додаткової професійної освіти «Новомосковський інститут підвищення кваліфікації керівних працівників і фахівців хімічної промисловості».

На закінчення ще раз посилання на проект. Парсер буде працювати і на деклараціях інших держорганів, створених за тим же шаблоном.

Корисні посилання
НПА:
Указ Президента Російської Федерації від 8 липня 2013 р. № 613 «Питання протидії корупції», 6 ст. про обов'язки Міністерства праці та соціального захисту.

Указ Президента Російської Федерації від 8 липня 2013 р. № 613 «Питання протидії корупції», Порядок розміщення відомостей про доходи, витрати, про майно і зобов'язання майнового характеру окремих категорій осіб і членів їх сімей на офіційних сайтах федеральних державних органів, органів державної влади суб'єктів Російської Федерації і організацій і надання цих відомостей загальноросійським засобам масової інформації для опублікування про обов'язки Міністерства праці та соціального захисту, п. 4 «Відомості про доходи, витрати, про майно і зобов'язання майнового характеру… щорічно оновлюються протягом 14 робочих днів з дня закінчення строку, встановленого для їх подання».

Указ Президента Російської Федерації від 8 липня 2013 р. № 613 «Питання протидії корупції», Стаття 8. Обов'язок подавати відомості про доходи, про майно і зобов'язання майнового характеру.

Всі НПА антикорупційного законодавства.

НПА Мінпраці

Програмування:

Сервіс перевірки регулярних виразів
Хелп за регулярними виразами в C#
Класи знаків регулярних виразів для C#, а також проект з простою реалізацією безрегистрового пошуку по xml: посилання.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.