- Как найти однотипную информацию в большом количестве файлов, используя Python?
- Поиск текста в нескольких файлах на Python
- Получение текущего рабочего каталога
- Определяем путь, по которому хотим искать текст
- Вывод списка файлов в директории
- Вывод всех файлов из каталога по одному
- Получаем абсолютный путь для каждого файла
- Рекурсивный вывод содержимого директории
- Открытие каждого файла, чтение и поиск текста
Как найти однотипную информацию в большом количестве файлов, используя Python?
Недавно мы решали следующую задачу – необходимо найти и удалить содержащие номера карт файлы, размещенные на общем ресурсе. Если нужно было бы искали что-то, определенное и однозначное, мы могли бы воспользоваться поиском в самой операционной системе (используя стандартны поиск текста в содержимом файла). Но, как правило, поиск стандартными средствами занимает очень много времени. А если еще нужно хотите использовать маски или регулярные выражения, то как быть? Поделимся, как мы решили эту задачу.
Данную задачу можно решить на многих языках взяв за основу идею, описанную в этой статье. Я буду делать реализацию на языке Python, а инструменты использовать «из коробки», без импорта сторонних библиотек. Почему я не использовал библиотеку Pandas? Pandas хороший инструмент для работы с файлами Excel, но он достаточно массивный и ресурсоемкий для решения нашей задачи.
Углубимся в формат XLSX. Что он из себя представляет? Файл Excel — это обычный структурированный архив с расширением. XLSX. Если мы изменим расширение на. ZIP, то сможем открыть его с помощью архиватора, установленного в вашей операционной системе.
Файл Excel открылся в архиваторе, и мы видим структуру самого архива. Нам нужна папка [xl]. Проваливаемся в нее и видим:
Нам интересны директория [worksheets] и файл [sharedStrings.xml].
В файле [sharedString.xml] хранятся все текстовые поля, которые есть на листах в Excel, т.е. если поле текстовое, то оно будет хранится в этом файле, а ссылка на это поле будет находится в директории [worksheets] на соответствующем листе. Если в нескольких ячейках будет одно и тоже слово, то в файле будет одно слово, а в ячейках будет указана одна ссылка на это слово (см. рис.).
Итак, мы знаем, что номер карты является текстовым полем, соответственно он будет находится в этом файле. Приступим к написанию кода. Нам понадобятся следующие библиотеки: os – для работы с путями ОС, zipfile – для работы с архивами, re – для работы с регулярными выражениями — паттернами.
import os, zipfile, re #импортируем библиотеки #Определяем регулярные выражения pattern_card16=rb»(\b\d<16>\b|\b\d\s\d\s\d\s\d\b|\b\d\s\d\b)» pattern_card18=rb»(\b\d\b|\b\d\s\d\b)»16>
Далее пишем функцию, которая будет сканировать выбранную нами директорию:
def find_file(dirn, path): # функция принимает os.listdir, и путь на папку try: for i in dirn: if os.path.isfile(path+’/’+i): #проверяем что перед нами, файл или нет #Проверяем расширение файла и исключаем системные которые начинаются на [~$] if i.find(‘.xlsx’)!=-1and i.find(‘~$’)==-1 and i.find(‘.xlsx.’)==-1: open_arch(path+’/’+i) #Функция по обработке архивов else: #Если это директория, то проваливаемся в нее find_file(os.listdir(path+’/’+i),path+’/’+i) except Exception as err: print(err,path+’/’+i)
Теперь напишем саму функцию, которая будет обрабатывать найденные по условию файлы:
def open_arch(path_file): z = zipfile.ZipFile(path_file, ‘r’) #открываем архив files=z.namelist() #получаем список файлов в архиве try: for f in files: if f==’xl/sharedStrings.xml’: if re.search(pattern_card16, z.read(f))!=None or re.search(pattern_card18, z.read(f))!=None: list_file.write(path_file+’\n’) #Если находит совпадение, то пишем путь в файл #print(re.findall(pattern_card16, z.read(r))) # если вам нужно #print(re.findall(pattern_card18, z.read(r))) # выводить совпадения except Exception as err: print(err, files)
Определяем директорию для поиска и запускаем функцию для поиска:
path=’Y:’ #указываем путь к общему ресурсу, здесь я его подцепил как диск Y: list_file=open(‘list_file’, ‘w+’) #открываем файл для записи find_file(os.listdir(path), path) #запускаем обработку
Наша работа сделана. Ждем, когда отработает скрипт и получим итоговый файл для анализа. Вы зададите вопрос, почему я сразу не стал удалять файлы? Потому что поиск основан на простом регулярном выражении и туда могут попасть номера заявок, договоров и т.д.
В результате нам удалось избежать ручного анализа более 154 тысяч файлов и сократить выборку более чем в 100 раз.
Я надеюсь, моя инструкция была полезна. Спасибо за внимание.
Поиск текста в нескольких файлах на Python
В этой статье мы будем искать текст или строку в нескольких файлах. План действий следующий: определяем директорию, в которой нужно искать, получаем список всех файлов в этой директории (в том числе во вложенных папках), а затем открываем каждый файл и ищем в нем нужный текст.
Для начала укажите текст, который вы хотите найти.
text = input("Please enter text: ")
Напишите в поле ввода текст, который вы хотите найти, затем нажмите клавишу Enter. Например, введем слово “machine”.
print(f"You have entered \"\" word to search.")
You have entered “machine” word to search.
Получение текущего рабочего каталога
Модуль OS в Python предоставляет функции для взаимодействия с операционной системой. Это один из стандартных модулей Python. Он обеспечивает переносимый способ использования функциональности, зависящей от операционной системы.
Получение текущего рабочего каталога:
import os current_path = os.getcwd() current_path
'E:\\jupyter-notebook-workspace'
Мой текущий рабочий каталог – E://jupyter-notebook-workspace. Но я хочу искать текст в другом каталоге.
Определяем путь, по которому хотим искать текст
Я хочу найти текст по пути “G:/data/input”. По этому пути у меня есть несколько файлов и папок.
Вывод списка файлов в директории
Примечание редакции: на эту тему у нас есть отдельная статья с разбором нескольких подходов – “Как вывести список файлов в каталоге на Python”.
Давайте создадим функцию для смены директории на ту, где нужно искать текст, и вывода списка файлов в ней.
os.chdir(path) – смена текущего рабочего каталога на указанный путь.
os.listdir(path=’.’) возвращает список содержимого директории, заданной как path . Элементы списка будут идти в произвольном порядке и не будут включать специальные записи . и .. , даже если они присутствуют в каталоге. Если во время вызова этой функции файл удаляется из каталога или добавляется в него, будет ли включено имя этого файла, не определено.
def searchText(path): os.chdir(path) files = os.listdir() print(files) pass searchText(path)
['001–001-intent-recognition-with-bert.ipynb', '002–001-deploy-machine-learning-model-with-flask-on-heroku.ipynb', 'add-signup-form-in-react-native-mobile-app-part-7.ipynb', 'build-the-neural-network-with-pytorch.ipynb', 'call-graphql-api-in-react-native-mobile-app-part-5.ipynb', 'capture-date-phone-and-email-from-text-with-regular-expression-in-python.ipynb', 'classify-images-of-clothing-with-neural network.ipynb', 'color-and-shape.ipynb', 'samples']
Мы получили список файлов и папок в указанной директории.
Вывод всех файлов из каталога по одному
def searchText(path): os.chdir(path) files = os.listdir() #print(files) for file_name in files: print(file_name) pass searchText(path)
001–001-intent-recognition-with-bert.ipynb 002–001-deploy-machine-learning-model-with-flask-on-heroku.ipynb add-signup-form-in-react-native-mobile-app-part-7.ipynb build-the-neural-network-with-pytorch.ipynb call-graphql-api-in-react-native-mobile-app-part-5.ipynb capture-date-phone-and-email-from-text-with-regular-expression-in-python.ipynb classify-images-of-clothing-with-neural network.ipynb color-and-shape.ipynb samples
Получаем абсолютный путь для каждого файла
def searchText(path): os.chdir(path) files = os.listdir() #print(files) for file_name in files: #print(file_name) abs_path = os.path.abspath(file_name) print("Absolute path of the file:", abs_path) pass searchText(path)
Absolute path of the file: G:\data\input\001–001-intent-recognition-with-bert.ipynb Absolute path of the file: G:\data\input\002–001-deploy-machine-learning-model-with-flask-on-heroku.ipynb Absolute path of the file: G:\data\input\add-signup-form-in-react-native-mobile-app-part-7.ipynb Absolute path of the file: G:\data\input\build-the-neural-network-with-pytorch.ipynb Absolute path of the file: G:\data\input\call-graphql-api-in-react-native-mobile-app-part-5.ipynb Absolute path of the file: G:\data\input\capture-date-phone-and-email-from-text-with-regular-expression-in-python.ipynb Absolute path of the file: G:\data\input\classify-images-of-clothing-with-neural network.ipynb Absolute path of the file: G:\data\input\color-and-shape.ipynb Absolute path of the file: G:\data\input\samples
Вы видите, что у нас есть папка samples. Файлы из этой папки тоже нужно добавить в общий список. Для этого нам нужно выполнить рекурсивный поиск.
Рекурсивный вывод содержимого директории
def searchText(path): os.chdir(path) files = os.listdir() #print(files) for file_name in files: #print(file_name) abs_path = os.path.abspath(file_name) print("Absolute path of the file: ", abs_path) if os.path.isdir(abs_path): searchText(abs_path) pass searchText(path)
Absolute path of the file: G:\data\input\001–001-intent-recognition-with-bert.ipynb Absolute path of the file: G:\data\input\002–001-deploy-machine-learning-model-with-flask-on-heroku.ipynb Absolute path of the file: G:\data\input\add-signup-form-in-react-native-mobile-app-part-7.ipynb Absolute path of the file: G:\data\input\build-the-neural-network-with-pytorch.ipynb Absolute path of the file: G:\data\input\call-graphql-api-in-react-native-mobile-app-part-5.ipynb Absolute path of the file: G:\data\input\capture-date-phone-and-email-from-text-with-regular-expression-in-python.ipynb Absolute path of the file: G:\data\input\classify-images-of-clothing-with-neural network.ipynb Absolute path of the file: G:\data\input\color-and-shape.ipynb Absolute path of the file: G:\data\input\samples Absolute path of the file: G:\data\input\samples\alice-in-wonderland.txt Absolute path of the file: G:\data\input\samples\ramayana.txt
Открытие каждого файла, чтение и поиск текста
def searchText(path): os.chdir(path) files = os.listdir() #print(files) for file_name in files: #print(file_name) abs_path = os.path.abspath(file_name) if os.path.isdir(abs_path): searchText(abs_path) if os.path.isfile(abs_path): with open(file_name, 'r', encoding='utf-8') as f: if text in f.read(): final_path = os.path.abspath(file_name) print(text + " word found in this path " + final_path) else: print("No match found in " + abs_path) pass searchText(path)
Текст найден в трех файлах.