読者です 読者をやめる 読者になる 読者になる

FLYING

〈全日本・紀文豆乳飲料シリーズ「麦芽コーヒー」の500ミリリットルパックを扱う小売店が少ないことに遺憾の意を表明する会〉活動記録

XMLサイトマップファイルを生成

ruby

gen_sitemap.rb

#!/usr/local/bin/ruby
# -*- encoding: utf-8 -*-

require 'uri'
require 'open-uri'

def get_depth(uri)
	uri.to_s.scan(/\//).size
end

def uri_normalize(uri)
	# include dynamic pages
	uri.sub(/#.*$/, "").sub(/index\.\w+$/, "").gsub(/&/, "&")
	# not include dynamic pages
	# uri.sub(/#.*$/, "").sub(/\?.*$/, "").sub(/index\.\w+$/, "").gsub(/&/, "&")
end

def find(array, uri, begin_uri)
	buf = nil
	begin
		# append a pair
		uri_array = array.map{|a| a.first.to_s}
		depth = get_depth(uri) - get_depth(begin_uri)
		return if uri_array.include?(uri.to_s)
		return if uri.to_s.index(begin_uri.to_s) != 0
		array << [ uri.to_s, 0.8 ** depth ]
		puts "#{uri.to_s}"
		# download source
		open(uri.to_s) {|f|
			buf = f.read
		}
		# find links recursively
		matches = buf.scan(/<a\s*?href=\"([^\"]+?)\"[^>]*?>/)
		matches.each{|m|
			href = uri_normalize(m.first)
			next_uri = uri.merge(href)
			find(array, next_uri, begin_uri)
		}
	rescue Exception
		return
	end
end

def gen_sitemap(uri)
	array = []
	uri = URI.parse(uri)
	find(array, uri, uri)
	
	result = ""
	result << "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
	result << "<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n"
	array.each {|a|
		result << "<url>\n"
		result << "  <loc>#{a.shift}</loc>\n"
		result << "  <lastmod>#{Time.now.strftime("%Y-%m-%d")}</lastmod>\n"
		result << "  <changefreq>daily</changefreq>\n"
		result << "  <priority>#{a.shift.to_s}</priority>\n"
		result << "</url>\n"
	}
	result << "</urlset>\n"
	
	File.open("sitemap.xml", "w") {|f|
		f.write(result)
	}
end

gen_sitemap(ARGV.shift)
puts "successfully completed."

使い方

$ ruby gen_sitemap.rb http://d.hatena.ne.jp/tondol/

出力

動的ページを含まないようにして*1上記のコマンドを実行した結果,生成されたXMLサイトマップファイルのサンプルです。

sitemap.xml

雑感

HTMLパーサを使わずに正規表現で適当にやってるので誤認識はもちろんあり得ます。また,律儀に1ページずつ全文取得しているので異様に遅いです。添付ライブラリのみでローカルにファイルがなくても生成できるのがメリットと言えばメリットかなあ。

*1:“# include dynamic pages”の部分をコメントアウトして,“# not include dynamic pages”の部分をコメントイン