Skip to main content

zh-chapter-splitter

Zero-dependency, deterministic chapter splitter for Chinese web-novel .txt files — encoding detection, rule-fusion heading recognition, and a rich quality report. No LLM, no network, pure standard library. Battle-tested on a 4.85M-character web novel.

  • No dependencies. Pure standard library (re, dataclasses, pathlib, statistics).
  • Deterministic. The same bytes always split the same way — no model, no randomness.
  • Encoding-aware. Auto-detects UTF-8, UTF-8-BOM, UTF-16 (LE/BE), GB18030, GBK, Big5.
  • Rule fusion. Preset heading rules plus one self-derived rule compete by a 5-dimension structural score; the best split wins and over-long blocks are re-scanned for missed headings.
  • Honest reports. Every split returns a diagnostics dict: confidence, problem category, per-chapter anomalies, author-note flags, weird-title flags, and ordinal gaps — nothing is silently deleted.

Install

pip install zh-chapter-splitter

Requires Python 3.10+.

Quickstart

from zh_chapter_splitter import split_chapters_with_report

text = open("novel.txt", encoding="utf-8").read()
chapters, report = split_chapters_with_report(text)

for ch in chapters[:3]:
    print(ch["chapter_number"], ch["title"], len(ch["content"]))

print(report["mode"], report["confidence"], report["problem_label"])

Split straight from a file (encoding auto-detected):

from zh_chapter_splitter import split_file

chapters, report, text = split_file("novel.txt")
print(report["encoding"])  # e.g. "gb18030"

Just detect the encoding, or just clean the text:

from zh_chapter_splitter import decode_bytes, clean_text

text, encoding = decode_bytes(open("novel.txt", "rb").read())
cleaned = clean_text(text)  # strip pirate ads / mojibake, normalize whitespace

Each chapter is a plain dict:

{
    "title": str,                    # heading line, e.g. "第12章 归途"
    "content": str,                  # chapter body
    "chapter_number": int,           # 1-based, contiguous
    "volume_title": str,             # owning volume heading, or ""
    "is_author_note": bool,          # author's aside (leave note / afterword)
    "exclude_from_extraction": bool, # == is_author_note
    "title_confidence": float,       # 0..1; low means a meme/quip title
    "content_descriptor": str,       # first-sentence descriptor for low-confidence titles
}

API

Function Signature Description
split_chapters_with_report (text, *, split_rule="auto", custom_pattern="", source_name="", title="") -> (list[dict], dict) Split text into chapters and return a diagnostics report.
split_chapters (text, ...) -> list[dict] Same, chapters only.
split_file (path, *, split_rule="auto", custom_pattern="", title="") -> (list[dict], dict, str) Read a file, auto-detect encoding, split; report includes encoding.
decode_bytes (content: bytes) -> (str, str) Detect encoding and decode to (text, encoding_label).
clean_text (text: str) -> str Normalize whitespace and strip pirate ads / mojibake.
build_custom_pattern (template: str) -> re.Pattern | None Compile a *-template or raw regex into a heading pattern (ReDoS-guarded).

Lower-level building blocks are also exported: sanitize_corpus, sanitize_corpus_text, filter_non_content, annotate_weird_titles, adaptive_split, structural_score, split_by_heading_regex, extract_seq, build_candidate_rules, and the ChapterSplitter class (with its chapter_splitter singleton).

Split rules

split_rule defaults to "auto" (rule fusion). You can also force a preset: chapter_cn, corpus, chapter_en, number_dot, paren_num, or custom (with custom_pattern, where * stands for a chapter number, e.g. 卷一-第*章).

Command line

Installs a zh-chapter-split console script (pure argparse):

# Split into one .txt per chapter plus a report.json.
zh-chapter-split novel.txt -o out/

# Print the chapter-title list only, write nothing.
zh-chapter-split novel.txt --preview

# Force a preset rule or a custom template.
zh-chapter-split novel.txt -o out/ --split-rule chapter_cn
zh-chapter-split novel.txt -o out/ --split-rule custom --custom-pattern "卷一-第*章"

How it works

  1. Decode & clean. Detect the encoding (BOM-aware), normalize newlines and full-width spaces, then delete whole advertising lines, strip inline promo fragments, and drop garbled (mojibake) lines — all deterministically.
  2. Split. In auto mode, rule-fusion adaptive splitting competes against a set of built-in detectors (numbered sections, pagination headings, strong / weak headings, fixed-window fallback). Candidates are ranked by a 5-dimension structural score (ordinal continuity, size uniformity, count sanity, marker consistency, coverage) and the winner is chosen.
  3. Post-process & annotate. Drop empty ghost chapters, window over-long blocks, dedupe exact repeats, then flag author notes and weird titles and reconcile ordinal gaps.
  4. Report. Return the chapters plus a diagnostics dict for human review.

License

MIT — see LICENSE.

Acknowledgements

Extracted from the RPG Roleplay platform (https://github.com/felixchaos/rpg-roleplay-platform). 中文说明见 README.zh-CN.md.

Metadata

Release files for zh-chapter-splitter 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for zh-chapter-splitter 0.1.0
File Size Uploaded Provenance Actions
zh_chapter_splitter-0.1.0.tar.gz 42.1 kB With provenance Details for zh_chapter_splitter-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for zh-chapter-splitter 0.1.0
File Interpreter ABI Platform Actions
zh_chapter_splitter-0.1.0-py3-none-any.whl Python 3 none any Details for zh_chapter_splitter-0.1.0-py3-none-any.whl

Total release size: 76.7 kB

Release files / zh_chapter_splitter-0.1.0.tar.gz

Download URL zh_chapter_splitter-0.1.0.tar.gz
Size 42.1 kB
Tags Source
SHA-256 checksum
How to use checksums
5b4cdd9b7d683c9e16ff06ddf988b6b4fdccea4ec04f06acdd7ec42cba958a09
BLAKE2b-256 checksum
How to use checksums
473a04773732f2a2d05a1e1ec2b30eee89503f0adc5e85f4f526b377fd25fb68
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 14, 2026.

Transparency log

Release files / zh_chapter_splitter-0.1.0-py3-none-any.whl

Download URL zh_chapter_splitter-0.1.0-py3-none-any.whl
Size 34.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
47b9b9c21141cdca8b28df5d527c0dc378937932cbb3ca7860bd5f72a6889539
BLAKE2b-256 checksum
How to use checksums
57b154d1a85cad906ef58dd5e80af919cbb4cf1ce6cefe77a46ca491f5f170fa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 14, 2026.

Transparency log

Security for zh-chapter-splitter 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for zh_chapter_splitter-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 14, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page