From 15cbdceb7f18807932cf7eeb98bf9a9307391135 Mon Sep 17 00:00:00 2001 From: jze9 Date: Mon, 9 Jun 2025 00:35:39 +0500 Subject: [PATCH] final --- .gitignore | 1 + algam.py | 268 +++++++++++++++++++++++++++++++++++++++++++++++++ algam1.py | 83 +++++++++++++++ favicon.ico | Bin 0 -> 99678 bytes main.py | 110 +++++++------------- main.spec | 39 +++++++ main1.py | 181 --------------------------------- pyproject.toml | 1 + ui.py | 0 uv.lock | 23 +++++ 10 files changed, 450 insertions(+), 256 deletions(-) create mode 100644 algam.py create mode 100644 algam1.py create mode 100644 favicon.ico create mode 100644 main.spec delete mode 100644 main1.py create mode 100644 ui.py diff --git a/.gitignore b/.gitignore index 3d65323..61adbfe 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ test # Virtual environments .venv +.32-bit diff --git a/algam.py b/algam.py new file mode 100644 index 0000000..5331f10 --- /dev/null +++ b/algam.py @@ -0,0 +1,268 @@ +from lxml import etree +from difflib import SequenceMatcher +import openpyxl +import os +import datetime + +class xlsx_filer(): + + def save_file(self): + if os.path.isfile(self.path): + try: + self.workbook.save(self.path) + except PermissionError: + return False + else: + current_datetime = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + file_name = f"/xml_{current_datetime}.xlsx" + self.workbook.save(self.path + file_name) + + self.workbook.close() + + def update_data(self): + self.sheet.cell(row=1, column=1).value = "№ п/п" + self.sheet.cell(row=1, column=2).value = "Раздел КПТР" + self.sheet.cell(row=1, column=3).value = "Кадастровый номер" + self.sheet.cell(row=1, column=4).value = "Кадастровый квартал" + self.sheet.cell(row=1, column=5).value = "Вид объекта" + self.sheet.cell(row=1, column=6).value = "Площадь ЗУ" + self.sheet.cell(row=1, column=7).value = "Погрешность определения площади" + self.sheet.cell(row=1, column=8).value = "Наличие координат" + self.sheet.cell(row=1, column=9).value = "Пояснения" + row = self.sheet.max_row+1 + for object in self.data: + self.sheet.cell(row=row, column=1).value = row-1 + self.sheet.cell(row=row, column=2).value = object.section_KPTR + self.sheet.cell(row=row, column=3).value = object.cadastral_number + self.sheet.cell(row=row, column=4).value = object.cadastral_quarter + self.sheet.cell(row=row, column=5).value = object.object_type + self.sheet.cell(row=row, column=6).value = object.land_plot_area + self.sheet.cell(row=row, column=7).value = object.error_in_determining_area + self.sheet.cell(row=row, column=8).value = object.availability_coordinates + self.sheet.cell(row=row, column=9).value = object.explanations + row += 1 + + def __init__(self,data=[], path=""): + self.data = data + self.path = path + if os.path.isdir(path): + self.workbook = openpyxl.Workbook() + self.sheet = self.workbook.create_sheet("Новый лист") + + +class Data_farame(): + def __init__(self,section_KPTR,cadastral_number,cadastral_quarter,object_type,land_plot_area,error_in_determining_area,availability_coordinates,explanations): + self.section_KPTR = section_KPTR #Раздел КПТР + self.cadastral_number = cadastral_number #Кадастровый номер + self.cadastral_quarter = cadastral_quarter #Кадастровый квартал + self.object_type = object_type #Вид объекта + self.land_plot_area = land_plot_area #Площадь ЗУ + self.error_in_determining_area = error_in_determining_area #Погрешность определения площади + self.availability_coordinates = availability_coordinates #наличие координат + self.explanations = explanations #Пояснения + + +class super_visor(): + + def find_best_match(self,input_str: str) -> str: + keywords = { + "FormParcels":"Образование ЗУ", + "SpecifyParcels":"Уточнение ЗУ", + "CadastralErrorsParcels":"Исправление ЗУ", + "ExistObjectsRealty":"Уточнение ОКС", + "CadastralErrorsOKS":"Исправление ОКС" + } + + # Сравниваем коэффициент схожести (0.0 - 1.0) строки с каждым ключевым словом + best_match = max(keywords, key=lambda word: SequenceMatcher(None, input_str, word.lower()).ratio()) + return keywords[best_match] + + def chec_kad_number(self,atrebut): + if '@attributes' in atrebut: + if 'CadastralNumber' in atrebut['@attributes']: + return atrebut['@attributes']['CadastralNumber'] + if 'Definition' in atrebut['@attributes']: + return atrebut['@attributes']['Definition'] + if 'CadastralNumber' in atrebut: + if '#text' in atrebut['CadastralNumber'][0]: + return atrebut['CadastralNumber'][0]['#text'] + return "нет" + + def get_cad_block(self,cad_block): + temp = "" + for item in cad_block: + temp += f"{item['#text']}, " + return temp + + def chec_cad_block(self, atrebut): + if 'CadastralBlocks' in atrebut: + if 'CadastralBlock' in atrebut['CadastralBlocks'][0]: + return self.get_cad_block(atrebut['CadastralBlocks'][0]['CadastralBlock']) + if 'CadastralBlock' in atrebut: + return atrebut['CadastralBlock'][0]['#text'] + return "нет" + + def get_object_type(self,type:str): + if type == "002001002000": + return "Здание" + if type == "002001004000": + return "Сооружение" + if type == "002001005000": + return "Объект" + + def chec_object_type(self, atrebut): + if 'ObjectType' in atrebut: + return self.get_object_type(atrebut['ObjectType'][0]['#text']) + return "нет" + + def chec_area(self,atrebut): + if "Area" in atrebut: + if "Area" in atrebut['Area'][0]: + if '#text' in atrebut['Area'][0]['Area'][0]: + return atrebut['Area'][0]['Area'][0]['#text'] + return "нет" + + def chec_inaccuracy(self, atrebut): + if "Area" in atrebut: + if "Inaccuracy" in atrebut['Area'][0]: + if '#text' in atrebut['Area'][0]['Inaccuracy'][0]: + return atrebut['Area'][0]['Inaccuracy'][0]['#text'] + return "нет" + + def chec_koordinat(self,atrebut): + if 'EntitySpatial' in atrebut: + if 'SpatialElement' in atrebut['EntitySpatial'][0]: + return "да" + else: + return "нет" + else: + return "нет" + + def chec_explanations(self,atrebut): + if 'Explanations' in atrebut: + return atrebut['Explanations'][0]['#text'] + if 'Explanation' in atrebut: + return atrebut['Explanation'][0]['#text'] + return "нет" + + def chec_object(self, atrebut): + if '@attributes' in atrebut: + if 'CadastralNumber' in atrebut['@attributes']: + return True + if 'Definition' in atrebut['@attributes']: + return True + if 'CadastralNumber' in atrebut: + if '#text' in atrebut['CadastralNumber'][0]: + return True + return False + + def return_data(self): + return self.data + + def __init__(self, xml): + self.data = [] + i = 0 + for section_name, section_data in xml.get('Package', [{}])[0].items(): + for group in section_data: + if isinstance(group, dict): + for item_type, item_list in group.items(): + for obj in item_list: + if isinstance(obj, dict): + if self.chec_object(obj): + self.data.append( + Data_farame( + section_KPTR=self.find_best_match(section_name), + cadastral_number=self.chec_kad_number(obj), + cadastral_quarter=self.chec_cad_block(obj), + object_type=self.chec_object_type(obj), + land_plot_area=self.chec_area(obj), + error_in_determining_area=self.chec_inaccuracy(obj), + availability_coordinates=self.chec_koordinat(obj), + explanations=self.chec_explanations(obj) + ) + ) + i += 1 + if i == 785: + pass + else: + for inner_key, inner_items in obj.items(): + for real_obj in inner_items: + if isinstance(real_obj, dict): + if self.chec_object(real_obj): + self.data.append( + Data_farame( + section_KPTR=self.find_best_match(section_name), + cadastral_number=self.chec_kad_number(real_obj), + cadastral_quarter=self.chec_cad_block(real_obj), + object_type=self.chec_object_type(real_obj), + land_plot_area=self.chec_area(real_obj), + error_in_determining_area=self.chec_inaccuracy(real_obj), + availability_coordinates=self.chec_koordinat(real_obj), + explanations=self.chec_explanations(real_obj) + ) + ) + else: + for inner_key, inner_items in obj.items(): + for real_obj_real in inner_items: + for real_wtf in real_obj_real: + + test_item = real_obj_real[real_wtf][0] + if self.chec_object(test_item): + self.data.append( + Data_farame( + section_KPTR=self.find_best_match(real_wtf), + cadastral_number=self.chec_kad_number(test_item), + cadastral_quarter=self.chec_cad_block(test_item), + object_type=self.chec_object_type(test_item), + land_plot_area=self.chec_area(test_item), + error_in_determining_area=self.chec_inaccuracy(test_item), + availability_coordinates=self.chec_koordinat(test_item), + explanations=self.chec_explanations(test_item) + ) + ) + i += 1 + if i == 785: + pass + pass + + + + + +class Parser(): + + def lxml_to_dict(self, element): + result = {} + + # Обрабатываем атрибуты (если есть) + if element.attrib: + result["@attributes"] = element.attrib + + # Обрабатываем текстовое содержимое (если есть) + if element.text and element.text.strip(): + result["#text"] = element.text.strip() + + # Группируем все дочерние элементы в списки + children_by_tag = {} + for child in element: + child_tag = child.tag + if child_tag not in children_by_tag: + children_by_tag[child_tag] = [] + children_by_tag[child_tag].append(self.lxml_to_dict(child)) + + # Добавляем в результат (всегда списками) + for tag, children in children_by_tag.items(): + result[tag] = children # Всегда массив, даже если элемент один + + return result + + def __init__(self, dir_xml=[], save_dir=""): + xlsx_file = xlsx_filer(path=save_dir) + for item in dir_xml: + tree = etree.parse(item) + temp = self.lxml_to_dict(tree.getroot()) + new_data = super_visor(temp) + xlsx_file.data = new_data.return_data() + xlsx_file.path = save_dir + xlsx_file.update_data() + xlsx_file.save_file() diff --git a/algam1.py b/algam1.py new file mode 100644 index 0000000..65abcea --- /dev/null +++ b/algam1.py @@ -0,0 +1,83 @@ +import os +import xml.etree.ElementTree as ET +import pandas as pd +from pathlib import Path + +# === 🔧 НАСТРОЙКИ (меняйте под себя) === +FOLDER_WITH_XMLS = r"C:\Users\jze9\Documents\work\git\kadastr12\test" # Папка с XML-файлами +OUTPUT_XLSX_FILE = r"C:\Users\jze9\Documents\work\git\kadastr12\result.xlsx" # Куда сохранить результат + +# === ⛏ ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ === +def extract_text(elem, tag): + node = elem.find(f".//{tag}") + return node.text.strip() if node is not None and node.text else "" + +def has_spatial(elem): + return elem.find(".//SpatialElement") is not None + +def collect_explanations(elem): + return " ".join(e.text.strip() for e in elem.findall(".//Explanation") if e.text and e.text.strip()) + +def process_section(tree, tag, label, records, is_zemel=True): + section = tree.find(f".//{tag}") + if section is None: + return + subtag = next(iter(section), None) + if subtag is None: + return + for item in section.findall(f".//{subtag.tag}"): + rec = { + "Раздел КПТР": label, + "Кадастровый номер": extract_text(item, "CadastralNumber"), + "Кадастровый квартал": extract_text(item, "CadastralBlock"), + "Вид объекта": extract_text(item, "ObjectType"), + "Площадь ЗУ": extract_text(item.find("Area") or item, "Area") if is_zemel else "", + "Погрешность определения площади": extract_text(item.find("Area") or item, "Inaccuracy") if is_zemel else "", + "наличие координат": "да" if has_spatial(item) else "нет", + "Пояснения": collect_explanations(item), + } + records.append(rec) + +# === 🚀 ОСНОВНОЙ КОД === +def main(): + records = [] + for file in os.listdir(FOLDER_WITH_XMLS): + if not file.lower().endswith(".xml"): + continue + xml_path = os.path.join(FOLDER_WITH_XMLS, file) + try: + tree = ET.parse(xml_path) + except ET.ParseError as e: + print(f"❌ Ошибка в файле {file}: {e}") + continue + + root = tree.getroot() + process_section(root, "FormParcels", "Образование ЗУ", records) + process_section(root, "SpecifyParcels", "Уточнение ЗУ", records) + process_section(root, "CadastralErrorsParcels", "Исправление ЗУ", records) + process_section(root, "ExistNewObjectsRealty", "Уточнение ОКС", records, is_zemel=False) + process_section(root, "CadastralErrorsOKS", "Исправление ОКС", records, is_zemel=False) + + if not records: + print("⚠️ Нет данных для экспорта.") + return + + for i, rec in enumerate(records, 1): + rec["№ п/п"] = i + + df = pd.DataFrame(records, columns=[ + "№ п/п", + "Раздел КПТР", + "Кадастровый номер", + "Кадастровый квартал", + "Вид объекта", + "Площадь ЗУ", + "Погрешность определения площади", + "наличие координат", + "Пояснения", + ]) + df.to_excel(OUTPUT_XLSX_FILE, index=False) + print(f"✔️ Файл успешно сохранён: {OUTPUT_XLSX_FILE}") + +if __name__ == "__main__": + main() diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..5d0983165ebc51db3b57cb22a00042bc0e5e7bc2 GIT binary patch literal 99678 zcmeI52b`Q$xwvQ9kWfMbNQn^G(BUEoC`FVcQUs(Zhy_F-pcDl}uL{yKLMS4Nz_lPn zNI*bEdXu(D2k9V+KsI!gvH`>u!p{GBX6LLY=l{*_%78LhiDtr|z^$-8d<}jIi^2Ec6!>w%$)vvmTSBP+N8;zh zIiOxGa3LHE>Kmg?r-J<~2=@OYI0(KBhru{F9gYUaCgupz*8LVN0HOYY#I65*7!B&N zB3Ncb3H3GpUDz0uw7&f>57)pxkjm<0+z30B9%R*LhU9($>Sqh_#>BMM<)ExRJCtP|X4CctEH|0>Gjnfr|E&3V`c|Ax2V z?S95S?CTx)Drl8{aDSRqVqz2zdG!iELEDGIyYP2#K0CLAG!b#Xi1Wg;dWFvG|3C-q zoHV*D=|8~6rF?a99{&z5t^&*N2~LqiAhbucxUTHK0N*krk}Zh82A?kFEkgLe@PBYx z67HQFa4( z1ik@5;{LZK(>eE7_zWx$asS%?1UN?8QZ4rVCg{H))$~7-N}dtlg5ANpMx|K(X!s6j zV~}e4cmBEVriIE?go{zu^Um`&mTLO9-htr!b8b{4pQrE(;29W8HT^sOKLgilHDjRd z*Ma*?Joiaqy^8pA_P5(<%={}eW-vHO?s-Ub0H^IyB3s?vg*YPaa3Y>pu!vYYb zn*ObGFgW%fhkM~7I0$|X?u|#mi*OvchusDCsSnh{da+d7zk9d)?vdaa%z?+jedQmJ-2-g%B*?03 zJLVq;?}6iZ9xMXN0`OgE2YukWN_m33f5IKG0^9%vI1$!`SD+0nm(~qw+tyb*foH^J z@Ete@UI6F0_Bhrl%aXT0*oI@}cw7N%m*Q=N6QNxF(4OZ(Q>p9)gm;7E`gtffZ+TRd z<@oQt;F?(zZ1dxwO}~cT>QiJc(f^}i!MSpKPPniA4W5Sw!1;I`tOx@o&hy*hAZP>q zGLYijy&2pK+ynN5fs_;I%=PvbxMo~mRm-?SVa_J`+-S*VaY|u)?k+f?bA0aD&e6GJ zPad87!HChhR`x1s%YC9q`(8()#gP*_IG+VsyrfOjoTkEEoy~ATz zYUXzeN)-2otq5;`4sgvk0xzSd>wFJ*3EqdN;8wV45Tkx?f@8cTya=8xhr$ZrnYGX$ zWfXe3Pd^Cie^n{`KB2y71aawj&a3}y@JwC>vc&y+2iP1^`^J*jQfHQ+y&#JciPIrJ z)?XVQh9$$pBpgrr8MqS`i=L_bCE%I-T%EA3YhWo*egy8}<4i=7>hJik7Cn!nlSupv zJO`~8#546*pzY4ZdSF|gd!e7hiC+Z49->7__3tG2XmGB?qW{hVeU$2NxdlO=jHwg0 zH4=iTkA0+)>aTvYVH$YX@_w};oDKhhEd6bFH~1l(SVwFx;9Ykga4(D{)!)7JWzY}* zfG6RNQo4=Mb37e?*M(<=w)H2TOKU!it3D^nadb+O-_GR$SBdz_xq`Xa(m%HTr*# z^6GyODCP8T;n^&3Zao6}u%0+BZ^Nt5ANr4_-HTx+=%0GiMw{Y$OK(C8cRXYhW07--L#kov&qhr?xX9C-IjCN^RT;J_7nt`>c05IQCb-`>-cuNxk%6gvOl{j_qF10{Xzd-vswS z?NhghzaP!izxN=%61Z>s9=9Rb*PY;4{}$Y%^wA2iD*PQR zy8&zs`pfdJ`EpWE{q181aExyQ*V|NZOiu&l3-COc=iEO4l(1fYN!+pj12`A=fu5w^ z`uo0g6*%u*qbtKR5au+|;-3C_!jFJ^(ggS`XpebYfj+t$mWH0B-ul~@=b3xnt)LH% z0mu8N&;+R*MuyLS1&;miOX;r>_9m6+e_*MR6$zh%hroK}L>;aM*XFL^+@1+9!nzPk z3yHsgYhgp!0^F-gLXp^Rfc4l0#Y|A(pgfl}oU6M7%{pHg}iLia(-7+(t9 z-^#Hh&-Mf7$eZANS5}8p!M#%12y9myJhQD=uFW{#{#S)Zz`FYO6<7zdK`dIheQuuSiMIe@CNn8WY)i!vl zLY&{WeFeA=>Mu#97MBm4{W@iNd`+wpUC344s|%QfUUzYA}Jea(TZVGXE8 z7N+o(U>gUNDt>@)R~TPPe~wVyy)P_T%IiyDy9dF=a6Oz0yTcMti#Volz(2rt9j^sJ zJNAH?;2ho)>M5?Pk>Ebp7qOiK;dO9s{uNr`QRo1DoQF{`SjDw_BDjX$0&SUHN_)0B zPJ>;(i-PKZ46FjqCDW%sBS_Hy2$c2Q{3@vbPoWXyJ1D8XufkLCaw+{2!bXtoQ1S(E z-oIH2|4BFn`Yib}EsW)tL}s7l zCpVRFcA+aQ6gqPS(u`tLPvM%hIT`ZM{W~o(GXC8vCAwuTVyD8h;F<0G9?Cq1eTrkh z6Fd&{gWbWW+Nx-~_Yw2Gd)y3DVLxzR9!l(uJ>IXw7~}3`zxnULGw@f??oehnaqkJ`>|dT| zPnMpC_UBc26?&BWj+2jc47Qy?o_>BFLSE3_v2kAP3A4cbJft##jPU$v;(vr229O)+ z%R8+4-3$vumgLC{wgp?wQ`}F!34RN(jQW2P+*ekFHmJn@A5hNq;GJQhScJY@dwsE= z>cw^M+_xRi(;(H@KaEP>OGXbMW9iHFKN#$P7Cml=iR|~0so%VljM2WU-ti`)V61l??VG6+V0)tdGHMDN%B1GFZ;va zHPpqmFc9K6-wN9FD0mO+N%B1GFZ)-b?XY*;MBFo}za{uyn+~g>vpi+`%YM7}9%=g> z@I~lP@o#6hfc?#cRiQV@Q^4|4@BPpBChv@)edA-GzhqY$cAV|c_me5mo8&1F^sA@+ zo`0uDZQF<6*LH#a5Z9LbY_P@9dzbI5JxQL2p-w&R{~y}*Z;H0C`2ejTCThUzU} zph3s?eQ+FJ2m3w=dXhX3`@??My1J;7-w=)g`|*8xC#a`5p4WrzKLsBK-+4{n0=^5C zlROVBC-wCIex)|`!@96K%q-0L}~FJDa8C&Pz?H<+GZpWv-v;-NuzuV#)`BegESZj{{dm?YJ3`1iyqHt|KY1SYhy6{o z>)vDAelv0pP~yDpyRzo`?>3}ngY}#{j)C!uA@!r<=Q#Sj4ICrO_`YY}Oei;QJSs|_ z|5{e+x&CRc_tEazJK5V*E3g*cC7uac*Pb)-M+r`h6tGv0?bkf#u5v7x*A6GZ zEv58K!j(YT1{_Pvxt0|3g6~fzUWxCmmj~OC{<41o+CH_^$85r_K*`G6ko>S-f?kF{ zg=TP^eh=n3rmio?)3s%ub}7uTC4lOQrrUB-E~tM0vj)*9q@Eru}~I{nz-fKymFj ze&)HRYVkeQdiB3$vZOEeYwsDL?%J#^`@vgap1ckE^;HPAn|~v$3Fm`p*NtncR>@N_ z^qJ*e4M99Z|LD8HI$JO}*Nv42!~dE$q|4&WSA%)1AIzV4ZQ@jcaZc?j)=JLH)@ zh{Q2i1cDwu`WVax>)r|{gY&jheoR^KFwcW+JOrM#ihJ!eF#oTx9)vk@a4BD3T?y6p z8|!D?J4@}^SBU?GcnkC-&JpX>3-1Ds@1igR-T~Wo%|8QMgR&X8H`c4)(2i$}V{2&M z>7XuIvJIK;&6ab&a=f0Xfxl5F*m(|dWl4zVxP7?)PXWa>6Xx9u#B1$4*4O>_6j%zb z2K#gzri1;t2RbKLf;mqKeHHJ5-eK&c6`W&A6S)3@U)<-v0b#xL<<3Vl zy~;wA_&6L1u7eA~z4MFU+^Ls1fAq2YoMUi1YzK>jHjjeU;CKlB@Jv`621@irU*~yG zy1M5%-@+KYMf^Uv4E_kuLU=ZdxZ^X_M1Onc#A_{$Kh5(=L(TBWo*jw1zqr5O2{*y@ z@FF-C*TF~_suJw)z(DU9?tPw#SHb*d|5n(nI0o~Z{m%bu!1qJ%h3J6dM7 z5w6!UHiWl!<&XM-+Zg|g2u(h3DusO8E2eWDi$OGY7 zrgO*mDTUVDgaYG5*i`U&TL@QdE~eY35RTs~mz$iY$F^MY>%^#50@8~4dCE-T{|!&; zs6xlegjm^;!#Q*Kzg$Z}>C8G&{@upEhY!op8G&;CKM@mS-y6RZ{2j=!44n}u=l?%pV(R}R>TI_6&#_=QEc0dr z%K85V)QSE7FVb7oQAOW7&V+lwcZ^k`7HOi=0z(k(s#K~eo3>fb|LHdYzwdk~tz2W; z?*r2zo?kOa`#Y#g#rICXJDdaO4?)hrrZ2)mP)_^}<;mdh;t5z!Yzdz8} zwA#kYl;4Vc=XUI~YW%+hb?-{*$88Oz_;0Xt1f;SP8UFYtw)K#-PzC8q{qKHoKn3kp zQsig~#d;gB#{c%QD|jY(2DlD}8rtO^HxaVL`_FXnp7t*In=*Y_typIkr2gp4$h(p} z|Gv`~S(?gOYqwhedk63w`2y@d1aW<@3_XeO&Rf8?;F(y9RO5etv;WyzI*IChgZO)p z&bMm)A2m4~?ZXIE<9~hTZ$P|z)*{{?o`KZ&ricAs%ZT>9PPP8mSN>Lil`6a5kn;X} zpDf=G`@hP;tYh(7{I9<}!?%V}z38$S&pn@?gmS*G#s3S^-b6SEzB8Y*7xqtpTBKJ0 z>$7&a0K9{FCiwfGF|Z7HH`@pNH!kl$Prk3k|Gta7Q9--C^*a=vcQOul!x~Vn^u_;S z?0o-t4juycg~#A!@Es@KTe=1{AtyJoN$NP)mzx&8~f2(9HJqJ85wgl%uT&EiU`*#TUo4EdP z{J;Nuc??a(QjPyxXmv?A5FP}7|69qp`>pp@@SEMjumZF}T(__O_b&2F_z|2u#5oE3 zZi0CHjGqS8O11tE?T;h!1vm>li_^K_+3)+_PvO(BI0Wer|35?HwmZLw?>+O<|6!b) zh^!3W`C@%uC++v1EE)EH)~HmMH(30y)*pZeAojm^#q}XehW(#4D%Ir;`+x5FHk0A= zEK?R3;%MW+5U)4m19|?dLy*C+{{7q3A7BQYKg5}ieOceq=V$+?Yhiv&pU%9fR%*Tf z$NdcS`kz4OzAw&?KJLk8-?gfhM)dy@80mNBp2lK+e0E5+&Zm4M`d>5smgF};zcai) zpX0ZeYa!f!iB>F)>i=deTpMmiNmf8X&x2mW2b@6SiTXc)?}7{(n94?rt?2KqYh8`b|G!uDAZ?s=Yp`@v8a zzxnxFi(vE9#MkPh!Hw#F&wcNHVJr;&CgR_vhN6tesD~i7*SWA`AB}BP|NDDV|HcrH zhx5VTg$+gdCPw+56Wi-=tk&zJv5o5gQP_Q9G9Hf2Jy7evg`n!7l;zOMGe7pd@$@utr}0 z-v6G@7@sg+f8v>cn{Gt${^C6**pi0Mfk|~RtWo{%ZwRyY#(13kCis;)jM2Pk!uw0s z+K=tKgEGDw_C*@i|5GtK9*c7ER?7K%fkqPVE#6YL; ze`6HJ$FKu-gGQ3QP}ciPY{$PyYhRpa{1I3lYL!OxzyIze-5XydZ(Fzy(lNS;yv3mr zWJ#3t-jdpI6?xl%-+bd|o^hXrTBQ;F|09fz$H4fRr2+8YD7xn3=l>>cej|wY6@41( z@1Ex0x|`s<pgyM{Esje2D5lixdl?)-P6XD z6yJ-m6XG(zC*2ISNTd1RZ@xD|Y`la52KVjdpjPp0cMYeyx*x>vEtWGcE%!b0 zYL!Ox|0Il^4e>a&4~zSLjr7N$R%t~4dxocX0LSD~i2p9;xBuH99xvm*KP(EBig)X8gL5oxD^5En z4+PJsN<~}TyW)0?-wfVkg1Bd01!=i!$ct?b7L(P4c`S#WICNS}tp^ zi0h>BPm%E|q+_3z{s-kgnKsZvdMBQxYubB@XG|e`?Oqm?~Th=6K_=iFO89R zKs+ACF9F{Xf-FTOt6aKQgz{td50KsmW|6ll^d{xj z^d3pY?MbI+k89uiNMEIq{qG)-^*3^T6Yl|*yAxs`8vi}G20hrZO&o=%9-dlpW_Ai6DedD*nlF(OaWdCdX*C5>kW|ODi zV#z9}pZs>_{_Z+XG2eO93Gw*rH~p$C21JgY9=i>>uM7gJ*Y;a^=!`m84ydvH!h;S5mLHGPl!?_mv>t>z$Knz1zr( z_lQuwmax(Nug&{GdIqq?n)jpc4PvN7|O@toF?RD#Wri3GXp+-ws3Q1QR_ z@%tbiFXIBGs=A}DOZo=Q1ZWP`~GCy9P1e{5`rv8 zhvWXO8$2o4ubTIeT}?{K8)mG;#uXg_5ja-)E_;ikB<5YQSTw?+IJ5+AQUKtTM%Zg z{dA8=s@0qvYW^>`w$EdP;Z6uM8kiG*tA@!qa^Y#6QA(hEw zcn^u|x%R!U#8T-V5!dN!d?@aWKmY&zj?52_j14A z>R0a)M}hsO;+``dQeC{Kc((}R9&tXT<;yU$+4^{tHy0*1H>wbSG z`6K!`!0t8YLhO6v?ib!uf>gRkg!1(ahpPV_qjGEeW61!1k8~%*e)64ulcZd=$xl$h zdq>=^Yv21xEE7povPZ;q>J=Z#{@1qjZ}a*hUE3|>JqEF#jQF#$N*O_|=H_2Hzp#w(S2q zNh7|CWbF~Yy9|`n!~bJY_6~^ceUbEMOUjWf zE3W-tLE4w^7>;!i*Z$d%mh*c=yhnuc{T0^3|LS%uILCuMml9tTvSgtBuMXdbpj!xC z+rG!gaukX1JcQ2W4N8R;Ak?l8z_?Pl2%-7P#^C)T)HQTme8-5zcaW?-!grQ|lzRDp zDU?1M{s^v@)uEis3;%n*KLN2{jQEE0+TLU2wS+7{ z1l!NrSN!fUucTi7-wXr%2J{Zhg1w-e%xnLzhGKt**iY`k9Z6nz?)}}n{Zi1AEX_mT z5whMhY|HlTC$wv5*_B~lNj?1Uo&OII+vS+KA7shA_P;v)0AhW!;`-`ZSR1O5btvq6 za8{dX-jUTb+z(~z;r}t{bw^^aXQ=yQmJ9~}ua06*LF$h(pjuS9CvPncY-XP zmL>DUuuRs&Ql58&nGm-d$B*uz?m#^%=l}N-z5Pz&nkgqs@WA_xem@C%I@8=2+#lkx zc#`yTFp#1>={-Q5oX6TyPPX8IcfHrZJK;nqCr9w06JlG9`yFCluYFV~`~UyDooBJm zzUORcg&w4dXU$;PlWfMrHz97{z0h&>JGy@iXpz^9H!4oNEJteZ38-E@zRq z0HoqxzXPP>^&EMhhNU4D*TW1*`>@}Ev^8ry?ca4CpW8vttiNMSr|g2z7a2`u@6@56 z!5HqBVc_QEx#zoYrTe+**--8*IGAUH(axT9+8dqI_hJ8D`Elrre2&UlYpy3<2J+dv z=;s=bWib-zo?lKU&w@qb%EWhpIZ&?7V9R%}m;jGt=zIlvOF=ENGL>8-gU#MppMRs@ zmWgrWNdKimy&tArdJcFtIIrS<25a1TdIl)oT~j?hD^7#4P>n24;Y%QG&vAJS+*|)V z5Ae!kgkhgdxGeg$#4a`B&0&cE@+vO9_NjP>lD7xwnl=dI{;BzVtJyaV44sjc4C z&IiAv_9hEZU?aE@(sR>xuY?uA_s1m%kkH?B`b_Qn9(k#ZC*y~37x=e;xQ^$f-@i_P zYEbL*0}te zq&Eu%8X$Bn906}ZY)7r}muTlJ;C?Z$WoZ=nGo-ehMc&9V%7wGwdY&H-A1qUD6#3^t z+V)-Kxd%6rI2L=t(~#OzY1+NOd)_vXo-<_4GdYr;QyXTJw|fs7Id>hCp6u9*=UHne z>wZDeK`+|64!HmQ6Vfp&m)7sIz_qd>3^wr|>s=<*U!7~2tB%w5@LWclkCV4DG_pAF zy|?L4_cG^#?{VR*_fGI{cph#7=llP_VA$_bBU8MOX+t^(v|%4ezv+;bDc*zkgBKxf z%lC!@V5o@m+l)MO1pPBv_TmstUxvkx?m^RU|0tC2zXB20>N+f z2ydXhH3qlY!`ek7;5t1Qyuy!RO%3V(oft{g|+ur%%nWcmNQWz6wCVA%g<2B$%@ ztMR{o9~t(4gF3p5+Qa@YGcfZ>b~XMV-v5W*q{#BW?{t0#-ZsMYxiGx{GYCUSviv^> z``*pK{9*qOA?IUCmj6>9_mm!f|7+~|aAd}s?#bWjGym>AER8z?o1(gZ|4;o|NqQFb zHf&tehc#ye{JqM~a1A_IArDaQYS3x!jnBCVuH(MnOKzEL3E*&J+YIkqe9kCl{`=DE{j%cQ&O^Sr4r zr@OsLCzR6vRRH}vP@!8|b5q;rPPd>^SNHrcCKfgQZ<_Xb)ExB7)sSw^jcmr^F43OW ziF2phGSa2l+GKg32mNYHciUI0-<`%@+b`VJrQV#WrF2Q(j+Qd%(j;gP&(m~i(zJ!= z`L6ccCY9PNO|sUIZk<{zK+vTR4-|@ZrSoaJ#m9wQsGlpPTT10~V}0C7c4_=d>9HX_ z%I9+^*7bbE-03+ZiUZI=cJcX~kzMK0-RYvi?cM27q;Dy-k1sv%Y|a(tj4HH^3+*@O z3++vXwoO91DL=I>S7=?YlrA*27So4x>)$$wiJIRlr1NdXblapZeG2)#a+4=d&M{0~ zZ;#9-n3Sf()=`Pa&BaIx?@apYwoZy zj6&D*j*(5RxkE;Gr{|1nYRhSU>G_=ITwAVfTz9&&Ip5x-`K9NbP5Hx`HNTW*0FE5h ziuoa}X__C>3_wA;(>$|GNLyF)yVL89rH}un=^Gsi-Otet9gFF9=0C0*F+%gH-+r`d z20-&kcer{x_)VJTlXm|qbd2QZV^Mm}2>z)V=7#6RUAimXVSB|D>?AC;-", lambda event: open_directory(event, xml_entry)) -def process_section(tree, tag, label, records, is_zemel=True): - section = tree.find(f".//{tag}") - if section is None: - return - subtag = next(iter(section), None) - if subtag is None: - return - for item in section.findall(f".//{subtag.tag}"): - rec = { - "Раздел КПТР": label, - "Кадастровый номер": extract_text(item, "CadastralNumber"), - "Кадастровый квартал": extract_text(item, "CadastralBlock"), - "Вид объекта": extract_text(item, "ObjectType"), - "Площадь ЗУ": extract_text(item.find("Area") or item, "Area") if is_zemel else "", - "Погрешность определения площади": extract_text(item.find("Area") or item, "Inaccuracy") if is_zemel else "", - "наличие координат": "да" if has_spatial(item) else "нет", - "Пояснения": collect_explanations(item), - } - records.append(rec) +directory_label = tk.Label(root, text="Выберите директорию для сохранения:", font=font) +directory_label.pack(anchor="w") +directory_entry = tk.Entry(root, font=font, width=70) +directory_entry.pack(anchor="w") +directory_entry.bind("", lambda event: open_directory(event, directory_entry)) -# === 🚀 ОСНОВНОЙ КОД === -def main(): - records = [] - for file in os.listdir(FOLDER_WITH_XMLS): - if not file.lower().endswith(".xml"): - continue - xml_path = os.path.join(FOLDER_WITH_XMLS, file) - try: - tree = ET.parse(xml_path) - except ET.ParseError as e: - print(f"❌ Ошибка в файле {file}: {e}") - continue +# кнопка +empty_button = tk.Button(root, text="->", command=Pars, font=font) +empty_button.pack(side="right", padx=10, pady=10) - root = tree.getroot() - process_section(root, "FormParcels", "Образование ЗУ", records) - process_section(root, "SpecifyParcels", "Уточнение ЗУ", records) - process_section(root, "CadastralErrorsParcels", "Исправление ЗУ", records) - process_section(root, "ExistNewObjectsRealty", "Уточнение ОКС", records, is_zemel=False) - process_section(root, "CadastralErrorsOKS", "Исправление ОКС", records, is_zemel=False) - - if not records: - print("⚠️ Нет данных для экспорта.") - return - - for i, rec in enumerate(records, 1): - rec["№ п/п"] = i - - df = pd.DataFrame(records, columns=[ - "№ п/п", - "Раздел КПТР", - "Кадастровый номер", - "Кадастровый квартал", - "Вид объекта", - "Площадь ЗУ", - "Погрешность определения площади", - "наличие координат", - "Пояснения", - ]) - df.to_excel(OUTPUT_XLSX_FILE, index=False) - print(f"✔️ Файл успешно сохранён: {OUTPUT_XLSX_FILE}") - -if __name__ == "__main__": - main() +root.mainloop() \ No newline at end of file diff --git a/main.spec b/main.spec new file mode 100644 index 0000000..145e5e4 --- /dev/null +++ b/main.spec @@ -0,0 +1,39 @@ +# -*- mode: python ; coding: utf-8 -*- + + +a = Analysis( + ['main.py'], + pathex=[], + binaries=[], + datas=[], + hiddenimports=[], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, + optimize=0, +) +pyz = PYZ(a.pure) + +exe = EXE( + pyz, + a.scripts, + a.binaries, + a.datas, + [], + name='main', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=False, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, + icon=['favicon.ico'], +) diff --git a/main1.py b/main1.py deleted file mode 100644 index 8d4fcea..0000000 --- a/main1.py +++ /dev/null @@ -1,181 +0,0 @@ -from lxml import etree -from difflib import SequenceMatcher - -data=[] -class Data_farame(): - def __init__(self,section_KPTR,cadastral_number,cadastral_quarter,object_type,land_plot_area,error_in_determining_area,availability_coordinates,explanations): - self.section_KPTR = section_KPTR #Раздел КПТР - self.cadastral_number = cadastral_number #Кадастровый номер - self.cadastral_quarter = cadastral_quarter #Кадастровый квартал - self.object_type = object_type #Вид объекта - self.land_plot_area = land_plot_area #Площадь ЗУ - self.error_in_determining_area = error_in_determining_area #Погрешность определения площади - self.availability_coordinates = availability_coordinates #наличие координат - self.explanations = explanations #Пояснения - - -class super_visor(): - - def find_best_match(self,input_str: str) -> str: - keywords = { - "FormParcels":"Образование ЗУ", - "SpecifyParcels":"Уточнение ЗУ", - "CadastralErrorsParcels":"Исправление ЗУ", - "ExistObjectsRealty":"Уточнение ОКС", - "CadastralErrorsOKS":"Исправление ОКС" - } - - # Сравниваем коэффициент схожести (0.0 - 1.0) строки с каждым ключевым словом - best_match = max(keywords, key=lambda word: SequenceMatcher(None, input_str, word.lower()).ratio()) - return keywords[best_match] - - def chec_kad_number(self,atrebut): - if '@attributes' in atrebut: - if 'CadastralNumber' in atrebut['@attributes']: - return atrebut['@attributes']['CadastralNumber'] - if 'CadastralNumber' in atrebut: - if '#text' in atrebut['CadastralNumber'][0]: - return atrebut['CadastralNumber'][0]['#text'] - return "нет" - - def get_cad_block(self,cad_block): - temp = "" - for item in cad_block: - temp += f"{item['#text']}, " - return temp - - def chec_cad_block(self, atrebut): - if 'CadastralBlocks' in atrebut: - if 'CadastralBlock' in atrebut['CadastralBlocks'][0]: - return self.get_cad_block(atrebut['CadastralBlocks'][0]['CadastralBlock']) - if 'CadastralBlock' in atrebut: - return atrebut['CadastralBlock'][0]['#text'] - return "нет" - - def get_object_type(self,type:str): - if type == "002001002000": - return "Здание" - if type == "002001004000": - return "Сооружение" - if type == "002001005000": - return "Объект" - - def chec_object_type(self, atrebut): - if 'ObjectType' in atrebut: - return self.get_object_type(atrebut['ObjectType'][0]['#text']) - return "нет" - - def chec_area(self,atrebut): - if "Area" in atrebut: - if "Area" in atrebut['Area'][0]: - if '#text' in atrebut['Area'][0]['Area'][0]: - return atrebut['Area'][0]['Area'][0]['#text'] - return "нет" - - def chec_inaccuracy(self, atrebut): - if "Area" in atrebut: - if "Inaccuracy" in atrebut['Area'][0]: - if '#text' in atrebut['Area'][0]['Inaccuracy'][0]: - return atrebut['Area'][0]['Inaccuracy'][0]['#text'] - return "нет" - - def chec_koordinat(self,atrebut): - if 'EntitySpatial' in atrebut: - if 'SpatialElement' in atrebut['EntitySpatial'][0]: - return "да" - else: - return "нет" - else: - return "нет" - - def chec_explanations(self,atrebut): - if 'Explanations' in atrebut: - return atrebut['Explanations'][0]['#text'] - return "нет" - - def chec_object(self, atrebut): - if '@attributes' in atrebut: - if 'CadastralNumber' in atrebut['@attributes']: - return True - if 'CadastralNumber' in atrebut: - if '#text' in atrebut['CadastralNumber'][0]: - return True - return False - - def __init__(self, xml): - i = 0 - for section_name, section_data in xml.get('Package', [{}])[0].items(): - for group in section_data: - if isinstance(group, dict): - for item_type, item_list in group.items(): - for obj in item_list: - if isinstance(obj, dict): - if self.chec_object(obj): - data.append( - Data_farame( - section_KPTR=self.find_best_match(section_name), - cadastral_number=self.chec_kad_number(obj), - cadastral_quarter=self.chec_cad_block(obj), - object_type=self.chec_object_type(obj), - land_plot_area=self.chec_area(obj), - error_in_determining_area=self.chec_inaccuracy(obj), - availability_coordinates=self.chec_koordinat(obj), - explanations=self.chec_explanations(obj) - ) - ) - - else: - for inner_key, inner_items in obj.items(): - for real_obj in inner_items: - if isinstance(real_obj, dict): - data.append( - Data_farame( - section_KPTR=self.find_best_match(section_name), - cadastral_number=self.chec_kad_number(real_obj), - cadastral_quarter=self.chec_cad_block(real_obj), - object_type=self.chec_object_type(real_obj), - land_plot_area=self.chec_area(real_obj), - error_in_determining_area=self.chec_inaccuracy(real_obj), - availability_coordinates=self.chec_koordinat(real_obj), - explanations=self.chec_explanations(real_obj) - ) - ) - - pass - - -def lxml_to_dict(element): - result = {} - - # Обрабатываем атрибуты (если есть) - if element.attrib: - result["@attributes"] = element.attrib - - # Обрабатываем текстовое содержимое (если есть) - if element.text and element.text.strip(): - result["#text"] = element.text.strip() - - # Группируем все дочерние элементы в списки - children_by_tag = {} - for child in element: - child_tag = child.tag - if child_tag not in children_by_tag: - children_by_tag[child_tag] = [] - children_by_tag[child_tag].append(lxml_to_dict(child)) - - # Добавляем в результат (всегда списками) - for tag, children in children_by_tag.items(): - result[tag] = children # Всегда массив, даже если элемент один - - return result - -#tree = etree.parse('C:/Users/jze9/Downloads/12. ХМЛ КПТР в ексель/Исходные данные/Карта-план в хмл прмиер Копейск на кк 74 30 0104002/MapPlanTerritory_EA8F3032-3AF5-4FE2-9A0D-72BCCF94DF06.xml') -#tree = etree.parse('C:/Users/jze9/Downloads/12. ХМЛ КПТР в ексель/Исходные данные/Карта-план в хмл прмиер Копейск на кк 74 30 0104002/MapPlanTerritory_54F3719F-2ED8-48FF-8442-9813191EBA51.xml') -tree = etree.parse('C:/Users/jze9/Downloads/12. ХМЛ КПТР в ексель/Исходные данные/Карта-план в хмл прмиер Копейск на кк 74 30 0104002/MapPlanTerritory_E2DF5B75-E136-48DA-BB4C-8887BA4ABF46.xml') -xml_dict = lxml_to_dict(tree.getroot()) - -temp = super_visor(xml_dict) - - -pass - diff --git a/pyproject.toml b/pyproject.toml index 9b0ce7d..e3ba135 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,4 +7,5 @@ requires-python = ">=3.12" dependencies = [ "bs4>=0.0.2", "lxml>=5.4.0", + "openpyxl>=3.1.5", ] diff --git a/ui.py b/ui.py new file mode 100644 index 0000000..e69de29 diff --git a/uv.lock b/uv.lock index f1574ec..90813bf 100644 --- a/uv.lock +++ b/uv.lock @@ -27,6 +27,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/51/bb/bf7aab772a159614954d84aa832c129624ba6c32faa559dfb200a534e50b/bs4-0.0.2-py2.py3-none-any.whl", hash = "sha256:abf8742c0805ef7f662dce4b51cca104cffe52b835238afc169142ab9b3fbccc", size = 1189, upload-time = "2024-01-17T18:15:48.613Z" }, ] +[[package]] +name = "et-xmlfile" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d3/38/af70d7ab1ae9d4da450eeec1fa3918940a5fafb9055e934af8d6eb0c2313/et_xmlfile-2.0.0.tar.gz", hash = "sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54", size = 17234, upload-time = "2024-10-25T17:25:40.039Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/8b/5fe2cc11fee489817272089c4203e679c63b570a5aaeb18d852ae3cbba6a/et_xmlfile-2.0.0-py3-none-any.whl", hash = "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa", size = 18059, upload-time = "2024-10-25T17:25:39.051Z" }, +] + [[package]] name = "lxml" version = "5.4.0" @@ -69,6 +78,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fc/14/c115516c62a7d2499781d2d3d7215218c0731b2c940753bf9f9b7b73924d/lxml-5.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:bcb7a1096b4b6b24ce1ac24d4942ad98f983cd3810f9711bcd0293f43a9d8b9f", size = 3814606, upload-time = "2025-04-23T01:47:39.028Z" }, ] +[[package]] +name = "openpyxl" +version = "3.1.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "et-xmlfile" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3d/f9/88d94a75de065ea32619465d2f77b29a0469500e99012523b91cc4141cd1/openpyxl-3.1.5.tar.gz", hash = "sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050", size = 186464, upload-time = "2024-06-28T14:03:44.161Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/da/977ded879c29cbd04de313843e76868e6e13408a94ed6b987245dc7c8506/openpyxl-3.1.5-py2.py3-none-any.whl", hash = "sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2", size = 250910, upload-time = "2024-06-28T14:03:41.161Z" }, +] + [[package]] name = "soupsieve" version = "2.7" @@ -85,12 +106,14 @@ source = { virtual = "." } dependencies = [ { name = "bs4" }, { name = "lxml" }, + { name = "openpyxl" }, ] [package.metadata] requires-dist = [ { name = "bs4", specifier = ">=0.0.2" }, { name = "lxml", specifier = ">=5.4.0" }, + { name = "openpyxl", specifier = ">=3.1.5" }, ] [[package]]