This commit is contained in:
2025-06-09 00:35:39 +05:00
parent 70a65cefc5
commit 15cbdceb7f
10 changed files with 450 additions and 256 deletions

1
.gitignore vendored
View File

@@ -12,3 +12,4 @@ test
# Virtual environments # Virtual environments
.venv .venv
.32-bit

268
algam.py Normal file
View File

@@ -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()

83
algam1.py Normal file
View File

@@ -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()

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

108
main.py
View File

@@ -1,83 +1,43 @@
import tkinter as tk
from tkinter import filedialog
import algam
import glob
import os import os
import xml.etree.ElementTree as ET
import pandas as pd
from pathlib import Path
# === 🔧 НАСТРОЙКИ (меняйте под себя) === def Pars():
FOLDER_WITH_XMLS = r"C:\Users\jze9\Documents\work\git\kadastr12\test" # Папка с XML-файлами def get_all_xml_files(directory):
OUTPUT_XLSX_FILE = r"C:\Users\jze9\Documents\work\git\kadastr12\result.xlsx" # Куда сохранить результат """Возвращает список полных путей ко всем .xml файлам в директории"""
return glob.glob(os.path.join(os.path.abspath(directory), "*.xml"))
algam.Parser(dir_xml=get_all_xml_files(xml_entry.get()),save_dir=directory_entry.get())
# === ⛏ ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ === root = tk.Tk()
def extract_text(elem, tag): root.title("Parser12")
node = elem.find(f".//{tag}") font = ("Arial", 12)
return node.text.strip() if node is not None and node.text else "" root.configure(bg="#B85C38")
options = [""]
def has_spatial(elem): #путь для сохранения файлов
return elem.find(".//SpatialElement") is not None def open_directory(event, entry):
directory_path = filedialog.askdirectory()
entry.delete(0, tk.END)
entry.insert(0, directory_path)
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}") xml_label = tk.Label(root, text="директория xml", font=font)
if section is None: xml_label.pack(anchor="w")
return xml_entry = tk.Entry(root, font=font, width=70)
subtag = next(iter(section), None) xml_entry.pack(anchor="w")
if subtag is None: xml_entry.bind("<Button-1>", lambda event: open_directory(event, xml_entry))
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)
def main(): directory_label.pack(anchor="w")
records = [] directory_entry = tk.Entry(root, font=font, width=70)
for file in os.listdir(FOLDER_WITH_XMLS): directory_entry.pack(anchor="w")
if not file.lower().endswith(".xml"): directory_entry.bind("<Button-1>", lambda event: open_directory(event, directory_entry))
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) empty_button = tk.Button(root, text="->", command=Pars, font=font)
process_section(root, "SpecifyParcels", "Уточнение ЗУ", records) empty_button.pack(side="right", padx=10, pady=10)
process_section(root, "CadastralErrorsParcels", "Исправление ЗУ", records)
process_section(root, "ExistNewObjectsRealty", "Уточнение ОКС", records, is_zemel=False)
process_section(root, "CadastralErrorsOKS", "Исправление ОКС", records, is_zemel=False)
if not records: root.mainloop()
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()

39
main.spec Normal file
View File

@@ -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'],
)

181
main1.py
View File

@@ -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

View File

@@ -7,4 +7,5 @@ requires-python = ">=3.12"
dependencies = [ dependencies = [
"bs4>=0.0.2", "bs4>=0.0.2",
"lxml>=5.4.0", "lxml>=5.4.0",
"openpyxl>=3.1.5",
] ]

0
ui.py Normal file
View File

23
uv.lock generated
View File

@@ -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" }, { 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]] [[package]]
name = "lxml" name = "lxml"
version = "5.4.0" 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" }, { 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]] [[package]]
name = "soupsieve" name = "soupsieve"
version = "2.7" version = "2.7"
@@ -85,12 +106,14 @@ source = { virtual = "." }
dependencies = [ dependencies = [
{ name = "bs4" }, { name = "bs4" },
{ name = "lxml" }, { name = "lxml" },
{ name = "openpyxl" },
] ]
[package.metadata] [package.metadata]
requires-dist = [ requires-dist = [
{ name = "bs4", specifier = ">=0.0.2" }, { name = "bs4", specifier = ">=0.0.2" },
{ name = "lxml", specifier = ">=5.4.0" }, { name = "lxml", specifier = ">=5.4.0" },
{ name = "openpyxl", specifier = ">=3.1.5" },
] ]
[[package]] [[package]]