w3mで、LPI Japan が公開している例題をローカルに保存する(改定版)

■w3mで、LPI Japan が公開している例題をローカルに保存する(改定版) 
 以下の改定版です。このままだと「wget -r」や「curl」で充分になってしまうので。。。

 w3mで、LPI Japan が公開している例題をローカルに保存する。
 http://d.hatena.ne.jp/labunix/20110516

■まずはテキスト形式で保存。

$ mkdir lpic && cd lpic; \
  for list in 101 102 201 202 301 302 303 304;do \
    w3m -dump_source "http://www.lpi.or.jp/ex/$list/" | \
    sed s/"<a href=\|>"/"\n"/g | grep ex_ | \
    for example in `xargs`;do \
      w3m -dump "$example" > `echo "$example" | sed s%".*/"%"${list}_"% | sed s/"\.shtml"/".txt"/`;
    done
  done

■余分なヘッダの場所の確認。

$ for list in *.txt;do nl -b a "$list" | grep "受験者ログインメンバーズページ";done | sort | uniq -c
    444     85    &#8226; 受験者ログインメンバーズページ

$ for list in *.txt;do \
    TAIL=$(echo `wc -l "$list"` | awk '{print $1-84}'); \
    tail -n $TAIL "$list" | head -n 1; \
  done | sort | uniq -c
    444   &#8226; 受験者ログインメンバーズページ

■余分なフッタの場所を確認。

$ for list in *.txt;do \
    TAIL=$(echo `wc -l "$list"` | awk '{print $1-84}'); \
    tail -n $TAIL "$list" | tac | nl -b a | grep "この ページの"; \
  done | sort | uniq -c
    444    176  このページのトップへ

■余分なヘッダーとフッターを取り除く。

$ for list in *.txt;do \
    TAIL=$(echo `wc -l "$list"` | awk '{print $1-84}'); \
    HEAD=$(echo `wc -l "$list"` | awk '{print $1-(176+84-1)}');
    tail -n $TAIL "$list" | head -n $HEAD > `echo $list | sed s/".txt"/".log"/`; \
  done

■出来た全体のファイル数の確認。

$ ls *.log | wc -l
444

■余分なヘッターとフッターは過不足無く取り除かれています。

$ tail -n 2 *.log | grep -v "^=\|^\$" | sort | uniq -c
    444 このページのトップへ

$ head -n 1 *.log | grep -v "^=\|^\$" | sort | uniq -c
    444   &#8226; 受験者ログインメンバーズページ

■先頭から2行、最後の39行がまだ、減らせます。

$ for list in *.log;do nl -b a "$list";done | sort | uniq -c | awk '($1==444){print}'
    444      1    &#8226; 受験者ログインメンバーズページ
    444      2

$ for list in *.log;do tac "$list" | nl -b a;done | sort | uniq -c | awk '($1==444){print}' | tail -1
    444     39

■上記を反映させると。

$ for list in *.txt;do \
    TAIL=$(echo `wc -l "$list"` | awk '{print $1-(84+2)}'); \
    HEAD=$(echo `wc -l "$list"` | awk '{print $1-(176+39+84+2-1)}');
    tail -n $TAIL "$list" | head -n $HEAD > `echo $list | sed s/".txt"/".log"/`; \
  done3桁区切りの箇所はまあ、手作業でw。。。

$ echo "`wc -l *.txt | tail -1` `wc -l *.log | tail -1`" | \
  awk '{printf "%d,%d - %d,%d = %d,%d\n",$1/1000,$1%1000,$3/1000,$3%1000,($1-$3)/1000,$3%1000}'
161,953 - 28,753 = 133,753

■上記に気づくと、最初からこうすればよいという方法があります。

$ for list in *.txt;do nl -b a "$list";done | sort | uniq -c | awk '($1=='`ls *.txt | wc -l`'){print}' | tail -1
    444     86
$ for list in *.txt;do tac "$list" | nl -b a;done | sort | uniq -c | awk '($1=='`ls *.txt | wc -l`'){print}' | tail -1
    444    214

$ echo $((84+2))
86
$ echo $((176+39+84+2-1))
300
$ echo $((300-86))
214

■なので、一見難しく見えるかも知れませんが、
 ファイルの中身を自分で見ること無く同じ答えを出す事が出来ます。

$ HEADER=$(for list in *.txt;do nl -b a "$list";done | sort | uniq -c | \
    awk '($1=='`ls *.txt | wc -l`'){print}' | tail -1 | awk '{print $2}'); \
  FOOTER=$( for list in *.txt;do tac "$list" | nl -b a;done | sort | uniq -c | \
    awk '($1=='`ls *.txt | wc -l`'){print}' | tail -1 | awk '{print $2}'); \
  for list in *.txt;do \
    TAIL=$(echo "`wc -l < $list` $HEADER" | awk '{print $1-$2}');
    HEAD=$(echo "`wc -l < $list` $FOOTER $HEADER" | awk '{print $1-($2+$3)}');
    tail -n $TAIL "$list" | head -n $HEAD > `echo $list | sed s/".txt"/".log"/`; \
  done

$ echo "`wc -l *.txt | tail -1` `wc -l *.log | tail -1`" | \
  awk '{printf "%d,%d - %d,%d = %d,%d\n",$1/1000,$1%1000,$3/1000,$3%1000,($1-$3)/1000,$3%1000}'
161,953 - 28,753 = 133,753

■何も考えなくて良くなったので、
 以下に実行権を与えてユーザ権限で実行するだけです。
 レベルを限定したい方は最初のfor文のリストをお好きなように。

$ cat lpic_dl.sh
#!/bin/bash
cd $HOME

mkdir lpic && cd lpic; \
  for list in 101 102 201 202 301 302 303 304;do \
    w3m -dump_source "http://www.lpi.or.jp/ex/$list/" | \
    sed s/"<a href=\|>"/"\n"/g | grep ex_ | \
    for example in `xargs`;do \
      w3m -dump "$example" > `echo "$example" | sed s%".*/"%"${list}_"% | sed s/"\.shtml"/".txt"/`;
    done
  done
unset example

HEADER=$(for list in *.txt;do nl -b a "$list";done | sort | uniq -c | \
    awk '($1=='`ls *.txt | wc -l`'){print}' | tail -1 | awk '{print $2}'); \
unset list

FOOTER=$( for list in *.txt;do tac "$list" | nl -b a;done | sort | uniq -c | \
    awk '($1=='`ls *.txt | wc -l`'){print}' | tail -1 | awk '{print $2}'); \
unset list

  for list in *.txt;do \
    TAIL=$(echo "`wc -l < $list` $HEADER" | awk '{print $1-$2}');
    HEAD=$(echo "`wc -l < $list` $FOOTER $HEADER" | awk '{print $1-($2+$3)}');
    tail -n $TAIL "$list" | head -n $HEAD > `echo $list | sed s/".txt"/".log"/`; \
  done
unset list HEADE FOOTER TAIL HEAD
exit 0


■例えば、303の例題を解く、201202を解く場合は以下のように。

$ cat 303*.log | less
$ cat 20[12]*.log | less

■え?進み具合が知りたい?
 (sshコンソール用)のprオプションで、ファイル名とPage数が出るので、
 それで我慢してくださいw。

$ pr -l25 20[12]*.log | less