|
from operator import itemgetter |
|
import re |
|
from bs4 import BeautifulSoup |
|
from termcolor import colored |
|
|
|
|
|
def get_pdf_blocks(pdf_doc): |
|
all_blocks = [] |
|
for page_num, page in enumerate(pdf_doc): |
|
page_blocks = page.get_text("blocks") |
|
page_blocks = [(round(el[0]), |
|
round(el[1]), |
|
round(el[2]), |
|
round(el[3]), |
|
el[4].strip()) for el in page_blocks if el[-1] == 0] |
|
page_blocks.sort(key=itemgetter(1, 0)) |
|
all_blocks += page_blocks |
|
all_blocks = [el[-1] for el in all_blocks] |
|
all_blocks = [ |
|
string.replace(u'\xa0', u' ') for string in all_blocks |
|
] |
|
all_blocks = [ |
|
re.sub("\s+", " ", block) for block in all_blocks |
|
] |
|
return all_blocks |
|
|
|
|
|
def get_doc_blocks(doc): |
|
paragraphs = [] |
|
for doc_para in doc.paragraphs: |
|
if doc_para.text: |
|
paragraphs.append(doc_para.text) |
|
else: |
|
soup = BeautifulSoup(doc_para._p.xml) |
|
paragraphs += [ |
|
j.strip() for j in |
|
soup.find_all("w:p")[0].text.strip().split("\n\n") |
|
if j.strip() |
|
] |
|
paragraphs = [ |
|
string.replace(u'\xa0', u' ') for string in paragraphs |
|
] |
|
paragraphs = [ |
|
re.sub("\s+", " ", block) for block in paragraphs |
|
] |
|
return paragraphs |
|
|
|
|
|
pdf_oik_regex = [ |
|
"\d+(?:\.\d{2})?%", |
|
"\d+(?:\.\d{2})? Российский рубль", |
|
"((?:не требуется)|(?:не установлены))", |
|
] |
|
|
|
|
|
def parse_pdf_oik(all_blocks, debug_print=False): |
|
oik_pdf = None |
|
check_if_3_30_present, check_if_24_22_present = False, False |
|
|
|
for i, block in enumerate(all_blocks): |
|
if "ч. 3 ст. 30" in block: |
|
check_if_3_30_present = True |
|
if "ч. 24 ст. 22" in block: |
|
check_if_24_22_present = True |
|
|
|
for string in [ |
|
'Размер обеспечения исполнения контракта', |
|
'Обеспечение исполнения контракта не требуется', |
|
"Обеспечение исполнения контракта", |
|
'Размер обеспечения исполнения', |
|
'Размер обеспечения', |
|
]: |
|
if ( |
|
not oik_pdf |
|
and re.sub("\s", '', string.lower()) in re.sub("\s", '', block.lower()) |
|
and not re.sub("\s", '', "Размер обеспечения заявки") in re.sub("\s", '', block) |
|
and not "гарантийных" in block |
|
): |
|
if debug_print: |
|
print("CAND_STRING", block) |
|
|
|
|
|
for possible_value in pdf_oik_regex: |
|
if oik_pdf := re.findall(possible_value, block): |
|
if debug_print: |
|
print("BLOCK_FOUND", block) |
|
|
|
break |
|
elif oik_pdf := re.findall(possible_value, all_blocks[i + 1]): |
|
if debug_print: |
|
print("BLOCK_FOUND", block) |
|
|
|
break |
|
elif oik_pdf := re.findall(possible_value, all_blocks[i + 2]): |
|
if debug_print: |
|
print("BLOCK_FOUND", block) |
|
|
|
break |
|
|
|
return oik_pdf, check_if_3_30_present, check_if_24_22_present |
|
|
|
|
|
oik_docx_regex = [ |
|
"(?:\d+(?:\.\d*)?|\.\d+) ?(?:процент|%)", |
|
"(?:\d+(?:\,\d*)?|\,\d+) ?(?:процент|%)", |
|
"\d{1,3} процент", |
|
"не установлен(?:ы|о)", |
|
"не устанавливается", |
|
"\d{1,3} ?%", |
|
"\d{1,3} ?\(десять\) ?процент", |
|
"\d{1,3} ?\(пять\) ?процент", |
|
"\d{1,3} ?\(тридцать\) ?процент" |
|
] |
|
|
|
ot_max_znacenia_tseni_kontracta_str = "Максимальное значение цены Контракта составляет ________________, ________________ (далее – Цена Контракта)." |
|
|
|
|
|
def parse_doc_oik(paragraphs): |
|
oik_docx = None |
|
ot_tseni_kontracta = False |
|
ot_nachalnoi_tseni_kontracta = False |
|
ot_max_znacenia_tseni_kontracta = False |
|
|
|
for i, docpara in enumerate(paragraphs): |
|
if ot_max_znacenia_tseni_kontracta_str in docpara: |
|
ot_max_znacenia_tseni_kontracta = True |
|
if any([ |
|
string in docpara.lower() for string in [ |
|
"обеспечение исполнения контракта устанавливается в размере", |
|
"обеспечение исполнения контракта в размере", |
|
"обеспечение исполнения настоящего контракта установлено в размере", |
|
"обеспечение исполнения договора устанавливается в размере", |
|
"обеспечение исполнения обязательств по настоящему контракту", |
|
"обеспечение исполнения обязательств по контракту устанавливается в размере" |
|
] |
|
]): |
|
for val in oik_docx_regex: |
|
if oik_docx := re.findall(val, docpara): |
|
print("НЕТИПОВОЙ") |
|
print(docpara.lower()) |
|
if any([ |
|
"начальной цены контракта" in docpara.lower(), |
|
"начальной (максимальной) цены контракта" in docpara.lower(), |
|
"максимального значения цены контракта" in docpara.lower(), |
|
"от начальной (макcимальной) цены контракта" in docpara.lower(), |
|
"начальной" in docpara.lower(), |
|
"от максимального значения цены контракта" in docpara.lower() |
|
]): |
|
ot_nachalnoi_tseni_kontracta = True |
|
elif any([ |
|
"цены контракта" in docpara.lower(), |
|
"цены договора" in docpara.lower() |
|
]): |
|
ot_tseni_kontracta = True |
|
break |
|
break |
|
elif "Обеспечение исполнения Контракта" == docpara: |
|
print(f"{paragraphs[i+1].lower() = }") |
|
for val in oik_docx_regex: |
|
if oik_docx := re.findall(val, paragraphs[i + 1]): |
|
if any([ |
|
string in paragraphs[i + 1].lower() for string in [ |
|
"начальной цены контракта", |
|
"начальной (максимальной) цены контракта", |
|
"максимального значения цены контракта" |
|
"начальной", |
|
"от начальной (макcимальной) цены контракта", |
|
"от максимального значения цены контракта" |
|
|
|
] |
|
]): |
|
ot_nachalnoi_tseni_kontracta = True |
|
elif "цены контракта" in paragraphs[i + 1].lower() or \ |
|
"цены договора" in paragraphs[i + 1].lower(): |
|
ot_tseni_kontracta = True |
|
break |
|
break |
|
|
|
return ( |
|
oik_docx, ot_tseni_kontracta, |
|
ot_nachalnoi_tseni_kontracta, |
|
ot_max_znacenia_tseni_kontracta |
|
) |
|
|
|
|
|
fits = [ |
|
"\d{2} дней", |
|
"\d{2} \(пятнадцати\) дней" |
|
] |
|
|
|
variants = [ |
|
"возвращаются поставщику при условии надлежащего выполнения поставщиком своих обязательств по контракту в течение", |
|
"возвращаются исполнителю при условии надлежащего выполнения исполнителем своих обязательств по контракту в течение", |
|
"возвращаются подрядчику при условии надлежащего выполнения подрядчиком своих обязательств по контракту в течение", |
|
"возвращаются поставщику в течение", |
|
"в случае оказания услуги субъектом малого предпринимательства -", |
|
"возврат обеспечения осуществляется заказчиком после подписания заключительного универсального передаточного документа в течение", |
|
"возвращаются поставщику при условии надлежащего выполнения поставщиком своих обязательств по договору по заявлению поставщика в течение", |
|
"возвращаются лицензиару в течение", |
|
"возврат обеспечения осуществляется заказчиком в течение", |
|
"возвращаются исполнителю в срок", |
|
"возвращаются исполнителю в течение" |
|
] |
|
|
|
|
|
def parse_doc_days(paragraphs): |
|
days_docx = None |
|
for i, docpara in enumerate(paragraphs): |
|
if any([ |
|
variant in docpara.lower() for variant in variants |
|
]): |
|
for val in fits: |
|
if days_docx := re.findall(val, docpara): |
|
break |
|
pass |
|
if days_docx: |
|
|
|
days_docx = days_docx[0] |
|
for possible_repl in [" (пятнадцати) дней", "дней"]: |
|
days_docx = days_docx.replace(possible_repl, "").strip() |
|
|
|
days_docx = int(days_docx) |
|
|
|
return days_docx |
|
|
|
|
|
price_rub_regex = [ |
|
"\d+(?:\.\d{2})? руб.", |
|
"\d+(?:\.\d{2})? рублей", |
|
"\d+(?:\,\d{2})? рублей", |
|
"\d+(?:\,\d{2})? руб", |
|
"\d+(?:\.\d{2})? Российский рубль", |
|
"((?:\d{1,3})(?:(?:\s\d{1,3})+)),(\d\d)", |
|
"((?:\d{1,3})(?:(?:.\d{1,3})+))\.(\d\d)" |
|
] |
|
|
|
|
|
def check_percent_before_price(paragraphs): |
|
for i, docpara in enumerate(paragraphs): |
|
if any([ |
|
re.sub("\s", '', string) in re.sub("\s", '', docpara.lower()) |
|
for string in [ |
|
'от цены контракта', |
|
'от начальной (максимальной) цены контракта' |
|
] |
|
]): |
|
for rub_re in price_rub_regex: |
|
if re.findall(rub_re, docpara): |
|
if temp := re.search(rub_re, docpara): |
|
if docpara.find("%") != -1 and docpara.find("%") < temp.span()[0]: |
|
print(colored("Ошибка, указана цена после %!!!", 'red')) |
|
print(f"\t{docpara = }") |
|
print("-"*50) |
|
return True |
|
return False |
|
|
|
|
|
rub_regex = [ |
|
"\d+(?:\.\d{2})? руб.", |
|
"\d+(?:\.\d{2})? рублей", |
|
"\d+(?:\,\d{2})? рублей", |
|
"\d+(?:\,\d{2})? руб", |
|
"\d+(?:\.\d{2})? Российский рубль" |
|
] |
|
|
|
|
|
def get_mck(all_blocks,debug_print=False): |
|
MCK = [] |
|
for i, block in enumerate(all_blocks): |
|
if re.sub("\s", '', 'Начальная (максимальная) цена контракта') \ |
|
in re.sub("\s", '', block): |
|
if debug_print: |
|
print("MCK_TEXT", all_blocks[i+1]) |
|
print("MCK_TEXT", block) |
|
print("-"*70) |
|
for rub_re in rub_regex: |
|
MCK += re.findall(rub_re, all_blocks[i+1]) |
|
MCK += re.findall(rub_re, block) |
|
|
|
elif re.sub("\s", '', 'Максимальное значение цены контракта') \ |
|
in re.sub("\s", '', block): |
|
for rub_re in rub_regex: |
|
if debug_print: |
|
print("MCK_TEXT", all_blocks[i+1]) |
|
print("MCK_TEXT", block) |
|
print("-"*70) |
|
MCK += re.findall(rub_re, all_blocks[i+1]) |
|
MCK += re.findall(rub_re, block) |
|
return [ |
|
float(re.sub("[а-яА-Я]", '', el).replace(",", ".").strip()) |
|
for el in MCK |
|
] |
|
|