adbird(広告鳥) 備忘録

カクヨムの小説をA5・2段組・縦書きのPDFデータにする


下記の通り、環境はUbuntuLinux)です。

環境

ディレクトリ構成

カクヨム
  ├── download.sh
  ├── A5_Kakuyomu_tex.sh
  └── 小説タイトル (このディレクトリ名がpdfファイル名になる)
       ├── 000001.html
       └── 000002.html
           ︙

スクリプト作成

ダウンロード用スクリプト(download.sh)

以下の内容を download.sh として保存。

#!/bin/sh

#目次ページダウンロード

wget -O 目次.html $1

#各話URL取得、ダウンロードスクリプトwget.sh生成。 
#wgetの直前に「sleep 10」で10秒待ちを入れている。任意で変更を。wgetは-ncオプションで同じファイル名のものは上書きしない。

sed -e "s/^[ \t]*//" -e "/DOCTYPE html/,/widget-toc-main/d" -e "/id\=\"reviews\"/,/<\/html>/d" 目次.html | grep -e "<a href" | sed -e "s/<a href=\"//g" -e "s/\" class=\"widget-toc-episode-episodeTitle\">//g" -e "s/\/works/https\:\/\/kakuyomu.jp\/works/g" | nl -n rz | sed -e "s/^/sleep 10\nwget -nc -O /g" -e "s/\thttp/.html http/g" | sed -e "1d" > wget.sh

# wget.sh実行
sh wget.sh

PDF変換スクリプト(A5_Kakuyomu_tex.sh)

以下の内容を A5_Kakuyomu_tex.shとして保存。

#!/bin/bash

if [ -e ./tmpfile ]; then
    \rm -r tmpfile
fi

mkdir -p tmpfile
if [ -e ./output-a.tex ]; then
    \rm -r output-a.tex
fi

onetimeflag=0

for fh in *.html
do
#タイトルと作者名を抽出
if [ $onetimeflag -eq 0 ]; then
    grep '<h1 class' $fh | sed -e "s/^[ \t]*//" -e "s/<li .*\">//g"  -e "s/<\/span>/\n/g" | sed -e "/<\/h1>/d" > ./tmpfile/tmp_title
    grep 'contentMain-header-author' $fh | sed -e "s/^[ \t]*//" -e "s/<p .*\">//g" -e "s/<\/p>//g" > ./tmpfile/tmp_auth
    echo "" > ./tmpfile/tmp_section
    onetimeflag=1
fi

done

#テキストの見出し部分をtex記法に。「<p id=p」「\section」「\subsection」の行だけ抽出。
sed -e "s/^[ \t]*//" -e '/chapterTitle level1/s/<\/span><\/p>/}/g' -e '/chapterTitle level1/s/<p .*\"><span>/\\section{/g' -e '/chapterTitle level2/s/<\/span><\/p>/}/g' -e '/chapterTitle level2/s/<p .*\"><span>/\\section{/g' -e '/widget-episodeTitle/s/<\/p>/}/g' -e '/widget-episodeTitle/s/<p .*\">/\\subsection{/g' -e "s/<p id=\"p1\"/\n<p id=\"p1\"/g" *.html | grep -e "<p id=\"p" -e "\\\section" -e "\\\subsection"  > output-a.tex
#傍点、ルビ(pxrubricaパッケージ対応)
sed -i -e 's/<em class=\"emphasisDots\">/\\kenten\[s\]{/g' -e 's/<\/span><\/em>/\}/g' -e 's/<span>//g' -e 's/<ruby><rb>/\\ruby\[g\]{/g' -e 's/<\/rb><rp>(<\/rp><rt>/}{/g' -e 's/<\/rt><rp>)<\/rp><\/ruby>/}/g' -e 's/<\/span>//g' -e 's/<\/a>//g' output-a.tex
#「<p id=p」の行からテキストだけを抽出。空行1つ分は削除、空行2つ分は空行1つに
perl -e 'while(<>){s/^<p id="p[0-9]+">(.*)<\/p>$/$1\n/;print $_;}' output-a.tex | sed -e '/class=\"blank\"><br \/><\/p>$/d' -e "s/^ *//" | perl -e 'while(<>){s/^<p id="p[0-9]+" class="blank">(.*)<\/p>$/\\vskip\\baselineskip/;print $_;}' > outputb.tex

