次ログ

次ログ

ゆるりと働いているSREの技術ブログのような何か。趣味の話も書く

静的な小説サイトからテキストを抽出して保存するスクリプト

どうもです。
ブログ更新忘れていたので、連投をば。

まえがき

もともとRPGツクール用のツールとかを配布するときに、 コミュニティサイトしか情報がなかったら良くないかも、 と思って開始したブログでしたが、 せっかくなので技術発信とかも少しでもしといたほうが、 今後の自分の糧になるのかなぁ、と思ったので、 そういう記事も書いていこうと思います。

目次

Webクローリングスクリプト

表題のとおり、今回はクローリングスクリプトです。

Bashwgetというコマンドを使えば、Webクローリングができるという情報を知って、自分がよく見ていた小説サイトの情報を抜き取って保存してみました。

参考サイト : http://girigiribauer.com/archives/925/

作成したスクリプト

#!/bin/bash
# -*- coding: utf-8 -*-

set -eux
: $1 $2 $3

# 対象サイトからHTMLを取得する
wget -r --random-wait $1 || exit 1

# ドメイン名のみ取り出す
dirname=`echo $1 | sed -E "s@https?://@@g" | sed -E "s@/.*@@g"`

# 不要なファイルを削除する
rm $dirname/*.png
rm $dirname/*.jpg
rm $dirname/*.gif
rm $dirname/*.zip

# ディレクトリ内のフォルダを取得
files=`find $dirname | xargs`
for file in $files; do
  if [ -f $file ]; then
    # 文字コードを変換して、別名ファイルで出力
    html=`cat $file | iconv -f $2 -t $3`
    title=`echo $html | sed -e "s@.*<title>\(.*\)</title>.*@\1@g"`

    cat $file | iconv -f $2 -t $3 \
      | sed -E 's@<[^>]*>@@g' \
      | sed -E 's@(^ +| +$)@@g' > "${dirname}/${title}.txt"

    # 元のファイルを削除
    rm $file
  fi
done

解説

引数チェック

set -eux
: $1 $2 $3

引数チェックの方法の一つです。 Qiitaの記事で知りました。
http://qiita.com/m-yamashita/items/889c116b92dc0bf4ea7d

今回の引数はそれぞれ下記の用途で使用しています。

HTML取得+ドメイン名の取得

# 対象サイトからHTMLを取得する
wget -r --random-wait $1 || exit 1

# ドメイン名のみ取り出す
dirname=`echo $1 | sed -E "s@https?://@@g" | sed -E "s@/.*@@g"`

wget再帰的に取得した時、ドメイン名のフォルダに保存されます。

そして、保存されるファイル名は、htmlファイルのファイル名なので、 必ずしも、その小説のタイトルではない場合があります。

なので、findしてhtml内のタイトルをファイル名にして保存するようにしたいわけです。 そこでwgetした時のURLからドメインのみを抜き出します。

sedするときは/(スラッシュ)を使うことが多いですけれど、 今回は@を使ってます。 URLが混じってると失敗してしまうので。

フォルダ内のファイルを処理

# ディレクトリ内のフォルダを取得
files=`find $dirname | xargs`
for file in $files; do
  ...
done

先ほど取得したドメイン名のフォルダをfindして、ループで処理します。

HTMLの文字コードの変換

# 文字コードを変換して、別名ファイルで出力
html=`cat $file | iconv -f $2 -t $3`

保存したファイルはUnicode文字として保存されていましたので、 それをUTF-8に変換する必要がありました。 なので、iconvで変換するようにします。

タイトルの取得

title=`echo $html | sed -e "s@.*<title>\(.*\)</title>.*@\1@g"`

次に、ファイル名がわかりやすくなるように、HTML内のタイトル要素を取得します。

ここも先ほどと同様にsedを使います。 sed正規表現と後方参照でタイトル部分のみを抜き出します。

HTMLからテキストのみを取り出して整形

cat $file | iconv -f $2 -t $3 \
  | sed -E 's@<[^>]*>@@g' \
  | sed -E 's@(^ +| +$)@@g' > "${dirname}/${title}.txt"

今回は小説サイトのテキストが必要なので、不要なタグを削除します。
また、インデントが存在していても見づらいので、それも削除します。

削除したら、先ほど取得した$titleをファイル名として保存します。

ここで、先ほど取得した$htmlを使用していないのは、 echo $htmlすると改行文字が削除されてしまっていたからです。

対処方法がわからなかったので、ここではファイルから再度取得して文字コードを変換し た結果をパイプするようにしました。

ここでも同様にsedします。 sedが便利すぎてやばいです。 でも何でも正規表現すると遅くなるとかって話を聞いたので、あまり良くはないのかも…。

所感

そんな感じで、好きな小説サイトのテキストを抜き出して閲覧できるようになりました。
閲覧するときは、less -N $filenameで読めば、ターミナルで読書ができます。

問題点としては、一昔前のような静的な小説サイトでないと機能しないということです。

Ctrl + U してソースを閲覧して、テキストがすっからかんになっているような 動的にページが構築されているようなサイトだと、ほぼ失敗します。

次に、1ページに1話である必要があります。 1話が何ページにも渡っていて、それらを1つのファイルにまとめるような処理は含まれていません。

他にも、ページ内に小説の記事以外の要素が含まれていてもダメです。

ブログサイトのように、他の記事へのリンクや、サイドメニューとか ヘッダとかの要素も取り込んでしまうので、それらを省く処理も場合によっては必要です。

この辺は課題ですね。