地盤データのオープンデータハッカソンが jig.jp さんで開催されたので、学生さんを何人か誘って、おまけ参加。
github.com に 福井県のボーリング情報があるけど、要望の中に緯度経度が間違ったデータがあるとの
お話だったので、XML データの緯度経度と、ボーリング箇所の町名データを比較するプログラムを書いてみた。
しかしながら、町名といっておきながら、先頭に川の名前がついていたり、複数の町をまたがっているから○○町〜○○町といった町名記載があって、ボーリングの住所から緯度経度がとれないことが多発。
ということで、ボーリングデータを登録する側で、住所の記載方法を統一化してほしいよねぇ〜という感想。
#!/usr/bin/env python3
import requests
import csv
import re
from bs4 import BeautifulSoup
import geocoder
import math
url_top = "https://raw.githubusercontent.com/GeoFUKUI/jiban-opendata/main/filelist.csv"
url_data = "https://raw.githubusercontent.com/GeoFUKUI/jiban-opendata/mai\ n/data/"
res = requests.get( url_top )
if res.ok :
for line in res.text.splitlines() :
url , type , size = line.split(',')
if re.match( '.*/DATA/BED\d\d\d\d\.XML$' , url ) :
xml_url = url_data + url
xml_res = requests.get( xml_url )
if xml_res.ok :
soup = BeautifulSoup( xml_res.text , 'xml' )
# <経度緯度情報><{緯度|経度}_{度|分|秒}>
for lat_lng in soup.find_all( '経度緯度情報' ) :
# <調査位置><調査位置住所>
lat_deg = int( lat_lng.find( '緯度_度' ).string )
lat_min = int( lat_lng.find( '緯度_分' ).string )
lat_sec = float( lat_lng.find( '緯度_秒' ).string )
lng_deg = int( lat_lng.find( '経度_度' ).string )
lng_min = int( lat_lng.find( '経度_分' ).string )
lng_sec = float( lat_lng.find( '経度_秒' ).string )
lat = lat_deg + lat_min / 60 + lat_sec / 3600
lng = lng_deg + lng_min / 60 + lng_sec / 3600
# print( lat )
addr = soup.find( '調査位置住所' ).string
addr = re.sub( '地係$' , '' , addr )
addr = re.sub( ' ' , '' , addr )
addr = re.sub( '(~|から).*$' , '' , addr )
addr = re.sub( '^.*福井県' , '' , addr )
addr = re.sub( '(.*)' , '' , addr )
addr = re.sub( '\(.*\)' , '' , addr )
addr = "福井県" + addr
#print( addr )
geo_addr = geocoder.osm( addr , timeout = 5.0 )
if geo_addr is None :
print( "None" )
elif isinstance( geo_addr.latlng , list ) :
geo_lat , geo_lng = geo_addr.latlng
err = math.sqrt( (lat - geo_lat)**2 + (lng - geo_lng)**2 )
if err > 0.001 :
print( "(%f,%f)-(%f,%f)-%s"
% ( lat , lng , geo_lat , geo_lng , addr ) )
else :
print( "(%f,%f) not [LAT LNG] -%s" % ( lat , lng , addr ) )
#!/usr/bin/env python3
import requests
import csv
import re
from bs4 import BeautifulSoup
import geocoder
import math
url_top = "https://raw.githubusercontent.com/GeoFUKUI/jiban-opendata/main/filelist.csv"
url_data = "https://raw.githubusercontent.com/GeoFUKUI/jiban-opendata/mai\ n/data/"
res = requests.get( url_top )
if res.ok :
for line in res.text.splitlines() :
url , type , size = line.split(',')
if re.match( '.*/DATA/BED\d\d\d\d\.XML$' , url ) :
xml_url = url_data + url
xml_res = requests.get( xml_url )
if xml_res.ok :
soup = BeautifulSoup( xml_res.text , 'xml' )
# <経度緯度情報><{緯度|経度}_{度|分|秒}>
for lat_lng in soup.find_all( '経度緯度情報' ) :
# <調査位置><調査位置住所>
lat_deg = int( lat_lng.find( '緯度_度' ).string )
lat_min = int( lat_lng.find( '緯度_分' ).string )
lat_sec = float( lat_lng.find( '緯度_秒' ).string )
lng_deg = int( lat_lng.find( '経度_度' ).string )
lng_min = int( lat_lng.find( '経度_分' ).string )
lng_sec = float( lat_lng.find( '経度_秒' ).string )
lat = lat_deg + lat_min / 60 + lat_sec / 3600
lng = lng_deg + lng_min / 60 + lng_sec / 3600
# print( lat )
addr = soup.find( '調査位置住所' ).string
addr = re.sub( '地係$' , '' , addr )
addr = re.sub( ' ' , '' , addr )
addr = re.sub( '(~|から).*$' , '' , addr )
addr = re.sub( '^.*福井県' , '' , addr )
addr = re.sub( '(.*)' , '' , addr )
addr = re.sub( '\(.*\)' , '' , addr )
addr = "福井県" + addr
#print( addr )
geo_addr = geocoder.osm( addr , timeout = 5.0 )
if geo_addr is None :
print( "None" )
elif isinstance( geo_addr.latlng , list ) :
geo_lat , geo_lng = geo_addr.latlng
err = math.sqrt( (lat - geo_lat)**2 + (lng - geo_lng)**2 )
if err > 0.001 :
print( "(%f,%f)-(%f,%f)-%s"
% ( lat , lng , geo_lat , geo_lng , addr ) )
else :
print( "(%f,%f) not [LAT LNG] -%s" % ( lat , lng , addr ) )
#!/usr/bin/env python3 import requests import csv import re from bs4 import BeautifulSoup import geocoder import math url_top = "https://raw.githubusercontent.com/GeoFUKUI/jiban-opendata/main/filelist.csv" url_data = "https://raw.githubusercontent.com/GeoFUKUI/jiban-opendata/mai\ n/data/" res = requests.get( url_top ) if res.ok : for line in res.text.splitlines() : url , type , size = line.split(',') if re.match( '.*/DATA/BED\d\d\d\d\.XML$' , url ) : xml_url = url_data + url xml_res = requests.get( xml_url ) if xml_res.ok : soup = BeautifulSoup( xml_res.text , 'xml' ) # <経度緯度情報><{緯度|経度}_{度|分|秒}> for lat_lng in soup.find_all( '経度緯度情報' ) : # <調査位置><調査位置住所> lat_deg = int( lat_lng.find( '緯度_度' ).string ) lat_min = int( lat_lng.find( '緯度_分' ).string ) lat_sec = float( lat_lng.find( '緯度_秒' ).string ) lng_deg = int( lat_lng.find( '経度_度' ).string ) lng_min = int( lat_lng.find( '経度_分' ).string ) lng_sec = float( lat_lng.find( '経度_秒' ).string ) lat = lat_deg + lat_min / 60 + lat_sec / 3600 lng = lng_deg + lng_min / 60 + lng_sec / 3600 # print( lat ) addr = soup.find( '調査位置住所' ).string addr = re.sub( '地係$' , '' , addr ) addr = re.sub( ' ' , '' , addr ) addr = re.sub( '(~|から).*$' , '' , addr ) addr = re.sub( '^.*福井県' , '' , addr ) addr = re.sub( '(.*)' , '' , addr ) addr = re.sub( '\(.*\)' , '' , addr ) addr = "福井県" + addr #print( addr ) geo_addr = geocoder.osm( addr , timeout = 5.0 ) if geo_addr is None : print( "None" ) elif isinstance( geo_addr.latlng , list ) : geo_lat , geo_lng = geo_addr.latlng err = math.sqrt( (lat - geo_lat)**2 + (lng - geo_lng)**2 ) if err > 0.001 : print( "(%f,%f)-(%f,%f)-%s" % ( lat , lng , geo_lat , geo_lng , addr ) ) else : print( "(%f,%f) not [LAT LNG] -%s" % ( lat , lng , addr ) )
個人的なお遊びで、Webデータのスクレイピングは色々と体験あるけど、今までは Perl を使っていた。今回は、自分のチャレンジということで、Python を使ってスクレイピング。