最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

python - How to use ebooklib to create a nested chapter hierarchy? - Stack Overflow

programmeradmin0浏览0评论

I am trying to create an EPUB that has a nested chapter structure. There are top-level sections, with sub-chapters, and then subheadings below those sub-chapters. I would like this to be reflected in the TOC. Here is an example of what it looks like:

Section 1

Here is some preamble about what is going to happen in Chapter 1

Chapter 1

This is the contents of Section 1, Chapter 1.

Chapter 2

This is the contents of Section 1, Chapter 2.

Section 2

Preamble for section 2.

Chapter 1

Section 2, Chapter 1.

I have created this MWE that I think should represent the structure I want:

# /// script
# dependencies = [
#    "ebooklib"
# ]
# ///

from ebooklib import epub


def create_epub():
    book = epub.EpubBook()
    book.set_title("Minimal EPUB Example")
    book.set_language("en")
    book.add_author("Author Name")

    # Section 1
    section1_preamble = epub.EpubHtml(
        title="Section 1 Preamble",
        file_name="section1_preamble.xhtml",
        content="<h1>Section 1</h1><p>Preamble text...</p>",
    )
    chapter1 = epub.EpubHtml(
        title="Chapter 1",
        file_name="chapter1.xhtml",
        content="<h2>Chapter 1</h2><p>Content of Chapter 1</p>",
    )
    chapter2 = epub.EpubHtml(
        title="Chapter 2",
        file_name="chapter2.xhtml",
        content="<h2>Chapter 2</h2><p>Content of Chapter 2</p>",
    )

    # Section 2
    chapter3 = epub.EpubHtml(
        title="Chapter 1 (Section 2)",
        file_name="chapter3.xhtml",
        content="<h2>Chapter 1 (Section 2)</h2><p>Content of Chapter 1 in Section 2</p>",
    )

    # Add chapters to book
    for item in [section1_preamble, chapter1, chapter2, chapter3]:
        book.add_item(item)

    # Define table of contents with nesting
    book.toc = (
        (epub.Section("Section 1"), [section1_preamble, chapter1, chapter2]),
        (epub.Section("Section 2"), [chapter3]),
    )

    # Define book spine
    book.spine = ["nav", section1_preamble, chapter1, chapter2, chapter3]

    # Add navigation files
    book.add_item(epub.EpubNcx())
    book.add_item(epub.EpubNav())

    # Write to file
    epub.write_epub("minimal_epub.epub", book, {})
    print("EPUB created: minimal_epub.epub")


if __name__ == "__main__":
    create_epub()

However, the EPUB this creates doesn't work quite right:

There are three problems I'm having with this:

  1. The "Section" links don't work (I get a "Destination does not exist" error)
  2. I would prefer it if the "preamble" text were not its own chapter. I want the "Section" link to be a chapter with sub-chapters.
  3. I would like it if there were not an enforced page break after each sub-chapter, and certainly not after the preamble. The way I've got it structured now, "Section 1 Preamble" points to this:

But I would like it if "Chapter 1" were a subheading here, directly under "Preamble text". There can still be enforced page breaks at the end of a section.

I am trying to create an EPUB that has a nested chapter structure. There are top-level sections, with sub-chapters, and then subheadings below those sub-chapters. I would like this to be reflected in the TOC. Here is an example of what it looks like:

Section 1

Here is some preamble about what is going to happen in Chapter 1

Chapter 1

This is the contents of Section 1, Chapter 1.

Chapter 2

This is the contents of Section 1, Chapter 2.

Section 2

Preamble for section 2.

Chapter 1

Section 2, Chapter 1.

I have created this MWE that I think should represent the structure I want:

# /// script
# dependencies = [
#    "ebooklib"
# ]
# ///

from ebooklib import epub


