HTMLパーサーの Hpricot を使って、リンク <a href="hoge.html"> や 画像 <img src="hoge.png"> や Flash <embed src="hoge.swf"> から相対パスを抽出して、絶対パスへ置き換えるという方法。
直接、Hpricot や nokogiri で置換しようかと思ったが、元のHTMLの構造を崩しそうなのでそれはヤメ。
⇒ 参考: ヅラッシュ! - Ruby + Hpricot で HTML ファイル内の URL を置き換える
HTML内に存在する相対パスはダブルクォートで囲まれているという前提で処理することにした。(シングルクォートの可能性…)
処理の流れ:
1. hpricot で相対パスを抽出
2. 相対パスに対応する絶対パスを生成
3. 相対パスの前後にダブルクォートを付ける
4. HTML内からダブルクォート付き相対パスをダブルクォート付き絶対パスに置換
#!/usr/bin/env ruby
$KCODE='u'
require 'hpricot'
# 相対パスを絶対パスへ変換する
# [param] base_path (String) 絶対パスの基準となるパス文字列
# [param] src_path (String) 変換対象のパス文字列
# [return] (String) 絶対パス文字列
def replace_path(base_path, src_path)
begin
# 変換しなくていいパターン
no_replace_patterns = [ '^http://', '^https://', '^/', '^#' ]
no_replace_patterns.each{|pat|
reg = Regexp.new(pat)
return src_path if reg =~ src_path
}
# 変換するパターン
return File.expand_path(src_path, base_path)
rescue
# 主に <a herf="hoge"> などの typo でエラーが発生する
$stderr.puts "ERROR: src_path=#{src_path}, base_path=#{base_path}"
$stderr.puts $!.inspect
raise $!
end
end
# HTMLテキストからパス表現を抽出する
# [param] doc (Hpricot::Doc)
# [return] (Array[String]) パス文字列の配列
def extract_paths(doc)
paths = []
begin
(doc/:a).each{|elem|
# <a name="hoge"> は変換しない
# <a herf="hoge"> や <a hrf="hoge"> とかの
# typo を発見したらエラーが出るように
if !elem[:name] || elem[:href]
paths << elem[:href]
end
}
(doc/:img).each{|elem|
paths << elem[:src]
}
(doc/:embed).each{|elem|
paths << elem[:src]
}
(doc/:param).each{|elem|
if elem[:name] == 'movie'
paths << elem[:value]
end
}
rescue
$stderr.puts $!.inspect
raise $!
end
return paths
end
# HTMLテキスト内の相対パスを絶対パスへ変換する
# [param] html (String) 変換対象のHTML文字列
# [param] base_path (String) 絶対パスの基準となるパス文字列
# [return] (String) 変換後のHTML文字列
def replace_html(html, base_path)
dst_html = html
src_paths = extract_paths(Hpricot(html))
src_paths.each{|src_path|
dst_path = replace_path(base_path, src_path)
# HTML内のパスはダブルクォートで囲まれているという前提で
dst_html.gsub!("\"#{src_path}\"", "\"#{dst_path}\"")
}
return dst_html
end
# だいたいこんな感じでデータを渡す
base_path = '/zurazure2/'
src_html = File.open('srcdata.html').read()
dst_html = replace_html(src_html, base_path)
puts dst_html
tags: ruby hpricot
Posted by NI-Lab. (@nilab)