EbookLib
| Language | Python 3.10+ |
|---|---|
| License | AGPL-3.0 |
| Repository | github.com/aerkalov/ebooklib |
| Documentation | ebooklib.readthedocs.io |
| Depends on | lxml |
| Read / write | yes / yes (EPUB 2 and EPUB 3) |
EbookLib reads an EPUB into an EpubBook object with metadata, a list of items (chapters, images, styles, fonts), the spine and the table of contents, and writes EpubBook objects back to EPUB files. It generates the navigation document and NCX for you. It’s used by Marker, ebook2audiobook, Booktype and many text-processing tools that need the chapters of a book.
EbookLib works with the EPUB structure: chapters come back as XHTML bytes, not plain text (use BeautifulSoup or lxml to get text). It doesn’t render pages. The license is AGPL-3.0: if you use it in a network service or distribute software built on it, you must release your source code under the AGPL.
Installation#
pip install EbookLib
Basic usage: read an EPUB#
import ebooklib
from ebooklib import epub
book = epub.read_epub("book.epub")
# Dublin Core metadata: lists of (value, attributes) tuples
title = book.get_metadata("DC", "title")
authors = book.get_metadata("DC", "creator")
print("Title:", title[0][0] if title else "")
print("Authors:", [a[0] for a in authors])
print("Language:", [l[0] for l in book.get_metadata("DC", "language")])
# chapters in reading order: spine entries are (idref, linear)
for idref, _linear in book.spine:
item = book.get_item_with_id(idref)
if item is not None and item.get_type() == ebooklib.ITEM_DOCUMENT:
html = item.get_content() # bytes of the XHTML file
print(item.get_name(), len(html), "bytes")
How to extract text from an EPUB#
import ebooklib
from ebooklib import epub
from bs4 import BeautifulSoup # pip install beautifulsoup4
book = epub.read_epub("book.epub")
parts = []
for item in book.get_items_of_type(ebooklib.ITEM_DOCUMENT):
soup = BeautifulSoup(item.get_content(), "html.parser")
parts.append(soup.get_text("\n", strip=True))
text = "\n\n".join(parts)
get_items_of_type(ITEM_DOCUMENT) returns documents in manifest order; iterate book.spine (as above) for the exact reading order.
How to extract images and the cover#
import os
import ebooklib
from ebooklib import epub
book = epub.read_epub("book.epub")
os.makedirs("images", exist_ok=True)
for image in book.get_items_of_type(ebooklib.ITEM_IMAGE):
with open(os.path.join("images", os.path.basename(image.get_name())), "wb") as f:
f.write(image.get_content())
for cover in book.get_items_of_type(ebooklib.ITEM_COVER): # manifest item with properties="cover-image"
with open("cover" + os.path.splitext(cover.get_name())[1], "wb") as f:
f.write(cover.get_content())
How to read the table of contents#
book.toc is a list of epub.Link objects and (epub.Section, [children]) tuples:
def print_toc(entries, level=0):
for entry in entries:
if isinstance(entry, tuple):
section, children = entry
print(" " * level + section.title)
print_toc(children, level + 1)
else:
print(" " * level + f"{entry.title} -> {entry.href}")
print_toc(book.toc)
How to create an EPUB#
from ebooklib import epub
book = epub.EpubBook()
book.set_identifier("urn:uuid:9e2f3c1a-4b5d-4c6e-8f70-1a2b3c4d5e6f")
book.set_title("My Book")
book.set_language("en")
book.add_author("Jane Doe")
with open("cover.jpg", "rb") as f:
book.set_cover("cover.jpg", f.read())
c1 = epub.EpubHtml(title="Chapter 1", file_name="chap_01.xhtml", lang="en")
c1.content = "<h1>Chapter 1</h1><p>First chapter.</p>"
c2 = epub.EpubHtml(title="Chapter 2", file_name="chap_02.xhtml", lang="en")
c2.content = "<h1>Chapter 2</h1><p>Second chapter.</p>"
book.add_item(c1)
book.add_item(c2)
style = epub.EpubItem(uid="style", file_name="style/book.css", media_type="text/css",
content="body { font-family: serif; }")
book.add_item(style)
c1.add_item(style) # link the stylesheet from the chapter
c2.add_item(style)
book.toc = (c1, c2)
book.add_item(epub.EpubNcx()) # EPUB 2 table of contents, for older readers
book.add_item(epub.EpubNav()) # EPUB 3 navigation document
book.spine = ["nav", c1, c2]
epub.write_epub("book.epub", book)
How to change the metadata of an existing EPUB#
from ebooklib import epub
book = epub.read_epub("in.epub")
book.set_unique_metadata("DC", "title", "New Title") # replaces dc:title
book.add_metadata("DC", "publisher", "My Press")
epub.write_epub("out.epub", book)
Tips#
- Since 0.21,
write_epubraises an exception on errors instead of returningFalse. set_titleadds anotherdc:title; useset_unique_metadata("DC", "title", ...)to replace the existing one.book.get_item_with_href("text/chapter1.xhtml")finds an item by its path in the book.