次へ: 9 最後に 上へ: AWK による HTML ファイルの整形 その 2 前へ: 7 行の整形出力 (PDF ファイル: awkwww2.pdf)


8 全体のソースコード

以上をまとめた全体のソースコードを紹介しますが、 HTML のヘッダやフッタ部分の出力は関数を使って書いています。 これらは [4] とほぼ同様ですので、詳細はそちらを参照してください。

6 節で考察した行の分割も、 2 箇所に現われるので関数化してありますし、 7 節で考察した行の整形出力も、 後でカスタマイズできるように関数化してあります。

  BEGIN{ 
      if(TARGET=="") TARGET="yahoonews" # ターゲットフレーム名
      if(DIV=="") DIV=5 # 区切りを入れる個数
      N=0 # 一覧の項目数、h[]: 一覧を保存する配列
  }
  ##### タイトルや日付の取得 #####
  (ARGIND == 1 && $0 ~ /<b><font size=\+1>/){
      sub(/.*<b><font size=\+1>/,"")
      sub(/<\/font><\/b>.*/,"")
      TITLE=$0
      getline
      sub(/.*<small> - /,"")
      sub(/<\/small>.*/,"")
      DATE=$0
  }
  ##### 各行の取得 ##### 
  ($0 ~ /<ul>/){
      sub(/<ul>/,"")
      if($0 !~ /<li>/) getline
      do{
          # (1) 1 行を複数の <li> 行に分割して配列に保存
          N=divideline($0,h,N)
          getline
      }while($0 !~ /<\/ul>/)
      if($0 ~ /<li>/){
          sub(/<\/ul>/,"")
          # (1) 1 行を複数の <li> 行に分割して配列に保存
          N=divideline($0,h,N)
      }
  }
  ##### END ブロック #####
  END{
      putheader(DATE,TITLE,N)
      print "<ul>"
      for(j=1;j<=N;j++){
          put1list(h[j],TARGET)
          if(j%DIV==0) printf "<br>(ここまで %d 件)<br><br>\n",j
      }
      print "</ul>"
      putfooter()
  }
  
  ##### ユーザ定義関数 #####
  # 一つの <li> を整形して出力
  function put1list(str,target)
  {
      if(match(str,/<a href=\"[^\"]+\">/)==0) print str
      else{
          printf "%s",substr(str,1,RSTART+RLENGTH-2)
          printf " target=\"%s\"",target
          printf "%s\n",substr(str,RSTART+RLENGTH-1)
      }
  }
  
  
  # <br> で文字列を分割して配列 h に追加 (現在 h[1]~h[N] まで保存)
  function divideline(str,h,N,    tmp,j,M)
  {
      sub(/<br>(<br>|<\/ul>)? *$/,"",str)
      M=split(str,tmp,/<br>/)
      for(j=1;j<=M;j++) if(tmp[j] ~ /<li>/) h[++N]=tmp[j]
      return N
  }
  
  # ヘッダの出力
  function putheader(date,title,N)
  {
      printf "<html>\n"
      printf "<head>\n"
      printf "<meta http-equiv=\"Content-Type\""
      printf " content=\"text/html; charset=EUC-JP\">\n"
      printf "<title>Yahoo News (%s)</title>",title
      printf "</head>\n"
      printf "<body>\n"
      printf "<h2>Yahoo News (%s: %s : %d 件)</h2>\n",title,date,N
      #printf "<a href=\"%s\" target=\"%s\">(home)</a>\n",url,target
      printf "<hr>\n"
  }
  
  # フッタの出力
  function putfooter()
  {
      print "<hr>"
      print "</body>"
      print "</html>"
  }

ターゲットフレーム名 (= TARGET) や区切りを入れる個数 (= DIV) は 変更が容易にできるようにしてあります。 例えば、Yahoo! ニュースの一覧の HTML ファイルが file1.html,file2.html,...で、 上のスクリプトファイルを yahoo2.awk とすれば、

  awk -f yahoo2.awk file?.html > list.html
のようにすれば結合された一覧の HTML ファイル list.html ができますが、
  awk -f yahoo2.awk -v TARGET="another" file?.html > list.html
のようにすれば TARGET や DIV の値を AWK のコマンドラインオプションで 変更できます。

なお、関数 putheader() の中で、charset=EUC-JP としてありますが、 これは私の環境が Unix だからではなく、 普通に Yahoo! ニュース記事をダウンロードすると EUC-JP という 漢字コードになるからです。 MS-Windows 上でも EUC-JP のまま保存した場合は上のままでいいようですが、 Shift_JIS で保存する場合は適当にその辺を修正するといいでしょう。

また、ブラウザで HTML ファイルを保存する場合、 ブラウザによっては (例えば MS-IE) 単純に保存するのではなく 色々加工して保存することもあるようで、 そのような場合は今回のスクリプトではうまく処理できないかもしれません。


次へ: 9 最後に 上へ: AWK による HTML ファイルの整形 その 2 前へ: 7 行の整形出力
竹野茂治@新潟工科大学
2006年9月5日