#アポストロフィー変換、半角数字を全角数字など諸々置換
sed -i -e "s/\&#39;/\'/g" -e 'y/1234567890/1234567890/' -e 's/“/〝/g' -e 's/”/〟/g' -e 's/\&quot\;/"/g' -e "s/&lt;/</g" -e "s/&gt;/>/g" -e "s/\#/#/g" -e 's/\$/$/g' -e 's/%/%/g' -e "s/&/&/g" -e 's/\~/〜/g'  -e 's/?/?/g' -e 's/!/!/g' outputb.tex
#タイトルも諸々置換
sed -i -e "s/\&#39;/\'/g" -e 'y/1234567890/1234567890/' -e 's/“/〝/g' -e 's/”/〟/g' -e 's/\&quot\;/"/g' -e "s/&lt;/</g" -e "s/&gt;/>/g" -e "s/\#/#/g" -e 's/\$/$/g' -e 's/%/%/g' -e "s/&/&/g" -e 's/\~/〜/g'  -e 's/?/?/g' -e 's/!/!/g' ./tmpfile/tmp_title
#作者名も諸々置換
sed -i -e "s/\&#39;/\'/g" -e 'y/1234567890/1234567890/' -e 's/“/〝/g' -e 's/”/〟/g' -e 's/\&quot\;/"/g' -e "s/&lt;/</g" -e "s/&gt;/>/g" -e "s/\#/#/g" -e 's/\$/$/g' -e 's/%/%/g' -e "s/&/&/g" -e 's/\~/〜/g'  -e 's/?/?/g' -e 's/!/!/g' ./tmpfile/tmp_auth
# http://〜を含む行
sed -i -e 's/<a href.*\">//g' -e '/http/s/^/\\begin{verbatim}/g' -e '/http/s/$/\\end{verbatim}/g' -e '/http/y/1234567890/1234567890/' outputb.tex
# 括弧(「)の行の字下げ(半文字だけ字下げ)
sed -i -e 's/^「/\\noindent\\hspace{0.5em}「/g' outputb.tex


