Привет всем! Не так давно в Facebook возникло обсуждение — как навести порядок в библиотеке на локальном устройстве? Учитывая, что в основном читаю я файлы .fb2 — сегодняшний вопрос будет звучать как решение проблемы: извлекаем данные из файла .fb2. А заодно порядок на винте наводим 🙂
Суть проблемы: когда качаем книгу — чаще всего она имеет совершенно ненормальное название (например: Piz_Novyy-yazyk-telodvizheniy.RoTD5Q.393030.fb2 — да, в целом, понятно, но все же …). Учитывая, что по этой крякозябре сложно догадаться, о чем идет речь — возник вопрос, а можно ли как-то определить автора, название, и соответствующим образом переименовать файл? Вполне возможно!
Итак, что такое файл .fb2? Фактически — это .xml документ. А раз это .xml документ — то его можно и нужно распарсить 🙂
Проблема, с которой я столкнулся в самом начале — определить кодировку файла. В теории — можно было наобум открывать файл в любой кодировке, искать заголовок кодировки внутри самого файла, и исходя из этого работать далее. Но код получался таким большим, что пришлось использовать библиотеку chardet, которая работает со следующими кодировками:
В итоге код берет .fb2 файл, разбирает его, находит автора книги, название книги и сохраняет этот файл в видео «Автор-Название». Можно, конечно, добавить жанр, и прочее. Проверил код на работоспособность на паре тысяч книг, имеющихся в наличии. Вроде как работает.
Сам код в полном виде выглядит так:
from chardet.universaldetector import UniversalDetector #Определим кодировку файла
import re #Подключаем библиотеку для парсинга
import glob #Подключаем библиотеку для работы с файлами определенного расширения
import os #Подключаем библиотеку для работы с файловой системой
import random
path = str(input('Где находятся исходные файлы? : \n'))
regxp = '[\w-]+[\w:]'
result = re.findall(regxp, path) #Разбиваем введенный адрес на составляющие без обратного слеша
path = '\\\\'.join(result) #Добавляем двойной слеш после каждой папки (под формат Python)
print('Берем данные из:', path)
os.chdir(path)
print('Предстоит обработать книг:', len(glob.glob('*.fb2')))
for file in glob.glob('*.fb2'):
print('\n\nОбрабатываем файл:',file)
detector = UniversalDetector()
with open(file, 'rb') as file_encoding:
for line in file_encoding:
detector.feed(line)
if detector.done:
break
detector.close()
file_encoding = str(detector.result['encoding'])
print(file_encoding)
if file_encoding == False:
continue
else:
with open(file, 'r', encoding=file_encoding) as file_name:
stroke = file_name.read()
stroke = str(stroke)
reg_genre = '(.+) '
reg_title = '(.+) '
reg_last_name = '(.+) '
reg_first_name = 'first-name>(.+)'
reg_trial = 'Конец ознакомительного фрагмента. '
title = re.findall(reg_title, stroke)
title = str(title)
title = title.replace('\'', '').replace('\"', '').replace(':', '').replace('#', '').replace('(', ''). \
replace(')', '').replace('[', '').replace(']', '').replace('!', '').replace('?', '').replace('\\', '').\
replace('/', '').replace('.', '').replace('«', '').replace('»', '').replace(',', '').replace('-', '')
last_name = re.findall(reg_last_name, stroke)
print('Фамилия после поиска первой регуляркой: ', last_name )
print('Тип фамилии:', type(last_name))
if len(last_name) > 0:
last_name = last_name[0]
last_name = ''.join(last_name)
last_name = str(last_name)
else:
last_name = str('БезФамилии')
print('Фамилия после уборки лишних знаков: ', last_name)
print('Тип фамилии:', type(last_name))
reg_last_names = '^\w*'
last_name = re.findall(reg_last_names, last_name)
print('Фамилия после поиска второй регуляркой: ', last_name)
print('Тип фамилии:', type(last_name))
last_name = str(''.join(last_name))
first_name = re.findall (reg_first_name, stroke)
print('Результат имени после работы первой регулярки: ', first_name)
print('Тип имени: ', type(first_name))
if len(first_name) > 0:
first_name = first_name[0]
first_name = ''.join(first_name)
first_name = str(first_name)
else:
first_name = str('БезИмени')
print('Имя после уборки лишних знаков: ', first_name)
reg_first_names = '^\w*'
first_name = re.findall(reg_first_names, first_name)
print('Имя после обработки второй регуляркой: ', first_name)
print('Тип имени: ', type(first_name))
first_name = str(''.join(first_name))
trial_status = re.findall(reg_trial, stroke)
print('Demo? ',trial_status)
trial_status = ''.join(trial_status)
print(trial_status)
print(type(trial_status))
print('Название:', ''.join(title))
print('Фамилия: ', last_name)
title = str(''.join(title))
print('Имя: ', first_name)
if trial_status == 'Конец ознакомительного фрагмента.
':
print('Файл будет переименован: ', 'Demo' + ' ' + last_name + ' ' + first_name + ' ' + title + '.fb2')
new_file_name = str('Demo' + ' ' + last_name + ' ' + first_name + ' ' + title + '.fb2')
try:
os.rename(str(file), new_file_name)
except:
os.rename(str(file), 'copy ' + new_file_name)
else:
print('файл будет переименован: ', last_name + ' ' + first_name + ' ' + title + '.fb2')
new_file_name = str(last_name + ' ' + first_name + ' ' + title + '.fb2')
try:
os.rename(str(file), new_file_name)
except:
os.rename(str(file), 'copy ' + str(random.randrange(1, 10000)) + new_file_name)
print('Все сделано!')
Так же код доступен на GitHub по ссылке.
И как всегда — в случае возникновения вопросов и комментариев или даже идей — пишите на почту или в Telegram 🙂
Support the Blog!
Running a blog takes a lot of effort, time, and passion. Your donations help improve the content, inspire new ideas, and keep the project going.
If you’ve enjoyed the blog’s materials, any support would mean the world to me. Thank you for being here! ❤️