kiwilan/php-ebook

PHP包,用于读取电子书、漫画和有声书的元数据以及提取封面。

资助包维护!
kiwilan


README

Banner with eReader picture in background and PHP eBook title

php version downloads license tests codecov

PHP包,用于读取电子书、漫画和有声书的元数据以及提取封面。

因为元数据是抵御混乱的关键。

  • 电子书:.epub.pdf.azw.azw3.kf8.kfx.mobi.prc.fb2
  • 漫画:.cbz.cbr.cb7.cbt(来自 github.com/anansi-project 的元数据)
  • 有声书:.mp3.m4a.m4b.flac.ogg,需要外部包kiwilan/php-audio必须单独安装)

了解更多,请参阅支持的格式支持Linux、macOS和Windows。

注意

此包偏好于使用原生PHP解析的开放格式电子书,如.epub(来自IDPF)或.cbz(来自CBA),因此为了获得最佳体验,我们建议将使用的电子书转换为这些格式。如果您想了解更多关于电子书生态系统,可以阅读文档

警告

对于带有DRM(数字版权管理)的电子书,在某些情况下,您可以读取元数据但不能读取内容(例如EPUB的HTML文件)。要使用所有功能,您必须在使用此包之前使用软件去除DRM。对于EPUB,您可以使用calibre配合DeDRM插件本指南可以帮助您。

关于

此包是为bookshelves-project/bookshelves构建的,这是一个用于处理电子书的Web应用。

