Всем привет. В двух предыдущих статьях «Сортировка книг в формате PDF по годам выпуска с помощью Python» и «Дорабатываем сортировку книг по папкам. Сортировка Epub с помощью Python» был сделан сортировщик, который раскладывает книги в форматах pdf и epub по годам выпуска. Но, есть еще формат, который был не затронут в предыдущих статьях, это fb2. У данного формата также есть метаданные, и он представляет собой файл в формате xml. А значит, извлечение метаданных из него вполне возможно, как и последующая сортировка по папкам.
Что понадобиться?
Установить библиотеку для парсинга данных BeautifulSoup:
Возможно, использование данной библиотеки здесь избыточно, но, именно с ее помощью получилось довольно просто получить данные из файла данного формата. Все остальные решения либо сильно усложнены, либо требуют более детального изучения. А мне нужно было сделать все как можно быстрее и проще. Что я и реализовал на практике.
Дополнение сортировщика файлов
Давайте приступим к дополнению сортировщика файлов, который был сделан в прошлых статьях. Для начала импортируем библиотеку BeautifulSoup:
Теперь необходимо сделать функцию, которая будет получать данные из книги в формате fb2. Назову ее get_fb2_info(fname). В данную функцию передается путь к файлу для получения данных. А проще говоря, для парсинга. Далее, данный файл открывается для чтения и данные из него передаются в переменную src. После создается объект BeautifulSoup, в который и передаются данные из переменной src, а так же указывается парсер, с помощью которого будет выполняться поиск по файлу – xml. Далее пишем условие для поиска данных. Дело в том, что дата в файлах попадается в разных тегах. В зависимости от того, в какой программе создавалась книга. Поэтому делаем простую проверку на их наличие и если они присутствуют, получаем данные о дате. Ну и далее, возвращаем полученную дату из функции.
Теперь необходимо дополнить функцию main, чтобы файлы формата fb2 так же передавались в нужную функцию для обработки. А после получения даты перемещались в папку с нужным годом. Поэтому пишем еще одно условие, в котором так же проверяем расширение файла. И если расширение fb2, передаем в функцию нужные данные для получения даты.
Вот собственно и все. Теперь, с помощью дополненной программы можно быстро разложить загруженные книги в форматах pdf, epub и fb2 по годам издания. Вручную это, полагаю, заняло бы достаточно много времени. Я, к тому времени, как озаботился сортировкой книг, успел скачать их более 2000 штук. И просматривать все их вручную для сортировки по годам было очень утомительно, откуда и возникла идея создать сортировщик в python. Автоматизация
Ну и вот скрин папки до работы скрипта:
Ну и после сортировки:
Как видите, все файлы были отсортированы, остались только файлы в формате djvu. Ну, а те книги, которые попали в папки 0000 и 0101 я отсортирую вручную. Их уже гораздо меньше, чем было и они вполне поддаются ручной сортировке.
Спасибо за внимание. Надеюсь, что данная информация будет кому-нибудь полезной
Первая часть
Вторая часть
Что понадобиться?
Установить библиотеку для парсинга данных BeautifulSoup:
pip install bs4
Возможно, использование данной библиотеки здесь избыточно, но, именно с ее помощью получилось довольно просто получить данные из файла данного формата. Все остальные решения либо сильно усложнены, либо требуют более детального изучения. А мне нужно было сделать все как можно быстрее и проще. Что я и реализовал на практике.
Дополнение сортировщика файлов
Давайте приступим к дополнению сортировщика файлов, который был сделан в прошлых статьях. Для начала импортируем библиотеку BeautifulSoup:
from bs4 import BeautifulSoup
Теперь необходимо сделать функцию, которая будет получать данные из книги в формате fb2. Назову ее get_fb2_info(fname). В данную функцию передается путь к файлу для получения данных. А проще говоря, для парсинга. Далее, данный файл открывается для чтения и данные из него передаются в переменную src. После создается объект BeautifulSoup, в который и передаются данные из переменной src, а так же указывается парсер, с помощью которого будет выполняться поиск по файлу – xml. Далее пишем условие для поиска данных. Дело в том, что дата в файлах попадается в разных тегах. В зависимости от того, в какой программе создавалась книга. Поэтому делаем простую проверку на их наличие и если они присутствуют, получаем данные о дате. Ну и далее, возвращаем полученную дату из функции.
Python:
def get_fb2_info(fname):
with open(fname, 'r', encoding='utf-8') as file:
src = file.read()
soup = BeautifulSoup(src, 'xml')
if soup.find('date', {'value': True}):
return soup.find('date', {'value': True})['value'][0:4]
elif soup.find('date'):
return soup.find('date').text[0:4]
Теперь необходимо дополнить функцию main, чтобы файлы формата fb2 так же передавались в нужную функцию для обработки. А после получения даты перемещались в папку с нужным годом. Поэтому пишем еще одно условие, в котором так же проверяем расширение файла. И если расширение fb2, передаем в функцию нужные данные для получения даты.
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)
elif item.endswith('.fb2'):
print(item)
date_f = get_fb2_info(os.path.join(ins, item))
move_file(ins, item, date_f)
Вот собственно и все. Теперь, с помощью дополненной программы можно быстро разложить загруженные книги в форматах pdf, epub и fb2 по годам издания. Вручную это, полагаю, заняло бы достаточно много времени. Я, к тому времени, как озаботился сортировкой книг, успел скачать их более 2000 штук. И просматривать все их вручную для сортировки по годам было очень утомительно, откуда и возникла идея создать сортировщик в python. Автоматизация
Ну и вот скрин папки до работы скрипта:
Ну и после сортировки:
Как видите, все файлы были отсортированы, остались только файлы в формате djvu. Ну, а те книги, которые попали в папки 0000 и 0101 я отсортирую вручную. Их уже гораздо меньше, чем было и они вполне поддаются ручной сортировке.
Python:
import os
import zipfile
from PyPDF2 import PdfFileReader
from bs4 import BeautifulSoup
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 get_fb2_info(fname):
with open(fname, 'r', encoding='utf-8') as file:
src = file.read()
soup = BeautifulSoup(src, 'xml')
if soup.find('date', {'value': True}):
return soup.find('date', {'value': True})['value'][0:4]
elif soup.find('date'):
return soup.find('date').text[0:4]
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)
elif item.endswith('.fb2'):
print(item)
date_f = get_fb2_info(os.path.join(ins, item))
move_file(ins, item, date_f)
if __name__ == "__main__":
main()
Спасибо за внимание. Надеюсь, что данная информация будет кому-нибудь полезной
Первая часть
Вторая часть
Последнее редактирование: