HTMLを整える

2007年12月19日
2 分

Hpricot とかで Web ページをスクレイピングするときに,対象のページを解析するのが結構めんどくさい。

ページによっては人間が読むのを想定しているとは思えない(というか大抵は想定してない)ような HTML で,読むのにひどく骨が折れる。なのでせめて見やすくなるように整形するスクリプトを書いてみた。

探せばちょうどいいツールがありそうだけど。

コマンドライン引数でファイル名か URL を指定する。

require 'rubygems'
require 'hpricot'
require 'open-uri'


def show_html(elem)
  s = ""
  elem.search("/*").each do |e|
    if e.instance_of?(Hpricot::XMLDecl)
      s << e.to_s
    elsif e.instance_of?(Hpricot::DocType)
      s << e.to_s
    elsif e.instance_of?(Hpricot::Text)
      s << e.to_s
    elsif e.instance_of?(Hpricot::Elem)
      s << "<#{e.name}"
      e.attributes.each do |k, v|
        s << " #{k}=#{v.inspect}"
      end
      s << ">\n"
      s << show_html(e).gsub(/^/, "  ")
    end
  end
  s
end


src = open(ARGV.shift, "r"){|f| f.read }
src.gsub!(/^\s+/, "")
doc = Hpricot(src)
print(show_html(doc).gsub(/^\s*\n/, ""))

出力(の一部)はこんな感じ。要素のネストをインデントで表現するようにした。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
  <head>
    <meta content="text/html; charset=euc-jp" http-equiv="Content-Type">
    <meta content="text/css" http-equiv="Content-Style-Type">
    <meta content="text/javascript" http-equiv="Content-Script-Type">
    <title>
      2007-12-18 - Haskell はスケるよ

    <link href="/takatoh/" title="Haskell \244\317\245\271\245\261\244\353\244\350" rel="start">
    <link href="/help" title="\245\330\245\353\245\327" rel="help">
    <link href="/takatoh/20071216" title="\301\260\244\316\306\374" rel="prev">
    <link href="/css/base.css" rel="stylesheet" media="all" type="text/css">
    <link href="/headerstyle?color=lg" rel="stylesheet" media="all" type="text/css">
    <link href="/theme/hatena_carving-blue/hatena_carving-blue.css" rel="stylesheet" media="all" type="text/css">
    <link href="http://d.hatena.ne.jp/takatoh/rss" title="RSS" rel="alternate" type="application/rss+xml">
    <link href="http://d.hatena.ne.jp/takatoh/rss2" title="RSS 2.0" rel="alternate" type="application/rss+xml">
    <link href="http://d.hatena.ne.jp/takatoh/foaf" title="FOAF" rel="meta" type="application/rdf+xml">
    <link href="http://d.hatena.ne.jp/takatoh/opensearch/diary.xml" title="Haskell \244\317\245\271\245\261\244\353\244\350\306\342\306\374\265\255\270\241\272\367" rel="search" type="application/ope nsearchdescription+xml">
    <link href="http://d.hatena.ne.jp/takatoh/opensearch/archive.xml" title="Haskell \244\317\245\271\245\261\244\353\244\350\306\342\260\354\315\367\270\241\272\367" rel="search" type="application/o pensearchdescription+xml">
    <link href="http://d.hatena.ne.jp/images/lg_favicon.ico" rel="shortcut icon">
    <style type="text/css">
    <link href="http://d.hatena.ne.jp/takatoh/mobile?date=20071218" rel="alternate" type="text/html" media="handheld">
    <script type="text/javascript" src="http://d.hatena.ne.jp/js/prototype-1.4.0.js">
    <script type="text/javascript" src="http://d.hatena.ne.jp/js/textinput_description.js">
    <script type="text/javascript" src="/js/embed_movie_player.js">
    <script type="text/javascript">
      Event.observe(window, 'load', function() {

      new TextInputDescription($('comment-username'), $('comment-form'), 'なまえ');


(以下略)

余計な空行は消してるつもりなのにどういうわけか残ってる。まぁ,目的は達成できてるようなのでいいか。