import os
import sys
import zipfile
import subprocess
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 = root.find('.//{http://www.gribuser.ru/xml/fictionbook/2.0}coverpage')
if coverpage is None:
print(f"Обложка не найдена в файле {fb2_file}")
return
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 = 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:
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('\\', '/')
try:
cover_data = z.read(cover_path)
with open(output_file, 'wb') as img_file:
img_file.write(cover_data)
print(f"Обложка сохранена как {output_file}")
except KeyError:
print(f"Обложка не найдена по пути {cover_path} в файле {epub_file}")
except Exception as e:
print(f"Ошибка при обработке файла {epub_file}: {e}")
def extract_pdf_cover(pdf_file, output_file):
try:
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 extract_djvu_cover(djvu_file, output_file):
try:
# Создаем временный TIFF файл
temp_tiff = output_file + '.tiff'
# Используем ddjvu для извлечения первой страницы
subprocess.run(['ddjvu', '--format=tiff', '--page=1', djvu_file, temp_tiff], check=True)
# Конвертируем TIFF в JPG
from PIL import Image
with Image.open(temp_tiff) as img:
img.save(output_file, 'JPEG')
# Удаляем временный TIFF файл
os.remove(temp_tiff)
print(f"Обложка сохранена как {output_file}")
except subprocess.CalledProcessError as e:
print(f"Ошибка при обработке DJVU файла {djvu_file}: {e}")
except Exception as e:
print(f"Ошибка при конвертации обложки {djvu_file}: {e}")
finally:
if os.path.exists(temp_tiff):
try:
os.remove(temp_tiff)
except:
pass
def main():
if len(sys.argv) == 1:
# Поиск всех поддерживаемых файлов в текущей папке
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')]
djvu_files = [f for f in os.listdir() if f.endswith('.djvu')]
all_files = fb2_files + epub_files + pdf_files + djvu_files
if not all_files:
print("Не найдено файлов поддерживаемых форматов (.fb2, .epub, .pdf, .djvu)")
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 file.endswith('.djvu'):
extract_djvu_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)
elif input_file.endswith('.djvu'):
extract_djvu_cover(input_file, output_file)
else:
print("Поддерживаются только файлы .fb2, .epub, .pdf и .djvu")
return
else:
print("fb2cover - извлечение обложек из файлов поддерживаемых форматов")
print("\nИспользование:")
print("fb2cover - извлечение обложек из всех файлов в текущей папке")
print("fb2cover <input_file> <output_file> - извлечение обложки из указанного файла")
if __name__ == "__main__":
main()