フリー小説をKindleの縦書きファイルへ変換する(3)※小説家になろう版

  1. はじめに
  2. 1話ごとのテキストを、一括でダウンロード
  3. Powershellで、1つのファイル(EPUB)を生成
    1. 青空文庫 版
  4. Kindle PreviewerでMOBIファイルへ変換し、USB接続でKindleへ転送

Powershellで、1つのファイル(EPUB)を生成

以下のPowerShellを使えば、実行するだけで、epubファイルが生成されます。

実行する際のファイル構成

実行する際の注意点

  • 検証済環境:Windows10、PowerShell Ver. 5.1.19041.2364
  • txts2epub.ps1の文字コード=Shift-JIS
  • 作業フォルダは英数字のフォルダで作業してください
  • あたり前ですが、ZIPファイルは解凍してください。ZIPファイルのままでは、powershellは実行できません。
txts2epub.ps1

下記のテキストをテキストエディタにコピー&ペーストして
「txts2epub.ps1」と言うファイル名で保存します。

###########################################################
# Title:  小説になろうのテキスト群を、結合してepubファイルにする
# Created:2023/03/05

# Usage:
# > Powershell 実行方法
# > PowerShell -ExecutionPolicy RemoteSigned -file .\txts2epub.ps1 "title"

# File Tree:
#  book.epub = zip
#   ├ META-INF
#   │  └ container.xml
#   ├ OEBPS
#   │  ├ book.html
#   │  ├ content.opf
#   │  └ toc.ncx
#   └ mimetype
###########################################################
$fileList  = Get-ChildItem -Name 第*.txt | Sort-Object LastWriteTime
$outFile   = 'book\OEBPS\book.html'  # 結合後のファイル名

