import os
import sys
import zipfile
from xml.etree import ElementTree as ET
import fitz # PyMuPDF
def extract_fb2_cover(fb2_file, output_file):
try:
tree = ET.parse(fb2_file)
root = tree.getroot()
# Находим тег <coverpage>
coverpage = root.find('.//{http://www.gribuser.ru/xml/fictionbook/2.0}coverpage')
if coverpage is None:
print(f"Обложка не найдена в файле {fb2_file}")
return
# Находим тег <image> внутри <coverpage>
image = coverpage.find('.//{http://www.gribuser.ru/xml/fictionbook/2.0}image')
if image is None:
print(f"Изображение обложки не найдено в файле {fb2_file}")
return
# Извлекаем данные изображения
image_href = image.attrib.get('{http://www.w3.org/1999/xlink}href', '')
if not image_href.startswith('#'):
print(f"Некорректная ссылка на изображение в файле {fb2_file}")
return
# Находим элемент <binary> с соответствующим id
binary = root.find(f'.//{{http://www.gribuser.ru/xml/fictionbook/2.0}}binary[@id="{image_href[1:]}"]')
if binary is None:
print(f"Бинарные данные обложки не найдены в файле {fb2_file}")
return
# Декодируем и сохраняем изображение
image_data = binary.text
if image_data is None:
print(f"Нет данных изображения в файле {fb2_file}")
return
import base64
image_bytes = base64.b64decode(image_data)
with open(output_file, 'wb') as img_file:
img_file.write(image_bytes)
print(f"Обложка сохранена как {output_file}")
except Exception as e:
print(f"Ошибка при обработке файла {fb2_file}: {e}")
def extract_epub_cover(epub_file, output_file):
try:
# Открываем EPUB как ZIP-архив
with zipfile.ZipFile(epub_file, 'r') as z:
# Ищем файл с метаданными
container = z.read('META-INF/container.xml')
root = ET.fromstring(container)
rootfile = root.find('.//{urn:oasis:names:tc:opendocument:xmlns:container}rootfile')
if rootfile is None:
print(f"Файл с метаданными не найден в {epub_file}")
return
# Получаем путь к основному файлу с содержимым
content_path = rootfile.attrib['full-path']
content = z.read(content_path)
content_root = ET.fromstring(content)
# Ищем обложку в метаданных
meta_cover = content_root.find('.//{http://www.idpf.org/2007/opf}meta[@name="cover"]')
if meta_cover is None:
print(f"Обложка не найдена в метаданных файла {epub_file}")
return
cover_id = meta_cover.attrib['content']
manifest = content_root.find('.//{http://www.idpf.org/2007/opf}manifest')
if manifest is None:
print(f"Манифест не найден в файле {epub_file}")
return
# Ищем элемент с обложкой в манифесте
cover_item = manifest.find(f'.//{{http://www.idpf.org/2007/opf}}item[@id="{cover_id}"]')
if cover_item is None:
print(f"Элемент обложки не найден в манифесте файла {epub_file}")
return
cover_href = cover_item.attrib['href']
# Нормализуем путь к обложке
cover_href = cover_href.replace('\\', '/') # Заменяем обратные слэши на прямые
cover_path = os.path.normpath(os.path.join(os.path.dirname(content_path), cover_href))
cover_path = cover_path.replace('\\', '/') # Нормализуем путь для ZIP-архива
# Пытаемся прочитать обложку
try:
cover_data = z.read(cover_path)
except KeyError:
print(f"Обложка не найдена по пути {cover_path} в файле {epub_file}")
return
# Сохраняем обложку
with open(output_file, 'wb') as img_file:
img_file.write(cover_data)
print(f"Обложка сохранена как {output_file}")
except Exception as e:
print(f"Ошибка при обработке файла {epub_file}: {e}")
def extract_pdf_cover(pdf_file, output_file):
try:
# Открываем PDF-файл
doc = fitz.open(pdf_file)
# Получаем первую страницу (обычно это обложка)
page = doc.load_page(0)
# Получаем изображения со страницы
pix = page.get_pixmap()
# Сохраняем изображение
pix.save(output_file)
print(f"Обложка сохранена как {output_file}")
except Exception as e:
print(f"Ошибка при обработке файла {pdf_file}: {e}")
def main():
if len(sys.argv) == 1:
# Поиск всех .fb2, .epub и .pdf файлов в текущей папке
fb2_files = [f for f in os.listdir() if f.endswith('.fb2')]
epub_files = [f for f in os.listdir() if f.endswith('.epub')]
pdf_files = [f for f in os.listdir() if f.endswith('.pdf')]
all_files = fb2_files + epub_files + pdf_files
if not all_files:
print("Не найдено .fb2, .epub или .pdf файлов в текущей папке.")
return
# Извлечение обложек
for i, file in enumerate(all_files, start=1):
output_file = f"cover_{i:02d}.jpg"
if file.endswith('.fb2'):
extract_fb2_cover(file, output_file)
elif file.endswith('.epub'):
extract_epub_cover(file, output_file)
elif file.endswith('.pdf'):
extract_pdf_cover(file, output_file)
elif len(sys.argv) == 3:
# Извлечение обложки из указанного файла с заданным именем
input_file = sys.argv[1]
output_file = sys.argv[2]
if input_file.endswith('.fb2'):
extract_fb2_cover(input_file, output_file)
elif input_file.endswith('.epub'):
extract_epub_cover(input_file, output_file)
elif input_file.endswith('.pdf'):
extract_pdf_cover(input_file, output_file)
else:
print("Первый аргумент должен быть .fb2, .epub или .pdf файлом.")
return
else:
print("fb2cover - извлечение обложек из всех .fb2, .epub и .pdf файлов в текущей папке")
print("\nИспользование:")
print("fb2cover <имя_файла.fb2|имя_файла.epub|имя_файла.pdf> <имя_обложки.jpg> - извлечение обложки из указанного файла")
if __name__ == "__main__":
main()