Не знаю как у других, но у меня есть такая привычка – собирать как можно больше информации об изучаемом предмете. Не факт, что в будущем она может понадобиться, но, тем не менее, я от нее пока что не избавился. И вот, когда я начал изучать Python, конечно же, мне в голову пришла «гениальная» мысль скачать как можно больше книг по изучаемой теме. Со временем количество книг росло и, уже трудно было разобраться, что и где искать. Но хуже всего то, что не особо было понятно, свежая это книга или года эдак из 2010-го. Большинство книг, которые я скачивал (не спрашивайте где, думаю, что сами знаете) в формате pdf. И мне потребовалось как-то отсортировать их по году выпуска. Открывать вручную файл и перемещать его в нужную папку достаточно долго. Поэтому немного погуглив я понял, что нужно считать метаданные из файла, для того, чтобы получить дату создания и соответственно переместить файл в нужную папку.
Что потребуется?
Для того чтобы все заработало нужна будет библиотека PyPDF2. Установка происходит как обычно. Пишем в терминале:
Ну и стандартная библиотека os, которую нужно будет просто импортировать:
Создание скрипта
Создадим заготовку для будущего кода, в который добавим несколько функций. Первая для получения метаданных из pdf, а вторая для перемещения файла в нужную папку, третья для получения пользовательского ввода, на основании которого будем обрабатывать директорию. Ну и добавим функцию main, в которой будем запускать все процессы.
Вот код заготовки:
Что же, заготовка готова. Давайте двигаться дальше. Для начала получим директорию, в которой будем сканировать файлы на наличие pdf. Для этого запустим функцию def get_target_path(), которая будет возвращать папку для обработки.
А так же напишем саму функцию, в которой (до посинения пользователя ) будем запрашивать валидную папку, которая существует. В противном же случае, будем просить его ввести путь заново.
Теперь необходимо просканировать содержимое полученной директории. Для этого воспользуемся функцией os.listdir.
Ну и в цикле будем перебирать полученный список файлов, из которого будем выбирать только те, расширение которых равно «.pdf», чтобы не передать в функцию получения метаданных файлы, которые не имеют отношения к pdf. Далее, полученную директорию и имя файла нужно будет объединить и передать в функцию def get_date_file(file_name), которая вернет дату создания файла. А далее, запустить функцию def move_file(ins, item, date_f), в которую передать директорию, имя файла и полученную дату создания.
Вот код функции main:
Теперь перейдем к созданию функции для получения даты. Открываем файл для чтения побайтово. Прочитанное содержимое передадим в PdfFileReader. Затем получим с помощью функции getDocumentInfo() метаданные. Не все файлы pdf имеют метаданные. Поэтому для начала проверяем их наличие, затем получаем из списка метаданных дату создания, обрезаем ее, для приведения к году издания. Если же метаданных у файла нет, в этом случае просто возвращаем значение 0000. И закрываем файл. Но, тут нужно учесть, что есть такие pdf файлы, которые собраны просто из картинок. И вот в них попросту нет метаданных вообще. При отсутствии метаданных программа просто вылетает с ошибкой. Поэтому обернем код получения метаданных в блок try – except. В случае если нам попадется такой вот файл, вернем значение 0000. Так же, если файл битый, то открыть его мы также не сможем. Поэтому открытие файла так же обернем в блок try – except, в котором будем сообщать об ошибке и закрывать файл.
Вот, кажется, одна функция готова. Закрывать файл даже в случае ошибки обязательно. Если этого не делать, переместить файл в нужную директорию просто не получится, так как будет возникать ошибка доступа к файлу. Он будет занят другим процессом.
Теперь сделаем функцию перемещения файла в директорию с полученной датой. Здесь в самом начале проверяем, есть ли директория с нужным нам именем, а именно датой создания файла. Если есть, ничего не делаем, а вот если нет, то просто создаем. Ну и перемещаем файл в только что созданную директорию.
Вот и все. На этом программу, на данном этапе можно считать законченной. Но, книги ведь бываю т не только в формате pdf, но так же и в epub и в fb2. Поэтому, думаю, что нужно будет немного улучшить сортировку, чтобы книги в других форматах тоже складировались в нужные папки.
Вот как выглядит директория с книгами до сортировки:
А так уже после:
Ну и полный код скрипта:
Спасибо за внимание. Надеюсь ,что данная информация кому-то будет полезна
Вторая часть
Третья часть
Надо отметить, что сильно полагаться на данные, которые находятся в метаданных именно в том случае, если вам требуется определить точную дату, когда была выпущена книга, не стоит. Ведь в метаданных может быть указана информация о дате выхода перевода книги, тогда как книга вышла на самом деле на пару лет раньше. Ну или стоять дата на год ранее, а в самой книге дата выпуска будет на год позднее. Но, для сортировки книг ее вполне можно использовать. А в дальнейшем уже проверять дату глазами.
Что потребуется?
Для того чтобы все заработало нужна будет библиотека PyPDF2. Установка происходит как обычно. Пишем в терминале:
pip install PyPDF2
Ну и стандартная библиотека os, которую нужно будет просто импортировать:
Python:
import os
from PyPDF2 import PdfFileReader
Создание скрипта
Создадим заготовку для будущего кода, в который добавим несколько функций. Первая для получения метаданных из pdf, а вторая для перемещения файла в нужную папку, третья для получения пользовательского ввода, на основании которого будем обрабатывать директорию. Ну и добавим функцию main, в которой будем запускать все процессы.
Вот код заготовки:
Python:
import os
from PyPDF2 import PdfFileReader
def get_date_file(file_name):
pass
def move_file(ins, item, date_f):
pass
def get_target_path():
pass
def main():
pass
if __name__ == "__main__":
main()
Что же, заготовка готова. Давайте двигаться дальше. Для начала получим директорию, в которой будем сканировать файлы на наличие pdf. Для этого запустим функцию def get_target_path(), которая будет возвращать папку для обработки.
Python:
def main():
ins = get_target_path()
А так же напишем саму функцию, в которой (до посинения пользователя ) будем запрашивать валидную папку, которая существует. В противном же случае, будем просить его ввести путь заново.
Python:
def get_target_path():
while not os.path.isdir(user_input := input("Введите путь к папке: ")):
print(f"Папка {user_input} не найдена")
print(f"\nРаботаем с папкой {user_input}\n")
return user_input
Теперь необходимо просканировать содержимое полученной директории. Для этого воспользуемся функцией os.listdir.
scan_dir = os.listdir(ins)
Ну и в цикле будем перебирать полученный список файлов, из которого будем выбирать только те, расширение которых равно «.pdf», чтобы не передать в функцию получения метаданных файлы, которые не имеют отношения к pdf. Далее, полученную директорию и имя файла нужно будет объединить и передать в функцию def get_date_file(file_name), которая вернет дату создания файла. А далее, запустить функцию def move_file(ins, item, date_f), в которую передать директорию, имя файла и полученную дату создания.
Вот код функции main:
Python:
def main():
ins = get_target_path()
for item in os.listdir(ins):
if item.endswith('.pdf'):
print(item)
date_f = get_date_file(os.path.join(ins, item))
move_file(ins, item, date_f)
Теперь перейдем к созданию функции для получения даты. Открываем файл для чтения побайтово. Прочитанное содержимое передадим в PdfFileReader. Затем получим с помощью функции getDocumentInfo() метаданные. Не все файлы pdf имеют метаданные. Поэтому для начала проверяем их наличие, затем получаем из списка метаданных дату создания, обрезаем ее, для приведения к году издания. Если же метаданных у файла нет, в этом случае просто возвращаем значение 0000. И закрываем файл. Но, тут нужно учесть, что есть такие pdf файлы, которые собраны просто из картинок. И вот в них попросту нет метаданных вообще. При отсутствии метаданных программа просто вылетает с ошибкой. Поэтому обернем код получения метаданных в блок try – except. В случае если нам попадется такой вот файл, вернем значение 0000. Так же, если файл битый, то открыть его мы также не сможем. Поэтому открытие файла так же обернем в блок try – except, в котором будем сообщать об ошибке и закрывать файл.
Python:
def get_date_file(file_name):
try:
file = open(file_name, "rb")
except:
print(f'Не могу открыть файл {file_name}')
try:
pdf_toread = PdfFileReader(file)
if pdf_info := pdf_toread.getDocumentInfo():
file.close()
return pdf_info['/CreationDate'][2:6]
else:
file.close()
return '0000'
except:
file.close()
return '0000'
Вот, кажется, одна функция готова. Закрывать файл даже в случае ошибки обязательно. Если этого не делать, переместить файл в нужную директорию просто не получится, так как будет возникать ошибка доступа к файлу. Он будет занят другим процессом.
Теперь сделаем функцию перемещения файла в директорию с полученной датой. Здесь в самом начале проверяем, есть ли директория с нужным нам именем, а именно датой создания файла. Если есть, ничего не делаем, а вот если нет, то просто создаем. Ну и перемещаем файл в только что созданную директорию.
Python:
def move_file(ins, item, date_f):
if not os.path.isdir(os.path.join(ins, date_f)):
os.mkdir(os.path.join(ins, date_f))
os.rename(os.path.join(ins, item), os.path.join(ins, date_f, item))
Вот и все. На этом программу, на данном этапе можно считать законченной. Но, книги ведь бываю т не только в формате pdf, но так же и в epub и в fb2. Поэтому, думаю, что нужно будет немного улучшить сортировку, чтобы книги в других форматах тоже складировались в нужные папки.
Вот как выглядит директория с книгами до сортировки:
А так уже после:
Ну и полный код скрипта:
Python:
import os
from PyPDF2 import PdfFileReader
def get_date_file(file_name):
try:
file = open(file_name, "rb")
except:
print(f'Не могу открыть файл {file_name}')
try:
pdf_toread = PdfFileReader(file)
if pdf_info := pdf_toread.getDocumentInfo():
file.close()
return pdf_info['/CreationDate'][2:6]
else:
file.close()
return '0000'
except:
file.close()
return '0000'
def move_file(ins, item, date_f):
if not os.path.isdir(os.path.join(ins, date_f)):
os.mkdir(os.path.join(ins, date_f))
os.rename(os.path.join(ins, item), os.path.join(ins, date_f, item))
def get_target_path():
while not os.path.isdir(user_input := input("Введите путь к папке: ")):
print(f"Папка {user_input} не найдена")
print(f"\nРаботаем с папкой {user_input}\n")
return user_input
def main():
ins = get_target_path()
for item in os.listdir(ins):
if item.endswith('.pdf'):
print(item)
date_f = get_date_file(os.path.join(ins, item))
move_file(ins, item, date_f)
if __name__ == "__main__":
main()
Спасибо за внимание. Надеюсь ,что данная информация кому-то будет полезна
Вторая часть
Третья часть
Последнее редактирование: