Rで青空文庫のテキスト整形

# はじめに
　Rで、[青空文庫](https://www.aozora.gr.jp/)のテキスト整形に挑戦してみました。
　目標は、↓こんなのを、
```
 [1] "手袋を買いに"
 [2] "新美南吉"
 [3] "-------------------------------------------------------"
 [4] "【テキスト中に現れる記号について】"
 [5] "《》：ルビ"
 [6] "（例）狐《きつね》"
 [7] "｜：ルビの付く文字列の始まりを特定する記号"
 [8] "（例）十｜米《メートル》"
 [9] "［＃］：入力者注　主に外字の説明や、傍点の位置の指定"
 [10] "（例）［＃ここから２字下げ］"
 [11] "-------------------------------------------------------"
 [12] "　寒い冬が北方から、狐《きつね》の親子の棲《す》んでいる森へもやって来ました。"
 [13] "　或朝《あるあさ》洞穴《ほらあな》から子供の狐が出ようとしましたが、"
 [14] "「あっ」と叫んで眼《め》を抑《おさ》えながら母さん狐のところへころげて来ました。"
 [15] "「母ちゃん、眼に何か刺さった、ぬいて頂戴《ちょうだい》早く早く」と言いました。"
```
　↓こんな風にすることです。
```
 [1] "手袋を買いに"
 [2] "新美南吉"
 [3] ""
 [4] ""
 [5] ""
 [6] ""
 [7] ""
 [8] ""
 [9] ""
[10] ""
[11] ""
[12] "寒い冬が北方から、狐の親子の棲んでいる森へもやって来ました。"
[13] "或朝洞穴から子供の狐が出ようとしましたが、"
[14] "「あっ」と叫んで眼を抑えながら母さん狐のところへころげて来ました。"
[15] "「母ちゃん、眼に何か刺さった、ぬいて頂戴早く早く」と言いました。"
```
# 作成したコード（`lapply`関数使用バージョン）
```r
aozora <- function(url){
    zip_file_name <- basename(url)
    if (!file.exists(zip_file_name)) download.file(url, destfile=zip_file_name)
    unzip_file_name <- unzip(zip_file_name)
    ruby_text <- scan(unzip_file_name, what=character(), fileEncoding='CP932')
    is_delete <- FALSE
    no_ruby_text <- lapply(ruby_text, function(text) {
        if (grepl('^------', text)) {is_delete <<- !is_delete; return('')}
        if (grepl('^底本|［＃本文終わり］', text)) is_delete <<- TRUE
        if (is_delete) return('')
        gsub('［＃[^］]*］|《[^》]*》|｜|　', '', text)
        }
    )
    no_ruby_text <- unlist(no_ruby_text)
    no_ruby_file_name <- paste(strsplit(unzip_file_name, '.txt'), '2.txt', sep='')
    write(no_ruby_text, no_ruby_file_name)
    no_ruby_text
    # no_ruby_file_name
}
```
# 下手な解説
## 関数名aozoraでテキスト整形を関数化
```r
aozora <- function(url){
```
- 「最後に」に記載の、徳島大学・石田基広教授の Aozora 関数にあやかりました。
## URLからzipファイル名の取り出し
```r
    zip_file_name <- basename(url)
```
- `basename()`というURLからファイル名を取り出す便利な関数がありました
## zipファイルが存在しなければダウンロード
```r
    if (!file.exists(zip_file_name)) download.file(url, destfile=zip_file_name)
```
- コード作成中に同じファイルを何度もダウンロードしないようにしました
## 解凍して保存、ファイル名の取得
```r
    unzip_file_name <- unzip(zip_file_name)
```
- 解凍されてできるファイルが、１個であることを前提にしています
## 解凍したテキストファイルをエンコードして読み込み
```r
    ruby_text <- scan(unzip_file_name, what=character(), fileEncoding='CP932')
```
- `CP932`は、`Shift-JIS`のこと？
- `CP932`を `Shift-JIS`に置き換えても正常に(?)動作した
## 行を削除するかどうかのフラグ
```r
    is_delete <- FALSE
```
- `TRUE`の間、削除対象とする
## `lapply`でruby_textから要素を順に取り出し整形
```r
    no_ruby_text <- lapply(ruby_text, function(text) {
```
- `for`より`apply`、`lapply`を使用するほうが良いという記述を見たので
## 【テキスト中に現れる記号について】ブロックの削除準備
```r
        if (grepl('^------', text)) {is_delete <<- !is_delete; return('')}
```
- `grepl()`で検索
- 正規表現で、`^------`の`^`は、行の先頭に、後の文字列があるということ
- `<<-`のように、`<`２個でグローバル変数に代入
- `is_delete <<- !is_delete`で、
  - １回目に`!FALSE`すなわち`TRUE`にして、これ以降を削除対象にする
  - ２回目に`!TRUE`すなわち`FALSE`にして、これ以降を削除対象から除く
- `return('')`で、この行を削除
  - ここで削除しないと、２回目の`"-------------------------------------------------------"`が消えない
## 本文より後ろの行の削除準備
```r
        if (grepl('^底本|［＃本文終わり］', text)) is_delete <<- TRUE
```
- `is_delete`を`TRUE`にすることで、この行以降をすべて削除対象にする
## 上記で準備した各削除を実行
```r
        if (is_delete) return('')
```
- 見たまんまです。`is_delete`が`TRUE`の間、行を削除します
## 注釈・ルビ・全角｜・全角スペースの削除
```r
        gsub('［＃[^］]*］|《[^》]*》|｜|　', '', text)
        }
    )
```
- `gsub()`で置換、置換後を`''`とすることで、削除
- 正規表現で、`［＃[^］]*］`は
  - `［＃`で始まり、間に`］`以外の文字が０個以上有り、`］`で終わる部分を表す 
  - `^` は、`[]` の中に入ると後ろの文字以外という意味
  - `*` は、直前の文字が０個以上という意味
- Rは最後の行が、関数の戻り値となるので`return`を書かなくて良い
## `write`でファイル出力するために`unlist`
```r
    no_ruby_text <- unlist(no_ruby_text)
```
- `lapply`の引数と戻り値はリストなので、`unlist`でベクトルにする
## 整形後のファイル名の作成
```r
    no_ruby_file_name <- paste(strsplit(unzip_file_name, '.txt'), '2.txt', sep='')
```
- `strsplit(unzip_file_name, '.txt')` で、元のテキストファイル名を `.txt` で分割することによって、拡張子を消す
- `paste()`で、`2.txt` と結合するときに、間にスペースをつけないよう `sep=''` で指定する
## ファイルに出力
```r
    write(no_ruby_text, no_ruby_file_name)
```
## 戻り値
```r
    no_ruby_text
    # no_ruby_file_name
}
```
- 適宜必要なものに変更する
# 使用例（「手袋を買いに」新美南吉）
```r
# 青空文庫・テキストファイル(ルビあり)・zip・ファイル名（リンク）のURL
url <- 'https://www.aozora.gr.jp/cards/000121/files/637_ruby_4095.zip'
print(aozora(url))
```
# 作成したコード（`for`使用バージョン）
```r
aozora <- function(url){
    zip_file_name <- basename(url)
    if (!file.exists(zip_file_name)) download.file(url, destfile=zip_file_name)
    unzip_file_name <- unzip(zip_file_name)
    ruby_text <- scan(unzip_file_name, what=character(), fileEncoding='CP932')
    no_ruby_text <- c()
    is_delete <- FALSE
    for (text in ruby_text) {
        if (grepl('^底本|［＃本文終わり］', text)) break
        if (grepl('^------', text)) {is_delete <- !is_delete; next}
        if (is_delete) next;
        text <- gsub('［＃[^］]*］|《[^》]*》|｜|　', '', text)
        no_ruby_text <- c(no_ruby_text, text)
    }
    no_ruby_file_name <- paste(strsplit(unzip_file_name, '.txt'), '2.txt', sep='')
    write(no_ruby_text, no_ruby_file_name)
    no_ruby_text
    # no_ruby_file_name
}
```
# 最後に
　コードの作成にあたり、RMeCab の作者、徳島大学・石田基広教授の、[このページ](http://rmecab.jp/wiki/index.php?RMeCabFunctions#b1945a7c)の Aozora.R のコードがとても参考になりました。ありがとうございます。
　ここに書いたコードや解説の間違いは、たくさんあると思います。また、私の作成したコードより、もっと良いコードもあると思います。ここだけでなく、他のサイトもお調べください。
# 参考にしたサイト
- [青空文庫](https://www.aozora.gr.jp/)
- [アールメカブ](http://rmecab.jp/wiki/index.php?FrontPage)