ディレクトリ内のHTMLファイル内とファイル名を置換

前職の関係で新刊本の情報をスクレイピングしてきて仕事で使いやすい様に加工するスクリプトを使っていました。
厳密に言うとコミック担当者の業務軽減のために作ったんだけど、
今までは生成したHTMLをUSBメモリに入れて店のPCに保存して使ってもらっていました。
普通に考えるとサーバに上げてそれを見てもらえばいいんだけど
いろいろと都合が悪かったのでそうしていました。
だけど、今はUSBメモリにいれて渡すことができなくなったのでサーバに上げてみることにした。

そこで問題発生

今まではローカル保存を前提にしてたのでファイル名が日本語になっていました。
しかし、サーバにアップできるのはアルファベットと記号のファイル名のみです。
出版社1社毎にファイルが存在していて全部で56ほど。
そのファイル内には別のファイルへのリンクがずらっと張ってあります。
さすがに全てを手作業で書き換えるのは馬鹿らしい。

方法を考えました。

  1. その手の機能があるアプリを探してきてサクッと変換コース
  2. スクレイピングスクリプト自体の該当箇所を書き直して再スクレイプコース
  3. その手の機能をRubyで書いてみるコース

勉強をかねて三つめの自作置換スクリプトを作ってみる

id:amachangにならってさらしてみます。
基本的にコピペ。

#!/usr/bin/ruby
# renamer.rb
#  Created by  on 2007-12-12.


$KCODE = 'u'

require "hatsubaihyou_Pub_HushList"

$lists = Pub_list.new()
def replacer(arg)                   #出版社の変換用のハッシュを使って置換するメソッド
  $lists.list.each { |key, value|
    k = Regexp.new("_#{key}_")
    arg = arg.gsub(k,"_#{value}_")
  }
  return arg
end

folder = "/Users/hogehoge/Desktop/hoge/"

Dir::glob("#{folder}*.html").each {|f|                     #folder変数にディレクトリを渡すとその中の拡張子がhtmlのファイルを取り出し、ファイル内の文字列とファイル名を置換する。
  puts "#{f}: #{File::stat(f).size} bytes"
  File.open(f,"r"){ |file|
    replaced = replacer(file.read)
    # file.puts('')
    File.open(f,"w+"){ |file|
      file.printf("%s\n",replaced)
    }
  }
  File.rename(f,replacer(f))
}

requireしてる意味不明な”hatsubaihyou_Pub_HushList”

#!/usr/bin/ruby
# hatsubaihyou_Pub_HushList.rb
#  Created by  on 2007-12-12.



