comicbox
| Language | Python (3.11+) |
|---|---|
| License | LGPL-3.0 |
| Repository | github.com/ajslater/comicbox |
| Documentation | comicbox.readthedocs.io |
| Depends on | Python packages (py7zr, rarfile, Pillow, marshmallow, ...); the unrar binary for CBR |
| Read / write | yes / yes (pages and metadata; writes ComicInfo.xml and other metadata into CBZ) |
comicbox is a comic book library and command line tool. It opens CBZ, CBR, CB7, CBT and PDF comics, finds the page images, picks the cover, and reads every common metadata format: ComicInfo.xml, MetronInfo.xml, ComicBookInfo (ZIP comment), CoMet and metadata parsed from the file name. It merges them into one normalized dictionary and can write any of them back. It’s the metadata engine of the Codex comic server.
Use comicbox when you work with comic metadata; use zipfile when you only need the pages and want no dependencies. comicbox sorts pages by case-insensitive name, not natural order, so zero-padded names (001.jpg) matter.
Installation#
pip install comicbox
# with PDF support
pip install "comicbox[pdf]"
Basic usage: pages, cover and metadata#
from comicbox.box import Comicbox
with Comicbox("Batman 001.cbz") as cb:
print(cb.get_file_type()) # "CBZ"
print(cb.get_page_count(), "pages")
for name in cb.get_page_filenames():
print(name)
md = cb.to_dict()["comicbox"] # merged metadata from all sources
print(md.get("series", {}).get("name"), md.get("issue", {}).get("name"), md.get("title"))
cover = cb.get_cover_page() # bytes of the cover image
with open("cover.jpg", "wb") as f:
f.write(cover)
get_cover_page() honors a FrontCover page in ComicInfo.xml and falls back to the first page.
How to read a page by index#
with Comicbox("comic.cbz") as cb:
data = cb.get_page_by_index(0) # bytes, or None if out of range
name = cb.get_pagename(0) # file name inside the archive
for page in cb.get_pages(page_from=0, page_to=4): # first five pages, as bytes
print(len(page))
How to get ComicInfo.xml as XML#
to_string serializes the merged metadata in any supported format:
from comicbox.box import Comicbox
from comicbox.formats import MetadataFormats
with Comicbox("comic.cbz") as cb:
print(cb.to_string(MetadataFormats.COMIC_INFO)) # ComicInfo.xml text
print(cb.to_string(MetadataFormats.METRON_INFO)) # MetronInfo.xml text
How to write ComicInfo.xml into a CBZ#
write_metadata merges a patch into the existing metadata and rewrites the archive:
from comicbox.write import write_metadata
result = write_metadata(
"Batman 001.cbz",
{"series": {"name": "Batman"}, "publisher": {"name": "DC Comics"}, "genres": ["Superhero"]},
formats=["COMIC_INFO"],
)
print(result.written)
Command line#
comicbox -p comic.cbz # print merged metadata
comicbox -X --dest-path ./out comic.cbz # extract the cover
comicbox -x 0:5 --dest-path ./out comic.cbz # extract pages 0-5
comicbox -m "{publisher: DC Comics}" -w cix comic.cbz # write ComicInfo.xml
comicbox -z comic.cbr # convert CBR/CB7/CBT to CBZ
Tips#
- All errors derive from
comicbox.exceptions.ComicboxError; catch it when scanning a large library. - Pass a config to
Comicbox(path, config=...)to restrict which metadata formats are read; reading fewer formats is faster on big libraries. - comicbox can’t create a CBZ from a folder of images; use zipfile for that, then write metadata with comicbox.