要求

  • PHP版本 >=8.1
  • PHP扩展:
    • zip(原生,可选)用于.EPUB.CBZ
    • phar(原生,可选)用于.CBT
    • rar(可选)用于.CBR(可以使用p7zip二进制文件代替)
    • imagick(可选)用于.PDF封面
    • intl(原生,可选)用于Transliterator以获得更好的slugify功能
    • fileinfo(原生,可选)用于更好地检测文件类型
  • 二进制文件
    • p7zip(可选)用于.CB7(也可以处理.CBR
  • 有声书
  • 想了解更多需求,请参阅支持的格式

注意

只有当您想读取这些格式的元数据时,才需要安装需求,例如,如果您想从.cbr文件中读取元数据,您必须安装rar PHP扩展p7zip二进制文件。因此,PHP扩展和二进制文件的所有需求都是可选的。

警告

使用kiwilan/php-archive处理存档,对于某些格式(如.cbr.cb7),可能需要rar PHP扩展p7zip二进制文件。有关安装这些需求的指南,请参阅kiwilan/php-archive

功能

  • 支持多种格式,请参阅支持的格式
  • 🔎 从电子书、漫画和有声书中读取元数据
  • 🖼️ 从电子书、漫画和有声书中提取封面
  • 🎵 如果安装了kiwilan/php-audio,则支持有声书
  • 📚 支持元数据
  • 🔖 提取章节(仅限EPUB
  • 📦 支持创建EPUBCBZ

路线图

  • 更好的.epub创建支持
  • 添加.epub元数据更新支持
  • 添加更好的MOBI文件处理:来自Calibre的libmobiebook-convert(备选方案可用)
  • 添加对Calibre的ebook-convert的支持
  • 添加对DJVU的支持:djvulibre

安装

您可以通过composer安装此包

composer require kiwilan/php-ebook

用法

使用电子书文件或有声书*文件(有关格式的更多信息,请参阅支持的格式)。

*:应单独安装,请参阅需求

use Kiwilan\Ebook\Ebook;

$ebook = Ebook::read('path/to/ebook.epub');

$ebook->getPath(); // string => path to ebook
$ebook->getFilename(); // string => filename of ebook
$ebook->getExtension(); // string => extension of ebook
$ebook->getTitle(); // string
$ebook->getAuthors(); // BookAuthor[] (`name`: string, `role`: string)
$ebook->getAuthorMain(); // ?BookAuthor => First BookAuthor (`name`: string, `role`: string)
$ebook->getDescription(); // ?string
$ebook->getCopyright(); // ?string
$ebook->getPublisher(); // ?string
$ebook->getIdentifiers(); // BookIdentifier[] (`value`: string, `scheme`: string)
$ebook->getPublishDate(); // ?DateTime
$ebook->getLanguage(); // ?string
$ebook->getTags(); // string[] => `subject` in EPUB, `keywords` in PDF, `genres` in CBA
$ebook->getSeries(); // ?string => `calibre:series` in EPUB, `series` in CBA
$ebook->getVolume(); // ?int => `calibre:series_index` in EPUB, `number` in CBA
$ebook->getCreatedAt(); // ?DateTime => file modified date
$ebook->getSize(); // int => file size in bytes
$ebook->getSizeHumanReadable(); // string => file size in human readable format

对于高级描述解析,您可以使用getDescriptionAdvanced()方法与BookDescription类一起使用。

use Kiwilan\Ebook\Ebook;

$ebook = Ebook::read('path/to/ebook.epub');

$description = $ebook->getDescriptionAdvanced(); // BookDescription

$description->getDescription(); // string => raw description
$description->toHtml(?int $limit = null); // string => description formatted to HTML
$description->toString(?int $limit = null); // string => description formatted to plain text
$description->toStringMultiline(?int $limit = null); // string => description formatted to plain text with new lines

对于页数,您可以使用以下方法

$ebook->getPagesCount(); // ?int => estimated pages count (250 words by page) in `EPUB`, `pageCount` in PDF, `pageCount` in CBA
$ebook->getWordsCount(); // ?int => words count in `EPUB`

注意

出于性能原因,在EPUB中,pagesCountwordsCount仅在请求时可用。如果您使用var_dump检查电子书,这些属性将为null

一些元数据可以通过extras()方法存储,无需输入,直接从元数据中获取。

$ebook->getExtras(); // array<string, mixed> => additional data for book
$ebook->getExtra(string $key); // mixed => safely extract data from `extras` array

注意

对于有声书,所有元数据都存储在extras数组中,您将发现与Ebook::class属性重复。有关更多信息,请参阅格式规范

要判断电子书是否有效,您可以使用在read()之前调用的isValid()静态方法。

use Kiwilan\Ebook\Ebook;

$isValid = Ebook::isValid('path/to/ebook.epub');

要获取附加数据,您可以使用以下方法

$ebook->getParser(); // ?EbookParser => Parser with modules
$ebook->getMetaTitle(); // ?MetaTitle, with slug for `title` and `series`
$ebook->getFormat(); // ?EbookFormatEnum => `epub`, `pdf`, `cba`
$ebook->getCover(); // ?EbookCover => cover of book

要访问电子书的存档,您可以使用getArchive()方法。您可以在kiwilan/php-archive中找到有关存档的更多信息。

$ebook->getArchive(); // ?BaseArchive => archive of book from `kiwilan/php-archive`

并且要测试某些数据是否存在

$ebook->isArchive(); // bool => `true` if `EPUB`, `CBA`
$ebook->isMobi(); // bool => `true` if Mobipocket derivatives
$ebook->isAudio(); // bool => `true` if `mp3`, `m4a`, `m4b`, `flac`, `ogg`
$ebook->hasCover(); // bool => `true` if cover exists
$ebook->hasMetadata(); // bool => `true` if metadata exists
$ebook->hasSeries(); // bool => `true` if series exists
$ebook->isBadFile(); // bool => `true` if file is not readable

元数据

Ebook::class包含许多信息,但如果您想访问原始元数据,则可以使用metadata()方法。

use Kiwilan\Ebook\Ebook;

$ebook = Ebook::read('path/to/ebook.epub');

$parser = $ebook->getParser();

$parser->getModule(); // Used into parsing can be any of `EbookModule::class`

$parser->getAudiobook(); // `AudiobookModule::class`
$parser->getCba(); // `CbaModule::class`
$parser->getEpub(); // `EpubModule::class`
$parser->getFb2(); // `Fb2Module::class`
$parser->getMobi(); // `MobiModule::class`
$parser->getPdf(); // `PdfModule::class`

$parser->isAudiobook(); // bool
$parser->isCba(); // bool
$parser->isEpub(); // bool
$parser->isFb2(); // bool
$parser->isMobi(); // bool
$parser->isPdf(); // bool

MetaTitle

如果书的标题不为空,则可以设置。

use Kiwilan\Ebook\Ebook;

$ebook = Ebook::read('path/to/ebook.epub');
$metaTitle = $ebook->getMetaTitle(); // ?MetaTitle

$metaTitle->getSlug(); // string => slug title, like `lord-of-the-rings-en-01-fellowship-of-the-ring-j-r-r-tolkien-1954-epub`
$metaTitle->getSeriesSlug(); // ?string => slug series title, like `lord-of-the-rings-en`

您可以使用MetaTitle::class自定义slug。

$meta->getSlug(removeDeterminers: true, addSeries: true, addVolume: true, addAuthor: true, addYear: true, addExtension: true, addLanguage: true);
$meta->getSeriesSlug(removeDeterminers: true, addAuthor: false, addExtension: false, addLanguage: true);

封面

封面可以从中提取电子书。

use Kiwilan\Ebook\Ebook;

$ebook = Ebook::read('path/to/ebook.epub');
$cover = $ebook->getCover(); // ?EbookCover

$cover->getPath(); // ?string => path to cover
$cover->getContents(bool $toBase64 = false); // ?string => content of cover, if `$toBase64` is true, return base64 encoded content

注意

格式规范

有声书

对于有声书,您必须单独安装kiwilan/php-audio

规范基于audiobookshelfID3标签。音频文件上的元数据将按以下方式映射("/"后的第二个标签是后备)

Audio::class的属性如下

  • 作者命名以及多个作者通过,;&and分隔。
  • ** 标签可以包含多个标签,通过///;分隔。例如:"Science Fiction/Fiction/Fantasy"。

您可以在Ebook::classgetExtras()数组中找到所有元数据。

EPUB

对于EPUB,元数据是从OPF文件、META-INF/container.xml文件中提取的,您也可以访问这些元数据,但您还可以从NCX文件中获取章节。通过使用chapters()方法,您可以将NCXHTML章节合并以获取带有labelsourcecontent的完整书籍章节。

use Kiwilan\Ebook\Ebook;

$ebook = Ebook::read('path/to/ebook.epub');

$epub = $ebook->getParser()?->getEpub();

$epub->getContainer(); // ?EpubContainer => {`opfPath`: ?string, `version`: ?string, `xml`: array}
$epub->getOpf(); // ?OpfItem => {`metadata`: array, `manifest`: array, `spine`: array, `guide`: array, `epubVersion`: ?int, `filename`: ?string, `dcTitle`: ?string, `dcCreators`: BookAuthor[], `dcContributors`: BookContributor[], `dcDescription`: ?string, `dcPublisher`: ?string, `dcIdentifiers`: BookIdentifier[], `dcDate`: ?DateTime, `dcSubject`: string[], `dcLanguage`: ?string, `dcRights`: array, `meta`: BookMeta[], `coverPath`: ?string, `contentFile`: string[]}
$epub->getNcx(); // ?NcxItem => {`head`: NcxItemHead[]|null, `docTitle`: ?string, `navPoints`: NcxItemNavPoint[]|null, `version`: ?string, `lang`: ?string}
$epub->getChapters(); // EpubChapter[] => {`label`: string, `source`: string, `content`: string}[]
$epub->getHtml(); // EpubHtml[] => {`filename`: string, `head`: ?string, `body`: ?string}[]
$epub->getFiles(); // string[] => all files in EPUB

注意

出于性能原因,ncxhtmlchapters只在需要时才可用。如果您使用var_dump来检查元数据,则这些属性将为null

创建

您可以使用create()静态方法创建EPUB或CBZ文件。

注意

仅支持创建EPUBCBZ

use Kiwilan\Ebook\Ebook;

$creator = Ebook::create('path/to/ebook.epub');

// Build manually
$creator->addFromString('mimetype', 'application/epub+zip')
    ->addFromString('META-INF/container.xml', '<?xml version="1.0" encoding="UTF-8" standalone="no" ?><container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container"><rootfiles><rootfile full-path="OEBPS/content.opf" media-type="application/oebps-package+xml"/></rootfiles></container>')
    ->save();

// Build from files
$creator->addFile('mimetype', 'path/to/mimetype')
    ->addFile('META-INF/container.xml', 'path/to/container.xml')
    ->save();

// Build from directory
$creator->addDirectory('./', 'path/to/directory')
    ->save();

支持格式

电子书和漫画有很多不同的格式,如果您想了解更多

MOBI封面注释

Mobipocket文件及其衍生文件(.mobi.prc.azw.azw3.kf8.kfx)可以嵌入封面图片。使用php-ebook的本地解决方案可以提取封面,但分辨率不高。最佳解决方案是使用calibre转换文件并使用EPUB格式。

测试

composer test

变更日志

请参阅变更日志获取更多关于最近更改的信息。

鸣谢

许可协议

MIT 许可协议 (MIT)。请参阅许可文件获取更多信息。