Newer
Older
geoconv / geoconv.rb
@HIROSE Yuuji HIROSE Yuuji on 9 Feb 2 KB Fix
#!/usr/bin/env ruby
require 'csv'
require 'json'
require 'open-uri'
require 'cgi'
# require 'pstore'
require 'yaml/store'

# [yuzaaed.csv]
# 施設名,設置場所,屋内外,住所,24h,,地図

yolp = 'https://map.yahooapis.jp/geocode/V1/geoCoder?'
yolocal = "https://map.yahooapis.jp/search/local/V1/localSearch?"
# cache = PStore.new("geoconv.pstore")
cache = YAML::Store.new("geoconv.yaml")
appid = IO.read(".appid").chomp
YOLP_baseurl = yolp + "appid=#{appid}&output=json&query="
YOLOCAL_baseurl = yolocal + "appid=#{appid}&output=json&query="

GSI_base = 'https://msearch.gsi.go.jp/address-search/AddressSearch?q='

SLEEP = (ENV["SLEEP_SECS"] || 5)

aed = CSV.read(ARGV[0], headers:true)


puts (aed.headers+["lon", "lat", "description"]).to_csv.sub("施設名", "name")
def outerr(addr)
    STDERR.puts "#{addr}は変換不能"
    STDERR.puts "-"*50
end
def geocode_gsi(addr)
  return $geo[addr] if $geo[addr]
  request = GSI_base+CGI.escape(addr)

  begin
    json = URI.open(request){|u| u.read}
    STDERR.puts "---DONE---" if $DEBUG
  ### puts JSON.pretty_generate(JSON.parse(json))
    # こんなふう
    # [{"geometry":{"coordinates":[139.917679,38.992184],"type":"Point"},"type":"Feature","properties":{"addressCode":"","title":"山形県遊佐町豊岡"}}]
    answer = JSON.parse(json)[0]	# 配列で来るようだ
  rescue
    return nil
  end
  # "Coordinates": "139.92680911,38.99745103",
  $geo[addr] = answer["geometry"]["coordinates"]
end
def geocode_yolp(addr, base=YOLP_baseurl)
  # https://qiita.com/takataka5845/items/4469fcc7226c8ef332b9
  return $geo[addr] if $geo[addr]
  request = base+CGI.escape(addr)
  STDERR.puts "q=#{addr}" if $DEBUG
  begin
    json = URI.open(request){|u| u.read}
    # こんなふう from YOLP
    #   "Geometry": {
    #       "Type": "point",
    #       "Coordinates": "139.92680911,38.99745103",
    #       "BoundingBox": "139.9256460,38.9963590 139.9300200,38.9986830"
    #   },
    answer = JSON.parse(json)["Feature"][0]
    STDERR.puts "ANS=#{answer}" if $DEBUG
  rescue
    STDERR.puts "#{addr}ではだめだった!!"
    STDERR.puts json
    return nil
  end
  $geo[addr] = answer["Geometry"]["Coordinates"].split(",")
end
# https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/localsearch.html
def geocode_yolp_local(spot)
  geocode_yolp(spot, YOLOCAL_baseurl)
end

cache.transaction do
  cache["geodata"] ||= Hash.new
  $geo = cache["geodata"]
  aed.each do |row|
    name = row["施設名"]
    addr = row["住所"].sub(/番地の?/, "-")
    if /(.*[市町村郡])/ =~ addr
      name = $1 + " " + name
    end
    #coord = geocode_yolp_local(name)||geocode_yolp(addr)||geocode_gsi(addr)
    coord = geocode_yolp(addr)||geocode_yolp_local(name)||geocode_gsi(addr)
    unless coord
      outerr(addr)
      next
    end
    sleep SLEEP			# 速度控えめに
    desc  = %w(設置場所 使用可能時間帯等 屋内外 住所).collect do |k|
      k + ": " + row[k].to_s
    end.join("\n")
    print (row.to_h.values+coord+[desc]).to_csv
  end
end