世界の都市名(カタカナ)から、その都市名(英語)と国名を返すプログラムが必要になったので、都市名データベースを用意します。
英語表記のデータベースは有償含めいくつかありましたが、日本語表記のものはあまりないのかなという印象です。
元になるデータをダウンロード
リンク先の「日本世界地名データ」をダウンロードします。
今回はこの中の「世界都市フォルダ」を使いますが、日本国内の市町村名などのファイルも含まれています。
※ ライセンスが明記されていないので注意が必要です
文字コードをUTF8に変換(どっちでもいいです)
先ほどダウンロードしたcsvファイルの文字コードを、nkfを使ってSJISからUTF8に変換します。
$ brew install nkf
$ cd flapna12
$ cd 世界都市フォルダ
$ nkf -Sw --overwrite **/*.csv
nkfをbrewでインストールして、さきほどダウンロードしたフォルダに移動、フォルダ内csvファイルをUTF8に一括変換。
csvファイルを編集
このcsvファイルには、ロンドンがイギリスとカナダ両方に含まれています。
今回は日本語の都市名から一意に国名を返したいので、Canada.csvからロンドンをコメントアウトします。
#ロンドン,London,42.59,-81.14,都市,4,
多次元ハッシュに格納し保存
国ごとに、
- 国名(英語)
- 国名(日本語)
- 都市名(英語)
- 都市名(日本語)
を多次元ハッシュとして格納し、cities.rbにハッシュを、cities.jsにjsonを保存するRubyコードを書きました。
convert.rb
require 'find'
require 'csv'
require "json"
d = Hash::new
Find.find('./') {|f|
if /.*?\.csv/ =~ f
CSV.foreach(f) do |city|
if $. == 1
next
elsif $. == 2
city[0] =~ /<TITLE>(.*?)\((.*?)\)<\/TITLE>/
$country_ja = $1
$country_en = $2
d[$country_en] = Hash::new
d[$country_en][:ja] = $country_ja
d[$country_en][:city] = Hash::new
else
d[$country_en][:city][city[1]] = city[0]
end
end
end
}
d.each_key do |key|
puts "#{d[key][:ja]}(#{d[key][:city].length})"
end
File.write("cities.rb", d)
File.write("cities.js", d.to_json)
現在のディレクトリが世界都市フォルダ
であることを確認し、実行します。
ruby convert.rb
結果
cities.rb
{
"Afghanistan" => {
:ja=>"アフガニスタン",
:city=>{
"Kabul" => "カブール",
"Qandahar" => "カンダハール",
"Herat" => "ヘラート",
"Qonduz" => "コンドゥーズ",
"Baghlan" => "バグラーン"
}
},
"Bahrain" => {
:ja => "バーレーン",
.
.
.
このような形式のハッシュができました。
国数:200
都市数:1778
また、国数・都市数共に十分実用的な数はあるのかなと思います。(日本は東京しかありませんけど)
他にもGoogle Map Apiから都市名を引っ張ってくるなんて方法もありかと思います。