class Pub_list
  def initialize
    @list = {'秋田書店' => 'AkitaShoten',
            '角川書店発行/角川グループパブリッシング発売' => 'KadokawaShoten',
            'メディアワークス発行/角川グループパブリッシング発売' => 'Mediaworks',
            'メディアワークス' => 'Mediaworks',
            '講談社' => 'Kodansha',
            '集英社' => 'Shueisha',
            '小学館' => 'Shogakukan',
            '白泉社' => 'Hakusensha',
            '茜新社' => 'AkaneShinsha',
            '朝日新聞社' => 'AsahiShinbunsha',
            '一迅社' => 'Ichijinsha',
            '一水社' => 'Issuisha',
            '潮出版社' => 'Ushioshuppansha',
            'エンジェル出版' => 'Angelshuppan',
            'エンジェル出版' => 'Angelshuppan',      #ファイル名の変換とリンクの変換に必要な重複
            'エンターブレイン' => 'Enterbrain',
            'オークス' => 'Oks',
            'オークラ出版' => 'Okurashuppan',
            '宙出版' => 'Ohzora',
            '太田出版' => 'Ohtashuppan',
            '海王社' => 'Kaiohsha',
            '学習研究社' => 'Gakken',
            'キルタイムコミュニケーション' => 'KillTimeCommunication',
            '近代映画社' => 'Kindaieigasha',
            '久保書店' => 'Kuboshoten',
            'クロエ出版' => 'Kuroe',
            '幻冬舎' => 'Gentosha',
            'コアマガジン' => 'Coremagazine',
            '小池書院' => 'Koikeshoin',
            '光彩書房' => 'Kousaishobou',
            '光文社' => 'Koubunsha',
            'コスミック出版' => 'Cosmicshuppan',
            '三和出版' => 'Sanwashuppan',
            'ジーウォーク' => 'Gwalk',
            'ジーウォーク' => 'Gwalk',
            '実業之日本社' => 'Jitsugyounonihonsha',
            'ジャイブ' => 'Jive',
            '祥伝社' => 'Shodensha',
            '少年画報社' => 'Shonengahosha',
            '松文館' => 'Shobunkan',
            '新書館' => 'Shinshokan',
            '新潮社' => 'Shinchosha',
            'スクウェア・エニックス' => 'SquareEnix',
            '青林工藝舎' => 'Seirinkogeisha',
            '蒼竜社' => 'Soryusha',
            'ソフトバンククリエイティブ' => 'SoftbankCreative',
            'ピクトプレス発行/大誠社発売' => 'PictPress',
            '大都社' => 'Daitosha',
            '大洋図書' => 'Taiyoh',
            '竹書房' => 'Takeshobou',
            '中央公論新社' => 'Chuokouronshinsha',
            'ティーアイネット' => 'TiNet',
            'デジマ' => 'Digima',
            '東京三世社' => 'Tokyosanseisha',
            '東京漫画社' => 'Tokyomangasha',
            '徳間書店' => 'Tokumashoten',
            '日本文芸社' => 'Nihonbungeisha',
            'ハーレクイン社' => 'Harlequinsha',
            'ヒット出版社' => 'Hitshuppansha',
            '白夜書房' => 'Byakuyashobou',
            '富士美出版' => 'Fujimishuppan',
            '双葉社' => 'Futabasha',
            'ブッキング' => 'Booking',
            'ふゅーじょんぷろだくと' => 'FusionProduct',
            'ふゅーじょんぷろだくと' => 'FusionProduct',
            'ブライト出版' => 'Brightshuppan',
            'フランス書院' => 'Franceshoin',
            '古川書房' => 'Furukawashobou',
            'ぶんか社' => 'Bunkasha',
            'ぶんか社' => 'Bunkasha',
            '文藝春秋' => 'Bungeishunjuu',
            '平凡社' => 'Heibonsha',
            '芳文社' => 'Houbunsha',
            'ポプラ社' => 'Poplarsha',
            'マイウェイ出版' => 'MyWayshuppan',
            'マガジン・マガジン' => 'MagazineMagazine',
            'マガジン・マガジン' => 'MagazineMagazine',
            'マッグガーデン' => 'MagGarden',
            'マッグガーデン' => 'MagGarden',
            'マックス' => 'Max',
            'マロ編集部発行/文苑堂発売' => 'Maro',
            'マンガショップ発行/パンローリング発売' => 'MangaShop',
            'メディアックス' => 'Mediax',
            'メディアックス' => 'Mediax',
            'メディアファクトリー' => 'MediaFactory',
            'メディアファクトリー' => 'MediaFactory',
            'モエールパブリッシング' => 'MoeruPublishing',
            'モエールパブリッシング' => 'MoeruPublishing',
            'リイド社' => 'Leadsha',
            'リイド社' => 'Leadsha',
            'リブレ出版' => 'Libreshuppan',
            'リブレ出版' => 'Libreshuppan',
            'ワニブックス' => 'WaniBooks',
            'ワニマガジン社' => 'WaniMagazine'}
  end  
  attr_accessor :list
end

かなり痛いってのはわかってます。
hatsubaihyou_Pub_HushList.rbはなんとなくクラスって形態で書いてみたかっただけです。
出版社名が重複してるのはなぜかその出版社だけが一方だけでは


リンクは置換できてもファイル名が置換できない
もしくは
ファイル名が置換できてもリンクが置換できない


ということになってしまってたので両方追加しています。


renamer.rbの方は

・渡したディレクトリ内の拡張子htmlのファイルを文字列として読み込む。
・replacerメソッドで読み込んだ文字列に対してrequireしたhatsubaihyou_Pub_HushListの
・ハッシュを元に置換ループ。
・置換済みの文字列をいったん変数replacedに入れておく。
・もう一度”w+”モードでファイルを読み込んで変数replacedの内容を書き込む。
・ファイル名をreplacerメソッドでハッシュを元に置換。
それをファイルの個数分繰り返す。

ということになりました。
最初、置換した内容をファイルに上書きする方法がわからなくて苦戦しました。

File.open(f,"r+"){ |file|
    replaced = replacer(file.read)
     file.printf("%s\n",replaced)
}

みたいにしてたら置換されたファイルをブラウザで見てみてらフッター部分が妙なかたちで二重になって
カスみたいに残ってました。
”w+”フラグを与えるとファイルサイズを0にするということを
Rubyレシピブック 第2版 268の技のP238に書かれているのを発見。
よって二回もFile.open()しちゃってます。

痛い

もっとエレガントに書けるんだろうけど現状ではこの程度です orz