if([string]::IsNullorEmpty($Args[0])){
  Write-Host "Usage: PowerShell -ExecutionPolicy RemoteSigned -file .\txts2epub.ps1 `"title`""
  Write-Host "" 
  exit
}
$htmlTitle = $Args[0]
Write-Host "Titile  :" $htmlTitle
$uuid = "txts2epub-" + ( Get-Date -Format "yyyyMMdd-HHmmss" )
$htmlHeader = "<html>
<head>
<title>" + $htmlTitle + "</title>
<meta http-equiv=`"Content-Type`" content=`"text/html; charset=utf-8`" />
<style type=`"text/css`">
    <!--
        body, h1, p {
            writing-mode: vertical-rl;
            text-orientation: upright;
            -webkit-writing-mode:vertical-rl;
            -epub-writing-mode:vertical-rl;
            -moz-writing-mode:vertical-rl;
            -o-writing-mode:vertical-rl;
        }
    -->
</style>    
</head>
<body>"
$htmlFooter = "</body>
</html>"

$opfBody = "<?xml version=`"1.0`" encoding=`"utf-8`"?>
<package version=`"2.0`" unique-identifier=`"BookId`" xmlns=`"http://www.idpf.org/2007/opf`">
  <metadata xmlns:dc=`"http://purl.org/dc/elements/1.1/`" xmlns:opf=`"http://www.idpf.org/2007/opf`">
    <meta content=`"horizontal-rl`" name=`"primary-writing-mode`"/>
    <dc:identifier id=`"BookId`" opf:scheme=`"UUID`">urn:uuid:" + $uuid + "</dc:identifier>
    <dc:language>ja</dc:language>
    <dc:title>" + $htmlTitle + "</dc:title>
    <dc:date opf:event=`"modification`" xmlns:opf=`"http://www.idpf.org/2007/opf`">" + ( Get-Date -UFormat "%Y-%m-%d" ) + "</dc:date>
  </metadata>
  <manifest>
    <item id=`"book.html`" href=`"book.html`" media-type=`"application/xhtml+xml`"/>
    <item id=`"ncx`" href=`"toc.ncx`" media-type=`"application/x-dtbncx+xml`"/>
  </manifest>
  <spine toc=`"ncx`">
    <itemref idref=`"book.html`"/>
  </spine>
</package>"

$containerBody = "<?xml version=`"1.0`" encoding=`"UTF-8`"?>
<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>"

$ncxBody = "<?xml version=`"1.0`" encoding=`"utf-8`"?>
<!DOCTYPE ncx PUBLIC `"-//NISO//DTD ncx 2005-1//EN`"
   `"http://www.daisy.org/z3986/2005/ncx-2005-1.dtd`">
<ncx xmlns=`"http://www.daisy.org/z3986/2005/ncx/`" version=`"2005-1`">
  <head>
    <meta name=`"dtb:uid`" content=`"urn:uuid:" + $uuid + "`" />
    <meta name=`"dtb:depth`" content=`"0`" />
    <meta name=`"dtb:totalPageCount`" content=`"0`" />
    <meta name=`"dtb:maxPageNumber`" content=`"0`" />
  </head>
<docTitle>
  <text>" + $htmlTitle + "</text>
</docTitle>
<navMap>
<navPoint id=`"navPoint-1`" playOrder=`"1`">
  <navLabel>
    <text>目次へ</text>
  </navLabel>
  <content src=`"book.html`" />
</navPoint>
</navMap>
</ncx>"

$mimetype = "application/epub+zip"

# ---------------------------------------------------------
# 結合後のファイルがあった場合は削除
Write-Host "Delete  : book dir, book.epub, book.zip"

If(Test-Path "book"){
  Remove-Item -Path "book" -Recurse
}
If(Test-Path "book.epub"){
  Remove-Item -Path "book.epub"
}
If(Test-Path "book.zip"){
  Remove-Item -Path "book.zip"
}

# フォルダ&ファイルの生成
New-Item "book"          -ItemType Directory > $null
New-Item "book\META-INF" -ItemType Directory > $null
New-Item "book\OEBPS"    -ItemType Directory > $null
Write-Output $containerBody | Out-File -FilePath "book\META-INF\container.xml"  -Append -Encoding UTF8
Write-Output $mimetype      | Out-File -FilePath "book\mimetype"                -Append -Encoding UTF8
Write-Output $opfBody       | Out-File -FilePath "book\OEBPS\content.opf"       -Append -Encoding UTF8
Write-Output $ncxBody       | Out-File -FilePath "book\OEBPS\toc.ncx"           -Append -Encoding UTF8

# ---------------------------------------------------------
$cnt = 0  # カウンター

# define hash table
$fileNameHashTable = @{};
$fileIndexHashTable = @{};

# ファイル名と、ソートするキーの取得
foreach($f in $fileList){
  # set index 
  # ファイル名が「第NNN部分~.txt」となるので、1文字目を飛ばして、部分で分割(split)して数字を取得
  $fileIndexHashTable.Add($cnt , [int]$f.Substring(1).Split('部分')[0]);
  # set file name
  $fileNameHashTable.Add($cnt , $f);
  $cnt++
}

# indexでソート
$fileIndexHashTable = $fileIndexHashTable.GetEnumerator() | sort -Property value

# ヘッダの出力
Write-Output $htmlHeader | Out-File -FilePath $outFile -Append -Encoding UTF8

# 目次の生成
Write-Output ( "<h1>目次</h1>`r`n<p>" )  | Out-File -FilePath $outFile -Append -Encoding UTF8
foreach($fileEnt in $fileIndexHashTable){
  $key = $fileEnt.Key;
  $val = $fileEnt.Value;
    
  $midashi = [System.IO.Path]::GetFileNameWithoutExtension($fileNameHashTable[($key)])
  Write-Output ( "<a href=`"#" + $val + "`">" + $midashi + "</a><br />" )  | Out-File -FilePath $outFile -Append -Encoding UTF8
}
Write-Output ( "`r`n</p>`r`n" )  | Out-File -FilePath $outFile -Append -Encoding UTF8

# 本文の生成
foreach($fileEnt in $fileIndexHashTable){
  $key = $fileEnt.Key;
  $val = $fileEnt.Value;
  # Write-Host ( $fileNameHashTable[($key)] )
  # PROGRESS
  Write-Host -NoNewline ("`r" + "Progress: ${val} / ${cnt} ")
  
  $midashi = [System.IO.Path]::GetFileNameWithoutExtension($fileNameHashTable[($key)])
  Write-Output ( "<h1 id=`"" + $val + "`" style=`"page-break-before:always`">" + $midashi + "</h1>`r`n<p>" ) | Out-File -FilePath $outFile -Append -Encoding UTF8

  #$htmlBody = Get-Content  -Encoding UTF8  
  # Get-Content $htmlBody -Encoding UTF8   | Out-File -FilePath $outFile -Append -Encoding UTF8

  $htmlBody = [System.IO.File]::ReadAllText($fileNameHashTable[($key)]).Replace("`r`n","<br />`r`n")
  ($htmlBody + "`r`n</p>`r`n" )| Out-File -FilePath $outFile -Append -Encoding UTF8
}

# フッタの出力
Write-Output $htmlFooter | Out-File -FilePath $outFile -Append -Encoding UTF8
Write-Host ""

# ---------------------------------------------------------
# ZIP圧縮 & 拡張子変更
Compress-Archive -Path "book" -DestinationPath "book.zip"
Rename-Item -Path "book.zip" -NewName "book.epub"
Write-Host "Created : book.epub"
実行方法
  • スタートメニュー等からPowerShellを起動
powershell console
  • txts2epub.ps1を実行

cdコマンドで、カレントフォルダを小説のテキストとpowershellを置いたPATHへ移動してから、実行してください。

PS C:\> cd C:\tensura_work\
PS C:\tensura_work> PowerShell -ExecutionPolicy RemoteSigned -file .\txts2epub.ps1 "[伏瀬] 転生したらスライムだった件"
Titile  : [伏瀬] 転生したらスライムだった件
Delete  : book dir, book.epub, book.zip
Progress: 304 / 304
Created : book.epub
powershell実行例
  • book.epubファイルができていたら成功です。
book.epubの確認

以上