Время прочтения: 3 мин.
Для выполнения задачи по поиску закупок, проведенных с ограничением конкуренции нужно было проанализировать порядка 4 тыс. технических заданий, размещенных на сайте Zakupki.gov. Понятно, что за короткий период времени просмотреть такое количество файлов невозможно. Мы нашли способ как это сделать максимально быстро и без значительных трудозатрат.
Изначально, мы определились какие условия в технических заданиях при проведении закупок могут ограничивать конкуренцию и спровоцировать жалобы участников, заявки которых были необоснованно отклонены, в ФАС.
Подбор слов триггеров осуществляется с помощью библиотеки pymorphy2, которая является морфологическим анализатором русского языка для обработки текста в NLP задачах. Стояла задача максимально четко их определить, чтобы, после выгрузки методом Web-scraping и отбором слов-триггеров, в отклонения попали только интересующие нас закупки. Это была наиболее трудоемкая процедура, так как пришлось проанализировать Базу решений ФАС, чтобы сопоставить список слов-триггеров, которые несопоставимы и являются конкурирующими между собой.
Массив технических заданий выгружается автоматизированным методом Web-scraping с сайта. Для того, чтобы преобразовать и распознать каждый из форматов: pdf, Excel, Word, rar, zip в текстовый документ для последующей обработки через Pymorphy2 необходимо установить ABBYY FineReader и LibreOffice, первая из которых через скрипт запускает задачу HotFolder, которая в свою очередь распознает сканы документов для возможности поиска текста в документе.
Преобразование уже распознанного текста документов в нормальную форму можно представить следующей функцией converter, функция countWords подсчитывает количество вхождений слов в тексте, текст очищается от слов, которые имеют длину меньше 4, а также от именованных слов, которые не имеют смысловой необходимости, такие как имена, адреса, даты, которые содержатся в словаре Rus_stop_words.
import pymorphy2
def del_stop_words(input, Rus_stop_words):
try:
return ' '.join([word for word in input.split() if word not in Rus_stop_words])
except AttributeError:
pass
def delete(input):
try:
return ' '.join([word for word in input.split() if len(word)>4])
except AttributeError:
pass
morph = pymorphy2.MorphAnalyzer()
def converter (sentence):
list = []
words = sentence.split()
for item in words:
list.append(morph.parse(item)[0].normal_form)
return ' '.join(list)
def countWords(a_list):
words = {}
for i in range(len(a_list)):
item = a_list[i]
count = a_list.count(item)
words[item] = count
return sorted(words.items(), key = lambda item: item[1], reverse=True)
with open('stop_rus_words.txt', 'r', encoding="utf-8-sig") as fs:
Rus_stop_words = fs.read().split(',')
fs.close()
Таким образом, с помощью функции countWords можно получить словарь из наиболее часто встречающихся слов с их частотой вхождения в конкретном документе.
resultdict={}
for text in dff['Text']:
aa=countWords(text.split())
a=dict(aa)
for key in a:
try:
resultdict[key] +=a[key]
except KeyError:
resultdict[key] =a[key]
После того, как слова с наибольшей частотой вхождения в документе отобраны, создан топ слов-триггеров, которые имеют несопоставимость внутри одного документа.
Таким образом, после преобразования данных с сайта закупок по словам триггерам сформировалась риск-ориентированная выборка. На анализ отобранных закупок экспертом было потрачено всего несколько часов, чтобы классифицировать их с признаком ограничения конкуренции. Задача выполнена за несколько часов без утомительного просмотра многочисленных технических заданий на сайте ЕИС.