def create_epub():
    book = epub.EpubBook()
    book.set_title("Minimal EPUB Example")
    book.set_language("en")
    book.add_author("Author Name")

    # Section 1
    section1_preamble = epub.EpubHtml(
        title="Section 1 Preamble",
        file_name="section1_preamble.xhtml",
        content="<h1>Section 1</h1><p>Preamble text...</p>",
    )
    chapter1 = epub.EpubHtml(
        title="Chapter 1",
        file_name="chapter1.xhtml",
        content="<h2>Chapter 1</h2><p>Content of Chapter 1</p>",
    )
    chapter2 = epub.EpubHtml(
        title="Chapter 2",
        file_name="chapter2.xhtml",
        content="<h2>Chapter 2</h2><p>Content of Chapter 2</p>",
    )

    # Section 2
    chapter3 = epub.EpubHtml(
        title="Chapter 1 (Section 2)",
        file_name="chapter3.xhtml",
        content="<h2>Chapter 1 (Section 2)</h2><p>Content of Chapter 1 in Section 2</p>",
    )

    # Add chapters to book
    for item in [section1_preamble, chapter1, chapter2, chapter3]:
        book.add_item(item)

    # Define table of contents with nesting
    book.toc = (
        (epub.Section("Section 1"), [section1_preamble, chapter1, chapter2]),
        (epub.Section("Section 2"), [chapter3]),
    )

    # Define book spine
    book.spine = ["nav", section1_preamble, chapter1, chapter2, chapter3]

    # Add navigation files
    book.add_item(epub.EpubNcx())
    book.add_item(epub.EpubNav())

    # Write to file
    epub.write_epub("minimal_epub.epub", book, {})
    print("EPUB created: minimal_epub.epub")


if __name__ == "__main__":
    create_epub()

However, the EPUB this creates doesn't work quite right:

There are three problems I'm having with this:

  1. The "Section" links don't work (I get a "Destination does not exist" error)
  2. I would prefer it if the "preamble" text were not its own chapter. I want the "Section" link to be a chapter with sub-chapters.
  3. I would like it if there were not an enforced page break after each sub-chapter, and certainly not after the preamble. The way I've got it structured now, "Section 1 Preamble" points to this:

But I would like it if "Chapter 1" were a subheading here, directly under "Preamble text". There can still be enforced page breaks at the end of a section.

Share Improve this question asked Feb 6 at 15:07 PaulPaul 10.9k14 gold badges54 silver badges93 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

So I think I actually figured this out, and all three are solved by:

  1. Using epub.Link or a tuple of epub.Link and a tuple of epub.Link objects pointing to sub-chapters (recursively, for further hierarchies).
  2. Instead of using epub.EpubHtml items for each chapter, concatenating the chapter contents into the top-level chapter and manually adding an <a name="unique-anchor-here"> tag to the chapter heading. which is the target of the links.

Here's an updated MWE:

# /// script
# dependencies = [
#    "ebooklib"
# ]
# ///

from ebooklib import epub


def create_epub():
    book = epub.EpubBook()
    book.set_title("Minimal EPUB Example")
    book.set_language("en")
    book.add_author("Author Name")

    # Section 1
    section1 = epub.EpubHtml(
        title="Section 1",
        file_name="section1.xhtml",
        content="<a name='section1'><h1>Section 1</h1><p>Preamble text...</p>\n" +
                "<a name='section1-chapter1'><h2>Chapter 1</h2><p>Content of Chapter 1</p>\n" +
                "<a name='section1-chapter1'><h2>Chapter 2</h2><p>Content of Chapter 2</p>",
    )

    # Section 2
    chapter3 = epub.EpubHtml(
        title="Chapter 1 (Section 2)",
        file_name="chapter3.xhtml",
        content="<h2>Chapter 1 (Section 2)</h2><p>Content of Chapter 1 in Section 2</p>",
    )

    # Add chapters to book
    for item in [section1, chapter3]:
        book.add_item(item)

    # Define table of contents with Link
    book.toc = [
        (epub.Link("section1.xhtml", "Section 1", "sec1"), (
            epub.Link("section1.xhtml#section1-chapter1", "Chapter 1", "chap1"),
            epub.Link("section1.xhtml#section1-chapter2", "Chapter 2", "chap2"),
        )),
        epub.Link("chapter3.xhtml", "Chapter 1 (Section 2)", "chap3"),
    ]

    # Define book spine
    book.spine = ["nav", section1, chapter3]

    # Add navigation files
    book.add_item(epub.EpubNcx())
    book.add_item(epub.EpubNav())

    # Write to file
    epub.write_epub("minimal_epub_link.epub", book, {})
    print("EPUB created: minimal_epub_link.epub")


if __name__ == "__main__":
    create_epub()
发布评论

评论列表(0)

  1. 暂无评论