В статье «Сортировка книг в формате PDF по годам выпуска с помощью Python» я поделился кодом, с помощью которого происходит сортировка книг в формате pdf по годам выпуска. Но, нужно больше. Ведь книги есть также и в формате epub. И их довольно много. Открывать каждую – значит просто потерять кучу времени. Следовательно, нужно как-то дополнить код, который был в статье так, чтобы сортировка велась также и по формату epub.
Что понадобиться?
Для работы сортировки epub нужно будет импортировать модуль:
А также установить, если у вас еще не установлена, библиотеку для парсинга xml, lxml:
И импортировать из нее etree:
Дополняем сортировщик
Не скажу, что я сам придумал решение. Нет, я нашел его в интернете, уж даже и не помню, на каком форуме. Но, суть в том, что каждый файл в формате epub – это zip-архив. И перед тем, как что-то в нем искать, его нужно распаковать. Ну, а далее, просто парсить xml. Давайте дополним код из предыдущей статьи дополнительной функцией def get_epub_info(fname), которая будет получать имя файла с директорией, открывать его, распаковывать и производить поиск нужной информации. После чего возвращать ее в переменную, из под которой была вызвана функция.
Ну и дополним функцию main собственно определением расширения файла и вызовом соответствующей функции для поиска в нем информации.
Все остальные функции остались без изменений. То есть, мы же получаем однотипные данные, а значит, для того, чтобы переместить файл в нужную папку их достаточно. К сожалению, не во всех файлах содержится корректная дата, а потому, создается папка с тем значением, которое получается из файла. Но, это все равно уменьшает количество просматриваемых книг вручную в разы.
Вот папка до перемещения книг epub:
И эта же папка после перемещения книг:
Как видите, создалась папка с именем 0101. Это значит, что в книгах содержалось некорректное значение даты. Я проверил данные, которые получаются до обрезки, во избежание того, что я обрезаю что-то нужное. Но нет, такая дата и содержится в получаемом значении.
Ну и полный код скрипта:
А вот о том, как переместить книги в формате fb2, думаю, что разберемся уже в следующей статье. Тут мне пришлось немного повозиться. Так как все предлагаемые решения, которые я находил, сводились к тому, что надо парсить xml. И это верно. Так я и сделал. Но, как? Это уже другой вопрос.
Спасибо за внимание. Надеюсь, что данная информация была кому-нибудь полезна
Первая часть
Третья часть
Что понадобиться?
Для работы сортировки epub нужно будет импортировать модуль:
import zipfile
А также установить, если у вас еще не установлена, библиотеку для парсинга xml, lxml:
pip install lxml
И импортировать из нее etree:
from lxml import etree
Дополняем сортировщик
Не скажу, что я сам придумал решение. Нет, я нашел его в интернете, уж даже и не помню, на каком форуме. Но, суть в том, что каждый файл в формате epub – это zip-архив. И перед тем, как что-то в нем искать, его нужно распаковать. Ну, а далее, просто парсить xml. Давайте дополним код из предыдущей статьи дополнительной функцией def get_epub_info(fname), которая будет получать имя файла с директорией, открывать его, распаковывать и производить поиск нужной информации. После чего возвращать ее в переменную, из под которой была вызвана функция.
Python:
def get_epub_info(fname):
ns = {
'n': 'urn:oasis:names:tc:opendocument:xmlns:container',
'pkg': 'http://www.idpf.org/2007/opf',
'dc': 'http://purl.org/dc/elements/1.1/'
}
try:
zip = zipfile.ZipFile(fname)
except:
print(f'Не могу прочитать файл {fname}')
try:
txt = zip.read('META-INF/container.xml')
tree = etree.fromstring(txt)
cfname = tree.xpath('n:rootfiles/n:rootfile/@full-path', namespaces=ns)[0]
cf = zip.read(cfname)
tree = etree.fromstring(cf)
p = tree.xpath('/pkg:package/pkg:metadata', namespaces=ns)[0]
return p.xpath('dc:%s/text()'%('date'), namespaces=ns)[0][0:4]
except:
return '0000'
Ну и дополним функцию 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)
elif item.endswith('.epub'):
print(item)
date_f = get_epub_info(os.path.join(ins, item))
move_file(ins, item, date_f)
Все остальные функции остались без изменений. То есть, мы же получаем однотипные данные, а значит, для того, чтобы переместить файл в нужную папку их достаточно. К сожалению, не во всех файлах содержится корректная дата, а потому, создается папка с тем значением, которое получается из файла. Но, это все равно уменьшает количество просматриваемых книг вручную в разы.
Вот папка до перемещения книг epub:
И эта же папка после перемещения книг:
Как видите, создалась папка с именем 0101. Это значит, что в книгах содержалось некорректное значение даты. Я проверил данные, которые получаются до обрезки, во избежание того, что я обрезаю что-то нужное. Но нет, такая дата и содержится в получаемом значении.
Ну и полный код скрипта:
Python:
import os
import zipfile
from PyPDF2 import PdfFileReader
from lxml import etree
def get_date_file(file_name):
try:
file = open(file_name, "rb")
except:
print(f'Не могу открыть файл {file_name}')
file.close()
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 get_epub_info(fname):
ns = {
'n': 'urn:oasis:names:tc:opendocument:xmlns:container',
'pkg': 'http://www.idpf.org/2007/opf',
'dc': 'http://purl.org/dc/elements/1.1/'
}
try:
zip = zipfile.ZipFile(fname)
except:
print(f'Не могу прочитать файл {fname}')
try:
txt = zip.read('META-INF/container.xml')
tree = etree.fromstring(txt)
cfname = tree.xpath('n:rootfiles/n:rootfile/@full-path', namespaces=ns)[0]
cf = zip.read(cfname)
tree = etree.fromstring(cf)
p = tree.xpath('/pkg:package/pkg:metadata', namespaces=ns)[0]
return p.xpath('dc:%s/text()'%('date'), namespaces=ns)[0][0:4]
except:
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)
elif item.endswith('.epub'):
print(item)
date_f = get_epub_info(os.path.join(ins, item))
move_file(ins, item, date_f)
if __name__ == "__main__":
main()
А вот о том, как переместить книги в формате fb2, думаю, что разберемся уже в следующей статье. Тут мне пришлось немного повозиться. Так как все предлагаемые решения, которые я находил, сводились к тому, что надо парсить xml. И это верно. Так я и сделал. Но, как? Это уже другой вопрос.
Спасибо за внимание. Надеюсь, что данная информация была кому-нибудь полезна
Первая часть
Третья часть
Последнее редактирование: