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 / converts to CBZ (7z archives can't be rewritten; writing metadata produces a 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, CoMet and metadata parsed from the file name. It merges them into one normalized dictionary. It’s the metadata engine of the Codex comic server. CB7 support uses py7zr (pure Python), so no external tool is needed.
comicbox doesn’t write 7z archives. When you write metadata to a CB7 file, it repacks the comic as a CBZ next to the original. 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.cb7") as cb:
print(cb.get_file_type()) # "CB7"
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.cb7") 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.cb7") 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 metadata (converts to CBZ)#
write_metadata merges a patch into the existing metadata. For a CB7 file it writes a new CBZ and reports its path in final_path; the original file is left in place:
from comicbox.write import write_metadata
result = write_metadata(
"Batman 001.cb7",
{"series": {"name": "Batman"}, "publisher": {"name": "DC Comics"}},
formats=["COMIC_INFO"],
)
print(result.written, result.final_path) # True Batman 001.cbz
comicbox.predict.predict_write_destination(path) tells you where a write would land before doing it.
Command line#
comicbox -p comic.cb7 # print merged metadata
comicbox -X --dest-path ./out comic.cb7 # extract the cover
comicbox -x 0:5 --dest-path ./out comic.cb7 # extract pages 0-5
comicbox -z comic.cb7 # convert to CBZ, keeping metadata
Tips#
- All errors derive from
comicbox.exceptions.ComicboxError; catch it when scanning a large library. - Convert without changing metadata with
comicbox -z comic.cb7. - To create comics from a folder of images, write a CBZ with zipfile.