Форум сайта python.su
Здравствуйте!
Основная задача программы состоит в том, чтобы сэкономить время на вытягивание данных из pdf документа, особенно если pdf файлов очень много (штук 50 например) либо в нем много обременений/ограничений прописано. Поэтому если бы программа уже могла формирование описание объектов из пдф файлов в таком формате:
“Нежилое здание - склад горюче-смазочных материалов. Назначение: нежилое здание.Площадь: 16.4 кв.м. Количество этажей, в том числе подземных этажей: 1, в том числе подземных 0. Адрес: Российская федерация, Краснодарский край, Усть-лабинский район, ст-ца ладожская, ул.Коншиных, д.100. Кадастровый номер: 23:35:1006004:277.”
http://prntscr.com/1ztcwk1
- сначала идет наименование объекта - берем данные из следующего столбца напротив,
далее назначение, площадь, количество этажей, Адрес, Кадастровый номер (сами слова и их значения).
Если это Земельный участок, то данные берутся в такой последовательности с 1 и 2 страницы ЕГРН:
"Земельный участок, площадью 36240 +/-66.63кв. м, категория земель - Земли населённых пунктов, Виды разрешенного использования:для размещения производственной базы, расположенного по адресу установлено относительно ориентира, расположенного в границах участка. Почтовый адрес ориентира: край Краснодарский, р-н Усть-Лабинский, ст-ца Ладожская, ул.
Коншиных, 111. Кадастровый номер: 23:35:1006004:18"
и второе соответственно каждому объекту указывались его все обременения из раздела 2 пункты 3.
в таком виде
“вид: Ипотека
дата государственной регистрации: 17.01.2018
номер государственной регистрации: 23:35:1006004:277-23/033/2018-3
срок, на который установлено ограничение прав и обременение объекта недвижимости: с 17.01.2018 по 10.10.2020
лицо, в пользу которого установлено ограничение прав и обременение
объекта недвижимости: Акционерное общество Банк ”Северный морской путь“, ИНН: 7750005482
основание государственной регистрации: ‘Договор ипотеки (залога недвижимости) №0800100420.102017КЛ/ДИ-02’ от 12.01.2018”
и т.д.
Достаточно на данном этапе, чтобы данные просто выгружались таким образом для возможности их ручного копирования в вордовский документ, например. Это бы сэкономило бы много времени.
Офлайн
ЕГРН ЗУ
Прикреплённый файлы:
ЗУ.pdf (146,0 KБ)
Офлайн
PSAS
Нежилое здание - склад горюче-смазочных материалов. Назначение: нежилое здание.Площадь: 16.4 кв.м. Количество этажей, в том числе подземных этажей: 1, в том числе подземных 0. Адрес: Российская федерация, Краснодарский край, Усть-лабинский район, ст-ца ладожская, ул.Коншиных, д.100. Кадастровый номер: 23:35:1006004:277.
import camelot def get_df_from_pdf(file, pages='1') -> list: out = [] tables = camelot.read_pdf(file, pages=pages) for t in tables: out.append(t.df) return out def get_info_for_building(dfs:list): t0 = dfs[0] t1 = dfs[1] up = lambda s: s[0].upper() + s[1:] low = lambda s: s[0].lower() + s[1:] edit_address = lambda s: s.replace('
','') name = up(t1[1][6]) purpose = low(t1[1][5]) square = t1[1][4] num_floors = t1[1][7] address = edit_address(t1[1][3]) cadastral_num = t0[0][4].replace('\n', ' ') text = '{name}. Назначение: {purpose}.Площадь: {square} кв.м. ' \ 'Количество этажей, в том числе подземных этажей: {num_floors}. Адрес: {address}.' \ '{cadastral_num}'.format(name=name, purpose=purpose, square=square, num_floors=num_floors, address=address, cadastral_num=cadastral_num) return text def get_text_from_pdf(file): dfs = get_df_from_pdf(file) if dfs[0][0][0] == 'Здание': return get_info_for_building(dfs) for f in ['16.4.pdf','496.2.pdf']: print(get_text_from_pdf(f)) print('==============================')
Нежилое здание - склад горюче-смазочных материалов. Назначение: нежилое здание.Площадь: 16.4 кв.м. Количество этажей, в том числе подземных этажей: 1, в том числе подземных 0. Адрес: Российская Федерация, Краснодарский кр., Усть-Лабинский район, ст-ца Ладожская, ул. Коншиных, 111.Кадастровый номер: 23:35:1006004:277 ============================== Ангар. Назначение: нежилое здание.Площадь: 496.2 кв.м. Количество этажей, в том числе подземных этажей: 1, в том числе подземных 0. Адрес: Краснодарский край, р-н. Усть-Лабинский, ст-ца. Ладожская, ул. Коншиных, д. 111.Кадастровый номер: 23:35:1011002:271 ============================== Process finished with exit code 0
Отредактировано xam1816 (Ноя. 17, 2021 21:12:42)
Офлайн
Здравствуйте!
1) Код работает хорошо, но почему-то только на этих ЕГРН, если беру другие (во вложении), то возвращает None.
import camelot import glob pdf_files=glob.glob('*.pdf') def get_df_from_pdf(file, pages='1-end') -> list: out = [] tables = camelot.read_pdf(file, pages=pages) for t in tables: out.append(t.df) return out def get_info_for_building(dfs:list): t0 = dfs[0] t1 = dfs[1] up = lambda s: s[0].upper() + s[1:] low = lambda s: s[0].lower() + s[1:] edit_address = lambda s: s.replace('
','') name = up(t1[1][6]) purpose = low(t1[1][5]) square = t1[1][4] num_floors = t1[1][7] address = edit_address(t1[1][3].replace('\n', ' ')) cadastral_num = t0[0][4].replace('\n', ' ') text = '{name}. Назначение: {purpose}.Площадь: {square} кв.м. ' \ 'Количество этажей, в том числе подземных этажей: {num_floors}. Адрес: {address}.' \ '{cadastral_num}'.format(name=name, purpose=purpose, square=square, num_floors=num_floors, address=address, cadastral_num=cadastral_num) return text def get_info_for_landplot(dfs:list): t0 = dfs[0] t1 = dfs[1] t2 = dfs[3] up = lambda s: s[0].upper() + s[1:] low = lambda s: s[0].lower() + s[1:] category = low(t2[1][0]) purpose = low(t2[1][1]) square = t1[1][4] address = t1[1][3].replace('\n', ' ') cadastral_num = t0[0][4].replace('\n', ' ') text = 'Земельный участок площадью {square}, расположенный по адресу {address}, '\ 'категория земель - {category}, разрешенное использование - {purpose}. {cadastral_num}.'.format(category=category, purpose=purpose, square=square, address=address, cadastral_num=cadastral_num) return text def get_text_from_pdf(file): dfs = get_df_from_pdf(file) if dfs[0][0][0] == "Здание": return get_info_for_building(dfs) if dfs[0][0][0] == "Земельный участок": return get_info_for_landplot(dfs) for f in pdf_files: print(get_text_from_pdf(f)) print('==============================')
Прикреплённый файлы:
другие ЕГРН.rar (761,2 KБ)
Офлайн
PSASПосмотрю позже
Прикреплённый файлы:
Офлайн
Вот как вариант ооочень сырой версии кода,где нет еще поиска обременений и редактирования текста.
Задача не проста тем,что в каждом файле могут быть всякие пробелы,переходы в словах по разному
и постоянно нужно как-то допиливать поиск совпадений.Библиотеки camelot и tabula долго обрабатываю файл,да и таблицы из файлах по разному достаются,т.е универсальный поиск в них та еще задача
на ваших нескольких файлах прогнал, из них вытащились данные,пробуйте на других
import fitz # pip install PyMuPDF import re def get_text(pdf_file):# получает текст из pdf print(pdf_file) doc = fitz.open(pdf_file) text = '' for page in doc: text += page.get_text() doc.close() # print(text.encode('1251', 'ignore').decode('1251')) return text # возвращает str print('==========>') class Building: # класс для здания def __init__(self): self.name = '???' self.purpose = '???' self.square = '???' self.num_floors = '???' self.address = '???' self.cadastral_num = '???' self.encumbrances = [] def set_attr(self, text): self.name = re.search(r'(?<=Наименование:)(.|\n)+(?=Количество этажей)', text)[0] # self.purpose = re.search(r'(?<=Назначение:)(.|\n)+(?=Наименование)', text)[0] # self.square = re.search(r'(?<=Площадь, м²:)(.|\n)+?(?=Назначение:)', text)[0] # self.num_floors = re.search( r'(?<=Количество этажей, в том числе подземных этажей:)(.|\n)+(?=Материал наружных стен)', text)[0] # self.address = re.search(r'(?<=Адрес:)(.|\n)+(?=Площадь)', text)[0] # self.cadastral_num = re.search(r'(?<=Кадастровый номер:)(.|\n)+(?=Номер кадастрового квартала:)', text)[0] def get_info(self): enc_info = '' if self.encumbrances: enc_info = ''.join(list(map(lambda t:t.get_info(),self.encumbrances))) text = '{name}. Назначение: {purpose}.' \ 'Площадь: {square} кв.м. ' \ 'Количество этажей, в том числе подземных этажей: {num_floors}.' \ ' Адрес: {address}.' \ 'Кадастровый номер: {cadastral_num}\n\n' \ '{enc_info}'.format(name=self.name, purpose=self.purpose, square=self.square, num_floors=self.num_floors, address=self.address, cadastral_num=self.cadastral_num, enc_info = enc_info) return text class Land: # класс для земельного участка def __init__(self): self.square = '???' self.category = '???' self.type_use = '???' self.address = '???' self.cadastral_num = '???' self.encumbrances = [] def set_attr(self, text): self.square = re.search(r'(?<=Площадь:)(.|\n)+?(?=Кадастровая стоимость)', text)[0] # self.category = re.search(r'(?<=Категория земель:)(.|\n)+?(?=Виды разрешенного использования)', text)[0] # self.type_use = re.search(r'(?<=Виды разрешенного использования:)(.|\n)+?(?=Сведения о кадастровом инженере:)', text)[0] # self.address = re.search(r'(?<=Адрес:)(.|\n)+?(?=Площадь:)', text)[0] # self.cadastral_num = re.search(r'(?<=Кадастровый номер:)(.|\n)+(?=Номер кадастрового квартала:)', text)[0] def get_info(self): enc_info = '' if self.encumbrances: enc_info = ''.join(list(map(lambda t: t.get_info(), self.encumbrances))) # text = 'Земельный участок, площадью {square}, категория земель - {category}, ' \ 'Виды разрешенного использования:{type_use}. ' \ 'Почтовый адрес ориентира: {address}. ' \ 'Кадастровый номер: {cadastral_num}\n\n' \ '{enc_info}'.format(square=self.square, category=self.category, type_use=self.type_use, address=self.address, cadastral_num=self.cadastral_num, enc_info=enc_info) return text # def get_data(text):# получает данные из текста estate = None target = re.search(r'((?<=недвижимости:\n)|(?<=недвижимости:)).+(?=\n)',text) if target is not None: if target[0] == 'Земельный участок': estate = Land() elif target[0] == 'Здание': estate = Building() if estate is not None: estate.set_attr(text) return estate.get_info() # def get_directory(): # окно с выбором папки print('выбор дирректории') import tkinter as tk from tkinter import filedialog root = tk.Tk() root.withdraw() dirname = filedialog.askdirectory(parent=root,initialdir="/",title='Please select a directory') return dirname # возвращает путь # def get_all_pdf_file(dir): # выбирает файлы pdf out = [] import os for file in os.listdir(dir): if file.endswith('.pdf'): out.append(f'{dir}/{file}') return out # возвращает список с pdf # dir = get_directory() pdf_file_list = get_all_pdf_file(dir) # for f in pdf_file_list: text = get_text(f) print(get_data(text))
Офлайн
Здравствуйте!
Спасибо, не могу запустить код, установил обе библиотеки fitz и PyMuPDF
ModuleNotFoundError: No module named ‘fitz’ Всвязи с чем это может быть?
Офлайн
PSASнет надо было только PyMuPDF,
No module named ‘fitz’ Всвязи с чем это может быть?
pip uninstall fitz
Офлайн
Здравствуйте!
по данным егрн не формируются данные
http://prntscr.com/20x0mic
https://disk.yandex.ru/d/EV1kgSo3Wds4KA
Офлайн
Вышла новая версия!
.
обновления:
-добавлены другие виды недвижимости
-добавлен вывод обременения
/
не сделано:
- у новых видов недвижимости, нет некоторых параметров(какие именно нужны непонятно,просто скопировал с других)
-нет форматирования данных(в каком виде достались,в том и выводятся)
- и еще,еще,еще,еще,чего нибудь…
для скачивания нажать ctrl-c ctrl-v
import fitz # pip install PyMuPDF import re def get_text(pdf_file):# получает текст из pdf print(pdf_file) doc = fitz.open(pdf_file) text = '' for page in doc: text += page.get_text() doc.close() # print(text.encode('1251', 'ignore').decode('1251')) return text # возвращает str print('==========>') class Room: def __init__(self): self.name = '???' self.purpose = '???' self.square = '???' self.num_floors = '???' self.address = '???' self.cadastral_num = '???' self.encumbrances = [] def set_attr(self, text): self.name = re.search(r'(?<=Наименование:)(.|\n)+(?=Номер, тип этажа, на котором расположено помещение)', text)[0] # self.purpose = re.search(r'(?<=Назначение:)(.|\n)+(?=Наименование)', text)[0] # self.square = re.search(r'(?<=Площадь:)(.|\n)+?(?=Назначение:)', text)[0] # self.address = re.search(r'(?<=Адрес:)(.|\n)+(?=Площадь)', text)[0] # self.cadastral_num = re.search(r'(?<=Кадастровый номер:)(.|\n)+(?=Номер кадастрового квартала:)', text)[0] # iter = re.finditer(r'(?<=3\.1\.\d\.\n)(.|\n)+?((?=3\.1\.\d+\.)|(?=Государственный регистратор))', text) self.encumbrances = [i[0] for i in iter] def get_info(self): enc_info = '' if self.encumbrances: enc_info = '\n'.join(self.encumbrances) text = '{name}. Назначение: {purpose}.' \ 'Площадь: {square} кв.м. ' \ 'Количество этажей, в том числе подземных этажей: {num_floors}.' \ ' Адрес: {address}.' \ 'Кадастровый номер: {cadastral_num}\n\n' \ '{enc_info}'.format(name=self.name, purpose=self.purpose, square=self.square, num_floors=self.num_floors, address=self.address, cadastral_num=self.cadastral_num, enc_info = enc_info) return text class Construction: def __init__(self): self.name = '???' self.purpose = '???' self.square = '???' self.num_floors = '???' self.address = '???' self.cadastral_num = '???' self.encumbrances = [] def set_attr(self, text): self.name = re.search(r'(?<=Наименование:)(.|\n)+(?=Количество этажей)', text)[0] # self.purpose = re.search(r'(?<=Назначение:)(.|\n)+(?=Наименование)', text)[0] # self.address = re.search(r'(?<=Адрес:)(.|\n)+(?=Основная характеристика \(для сооружения\):)', text)[0] # self.cadastral_num = re.search(r'(?<=Кадастровый номер:)(.|\n)+(?=Номер кадастрового квартала:)', text)[0] # iter = re.finditer(r'(?<=3\.1\.\d\.\n)(.|\n)+?((?=3\.1\.\d+\.)|(?=Государственный регистратор))', text) self.encumbrances = [i[0] for i in iter] def get_info(self): enc_info = '' if self.encumbrances: enc_info = '\n'.join(self.encumbrances) text = '{name}. Назначение: {purpose}.' \ 'Площадь: {square} кв.м. ' \ 'Количество этажей, в том числе подземных этажей: {num_floors}.' \ ' Адрес: {address}.' \ 'Кадастровый номер: {cadastral_num}\n\n' \ '{enc_info}'.format(name=self.name, purpose=self.purpose, square=self.square, num_floors=self.num_floors, address=self.address, cadastral_num=self.cadastral_num, enc_info = enc_info) return text class Building: # класс для здания def __init__(self): self.name = '???' self.purpose = '???' self.square = '???' self.num_floors = '???' self.address = '???' self.cadastral_num = '???' self.encumbrances = [] def set_attr(self, text): self.name = re.search(r'(?<=Наименование:)(.|\n)+(?=Количество этажей)', text)[0] # self.purpose = re.search(r'(?<=Назначение:)(.|\n)+(?=Наименование)', text)[0] # self.square = re.search(r'(?<=Площадь, м²:)(.|\n)+?(?=Назначение:)', text)[0] # self.num_floors = re.search( r'(?<=Количество этажей, в том числе подземных этажей:)(.|\n)+(?=Материал наружных стен)', text)[0] # self.address = re.search(r'(?<=Адрес:)(.|\n)+(?=Площадь)', text)[0] # self.cadastral_num = re.search(r'(?<=Кадастровый номер:)(.|\n)+(?=Номер кадастрового квартала:)', text)[0] # iter = re.finditer(r'(?<=3\.1\.\d\.\n)(.|\n)+?((?=3\.1\.\d+\.)|(?=Государственный регистратор))', text) self.encumbrances = [i[0] for i in iter] def get_info(self): enc_info = '' if self.encumbrances: enc_info = '\n'.join(self.encumbrances) text = '{name}. Назначение: {purpose}.' \ 'Площадь: {square} кв.м. ' \ 'Количество этажей, в том числе подземных этажей: {num_floors}.' \ ' Адрес: {address}.' \ 'Кадастровый номер: {cadastral_num}\n\n' \ '{enc_info}'.format(name=self.name, purpose=self.purpose, square=self.square, num_floors=self.num_floors, address=self.address, cadastral_num=self.cadastral_num, enc_info = enc_info) return text class Land: # класс для земельного участка def __init__(self): self.square = '???' self.category = '???' self.type_use = '???' self.address = '???' self.cadastral_num = '???' self.encumbrances = [] def set_attr(self, text): self.square = re.search(r'(?<=Площадь:)(.|\n)+?(?=Кадастровая стоимость)', text)[0] # self.category = re.search(r'(?<=Категория земель:)(.|\n)+?(?=Виды разрешенного использования)', text)[0] # self.type_use = re.search(r'(?<=Виды разрешенного использования:)(.|\n)+?(?=Сведения о кадастровом инженере:)', text)[0] # self.address = re.search(r'(?<=Адрес:)(.|\n)+?(?=Площадь:)', text)[0] # self.cadastral_num = re.search(r'(?<=Кадастровый номер:)(.|\n)+(?=Номер кадастрового квартала:)', text)[0] # iter = re.finditer(r'(?<=3\.1\.\d\.\n)(.|\n)+?((?=3\.1\.\d+\.)|(?=Государственный регистратор))', text) self.encumbrances = [i[0] for i in iter] def get_info(self): enc_info = '' if self.encumbrances: enc_info = '\n'.join(self.encumbrances) # text = 'Земельный участок, площадью {square}, категория земель - {category}, ' \ 'Виды разрешенного использования:{type_use}. ' \ 'Почтовый адрес ориентира: {address}. ' \ 'Кадастровый номер: {cadastral_num}\n' \ '{enc_info}'.format(square=self.square, category=self.category, type_use=self.type_use, address=self.address, cadastral_num=self.cadastral_num, enc_info=enc_info) return text # def get_data(text):# получает данные из текста estate = None target = re.search(r'((?<=недвижимости:\n)|(?<=недвижимости:)).+(?=\n)',text) if target is not None: if target[0] == 'Земельный участок': estate = Land() elif target[0] == 'Здание': estate = Building() elif target[0] == 'Сооружение': estate = Construction() elif target[0] == 'Помещение': estate = Room() if estate is not None: estate.set_attr(text) return estate.get_info() # def get_directory(): # окно с выбором папки print('выбор дирректории') import tkinter as tk from tkinter import filedialog root = tk.Tk() root.withdraw() dirname = filedialog.askdirectory(parent=root,initialdir="/",title='Please select a directory') return dirname # возвращает путь # def get_all_pdf_file(dir): # выбирает файлы pdf out = [] import os for file in os.listdir(dir): if file.endswith('.pdf'): out.append(f'{dir}/{file}') return out # возвращает список с pdf # dir = get_directory() pdf_file_list = get_all_pdf_file(dir) for f in pdf_file_list: text = get_text(f) res = get_data(text) print(res) print('=====')
Офлайн