#LaTex
perl -e '
    open(RDFILE, "< ./tmpfile/tmp_auth");
        $tmp_auth=<RDFILE>;
        chomp($tmp_auth);
    close(RDFILE);
        open(RDFILE, "< ./tmpfile/tmp_title");
        $tmp_title=<RDFILE>;
        chomp($tmp_title);
    close(RDFILE);
    #
    print "\\documentclass[a5paper,twocolumn,twoside,openleft]{ltjtbook}\n";
    print "\n";
    print "%ページ余白等\n";
    print "\\usepackage[top=17mm,bottom=17mm,left=17mm,width=111mm,right=20mm,headsep=5mm,footskip=9mm]{geometry}\n";
    print "\n";
    print "%行間\n";
    print "\\renewcommand{\\baselinestretch}{1}\n"; 
    print "\n";
    print "%段と段の間隔を10mm\n";
    print "\\setlength{\\columnsep}{10mm}\n";
    print "\n";
    print "% -----章番号を無しにする-----\n";
    print "\\setcounter{secnumdepth}{0}\n";
    print "\n";
    print "%目次をハイパーリンク付きにする\n";
    print "\\usepackage[luatex,pdfencoding=auto,hidelinks]{hyperref}\n";
    print "\n";
    print "%フォント指定のためのパッケージ\n";
    print "\\usepackage{luatexja-fontspec}\n";
    print "%欧文・数字フォント(フォントによっては文字が欠落する場合があるので注意)\n";
    print "\\setmainfont{GenEiChikugoMin2-R}\n";
    print "\\setsansfont{IPAexGothic}\n";
    print "%ここで日本語フォント指定 (フォントによっては文字が欠落する場合があるので注意)\n";
    print "\\setmainjfont{GenEiChikugoMin2-R}\n";
    print "\\setsansjfont{IPAexGothic}\n";
    print "\n";
    print "%見出しのフォントサイズ(smallやfootnotesizeに)等\n";
    print "\\makeatletter\\renewcommand{\\section}{\\\@startsection{section}{2}{\\z\@}{1.5\\Cvs \\\@plus.5\\Cvs \\\@minus.2\\Cvs}{.5\\Cvs \\\@plus.3\\Cvs}{\\gtfamily\\small\\mdseries}}\\makeatother\n";
    print "\\makeatletter\\renewcommand{\\subsection}{\\\@startsection{subsection}{3}{\\z\@}{1.5\\Cvs \\\@plus.5\\Cvs \\\@minus.2\\Cvs}{.5\\Cvs \\\@plus.3\\Cvs}{\\gtfamily\\small\\mdseries}}\\makeatother\n";
    print "\\makeatletter\\renewcommand{\\subsubsection}{\\\@startsection{subsubsection}{3}{\\z\@}{1.5\\Cvs \\\@plus.5\\Cvs \\\@minus.2\\Cvs}{.5\\Cvs \\\@plus.3\\Cvs}{\\gtfamily\\footnotesize\\mdseries}}\\makeatother\n";
    print "\n";
    print "% -----図の設定-----\n";
    print "\\usepackage{graphicx}\n";
    print "\\usepackage{float}\n";
    print "\n";
    print "% -----ルビ使用の設定-----\n";
    print "%\\usepackage{luatexja-ruby}\n";
    print "\\usepackage{pxrubrica}\n";
    print "\n";
    print "% -----囲みの設定-----\n";
    print "\\usepackage{boites}\n";
    print "\n";
    print "% -----ヘッダ・フッタの設定 フォントサイズをfootnotesizeに-----\n";
    print "\\makeatletter\\def\\ps\@myheadings{\\let\\ps\@jpl\@in\\ps\@plain\\let\\\@oddfoot\\\@empty\\let\\\@evenfoot\\\@empty\\def\\\@evenhead{{\\leftmark}\\hfil\\footnotesize{\\thepage}}\\def\\\@oddhead{\\footnotesize{\\thepage}\\hfil\\rightmark}\\let\\\@mkboth\\\@gobbletwo\\let\\sectionmark\\\@gobble\\let\\subsectionmark\\\@gobble}\\makeatother\n";
    print "\\pagestyle{myheadings}\n";
    print "%------ヘッダの右にsubsubsectionmark=節 を表示。章を表示させたい場合は subsectionmark に----\n";
    print "%\\renewcommand{\\subsectionmark}[1]{\\markright{#1}}\n";
    print "\n";
    print "%-------------目次ページ再設定---------------\n";
    print "\\makeatletter\n";
    print "\\renewcommand{\\tableofcontents}{%\n";
    print "  \\if\@twocolumn\\\@restonecoltrue\\onecolumn\n";
    print "  \\else\\\@restonecolfalse\\fi\n";
    print "  \\chapter*{\\contentsname\n";
    print "    \\\@mkboth{\\contentsname}{\\contentsname}%\n";
    print "\\thispagestyle{myheadings}\n";
    print "  }\\\@starttoc{toc}%\n";
    print "  \\if\@restonecol\\twocolumn\\fi\n";
    print "}\n";
    print "\\makeatother\n";
    print "\n";
    print "% hyperref.styの関係で、目次ページ番号が寝てしまうので、正しく縦向きに。 参考:http://id.fnshr.info/2017/05/20/my-latex-templates-201705/\n";
    print "\\makeatletter\n";
    print "\\def\\contentsline#1#2#3#4{\\csname l\@#1\\endcsname{\\hyper\@linkstart{link}{#4}{#2}\\hyper\@linkend}{\\rensuji{#3}}}\n";
    print "\\makeatother\n";
    print "\n";
    print "%目次のリーダー(点線)を消す。節(section)以降のページ下余白調整\n";
    print "\\makeatletter\n";
    print "\\def\\\@dottedtocline#1#2#3#4#5{%\n";
    print "  \\vskip\\toclineskip \\\@plus.2\\p\@%\n";
    print "  {\\setlength{\\parfillskip}{2em} %節(section)以降の下余白\n";
    print "    \\parindent #2\\relax\\\@afterindenttrue\n";
    print "   \\interlinepenalty\\\@M\n";
    print "   \\leavevmode\n";
    print "   \\\@lnumwidth #3\\relax\n";
    print "   \\advance\\leftskip \\\@lnumwidth \\hbox{}\\hskip -\\leftskip\n";
    print "    {#4}\\nobreak\n";
    print " \\leaders\\hbox to 3pt{\\hfil\\raise3pt\\hbox{}\\hfil}% ここのhbox{}でリーダーを設定\n";
    print "     \\hfill \\nobreak\\hbox to\\\@pnumwidth{%\n";
    print "         \\hss\\reset\@font\\rmfamily\\small \\normalcolor #5}\\par}}\n";
    print "\\makeatother\n";
    print "\n";
    print "%--------タイトルページの再定義-----------\n";
    print "\\makeatletter\n";
    print "\\if\@titlepage\n";
    print "  \\renewcommand{\\maketitle}{\\begin{titlepage}%\n";
    print "  \\let\\footnotesize\\small\n";
    print "  \\let\\footnoterule\\relax\n";
    print "  \\let\\thanks\\p\@thanks\n";
    print "  \\let\\footnote\\thanks\n";
    print "  \\vbox to\\textheight\\bgroup\\tate\\hsize\\textwidth\n";
    print "  \\null\\vfil\n";
    print "  \\begin{center}%\n";
    print "%タイトルの下に作者名を表示する場合\n";
    print "  \\vskip 65\\p\@ %右余白\n";
    print "    {\\Large $tmp_title}\\hspace{4em}{\\large $tmp_auth \\par}% \n";
    print "%タイトルと作者を別々の行で表示する場合\n";
    print "%  \\vskip 95\\p\@ %右余白\n";
    print "%    {\\Large $tmp_title} %タイトル\n";
    print "%    \\vskip 3em \n";
    print "%    {\\begin{flushright}\\large $tmp_auth \\end{flushright} \\par} %作者 \n";
    print "%タイトルのみ表示\n";
    print "%  \\vskip 55\\p\@ %右余白\n";
    print "%    {\\Large $tmp_title}%\n";
    print "  \\end{center}\\par\n";
    print "  \\vfil{\\centering\\\@thanks}\\vfil\\null\n";
    print "  \\egroup\n";
    print "  \\end{titlepage}%\n";
    print "  }%\n";
    print "\\makeatother\n";
    print "\n";
    print "% -----本文-----\n";
    print "\\begin{document}\n";
    print "\n";
    print "% -----タイトル表示-----\n";
    print "\\maketitle\n";
    print "% -----目次-----\n";
    print "\\tableofcontents\n";
    print "\n";
    open(RDFILE, "< ./outputb.tex");
    while(<RDFILE>){ print $_; }
    close(RDFILE);
    print "\n\n";
    print "\\end{document}";
' > output.tex

#一時ファイル削除
\rm -rf outputb.tex output-a.tex tmpfile

#lualatex実行
lualatex output
lualatex output

#output.pdfファイルの名前をカレントディレクトリ名のファイルに変換。上位ディレクトリにPDFが生成がされるので、カレントディレクトリに戻す。
mv output.pdf $(pwd)-a5.pdf
mv $(pwd)-a5.pdf ./

スクリプト実行

ダウンロード

小説タイトルのフォルダ内で右クリックで端末を開いて、以下を実行。[url]は作品の目次ページのURL。

$ sh ../download.sh [url]

実行すると、小説タイトルのフォルダ内に000001.html、000002.html、…とhtmlファイルとしてダウンロードされていく。

PDF変換

$ bash ../A5_Kakuyomu_tex.sh