あまりすることはないと思うが、bashで簡易的にスクレイピングする時によく使うコマンドとかのメモ。基本は行単位の処理なので、お手軽さを求めるなら用途は限られるか…。でも前処理とかに便利かもしれないし……。
クローリング
wgetでクローリング。
wget URL
再帰的にやるなら、たとえば以下。
wget -r --no-parent -w 1 -l 1 URL
オプションの意味は、rが再帰的(recursive)、--no-parentが親ディレクトリを探索しない、-w 1がwait 1秒でダウンロード間隔1秒毎(サイトに負荷をかけすぎない為)、-l 1が深さlevel 1、リンクをたどる深さを表している。
スクレイピング
スクレイピングの時のメモ。
やりやすい相手
bashは基本的に一行ずつ処理することになるので、一行で抜き出したい情報が判断できるようなソースコードであることが望ましい。たとえば<th>hogehoge</th>からhogehogeを抜き出したい場合、<th>タグとhogehogeは同一の行にあることが望ましい。これが複数行にまたがっていると、けっこう頑張ったコードになると思われ、それだったら普通にpythonなりなんなりで便利なライブラリを使って書いたほうがお手軽と思われる。
よく使うコマンド
grep,sed+正規表現を駆使する。
grepは-Eオプションで拡張正規表現が使える。-vでマッチしない行の出力もよく使う。
sedは
sed -e 's/a/b/'
の置換をよく使う。その際、ウェブスクレイピングでは/を区切り文字にすると何かと都合が悪いので、#とか@とか他の記号を区切りにするとよい。
また、正規表現+後方参照で整形する。たとえば郵便番号でハイフンがあったりなかったりする時、
sed -e 's#([0-9]{3})-?([0-9]{4})#\1\2#g'
とすると、番号部分だけ抜き出せる。gのあるなしは、1回の置換で対象が複数あった時に、最初だけやるのか全部やるのかの違い。
最短一致
bashの正規表現は基本的に最長一致で、最短一致は工夫がいる。よくある.*?なんかは使えない。どうするかというと、クラスと否定を組み合わせて使う。たとえば<p>aaaa</p>と<p class='hoge'>aaaa</p>からaaaaを抜き出したいときは、
sed -e 's/<p.*>[^a](a+)/\1/g'
とするとよい。
改行をまたいだ処理
trで\nを削るとか、そこだけruby -pe 'gsub.("hoge","")'みたくrubyやperlを呼び出すか。
参考書籍。pythonと言いつつ最初はbashから始まる良い本。
コメント