대전광역시 버스정보 API를 이용해서 평소 타고다니는
출/퇴근 버스 도착시간 평균을 구해보자 라는 취지로 API 를 이용해보기로했다
대전버스라는 어플이 있지만 언제쯤 도착(실시간)한다는거지
시간대별(분 단위) 평균 버스도착시간을 알려주질 않으니
평균 도착시간을 이용해서 아 다음건 언제 오겠구나
지금 꼭 타야하는구나(택시타야 되나?) 이런걸 알고 싶었다
늦장 대마왕이라...
한마디로 지극히 개인적인 이유로 API를 이용한다는 소리
근데 교통체증도 제공해주는진 모르겠고...
교통정보 공개서비스(http://openapi.its.go.kr), 공간정보 오픈플랫폼(http://dev.vworld.kr)에서 제공하는듯..
자세한건 안봐서...
좀더 확인해보긴 해야겠지만 네비게이션 서비스의 API가 이런게 다 되 있을 확률이 높다
(실시간 교통정보를 이용해 안내를 해주니)
그런의미로 SK플래닛의 T-MAP (https://developers.skplanetx.com/apidoc/kor/t-map/traffic-report/)도 API를 제공하는듯 하다
교통사고정보 개방시스템(http://taas.koroad.or.kr/)
교통체증과 교통사고 데이터를 받아와서 도착시간을 같이 보는것도 나쁘지 않을듯, 근데 험난할듯.. 버스노선 GIS로 받아와서 노선의 정체구간이랑... 생각만 해도 머리아픔
날씨야 뭐 기상청API쓰면됨
이러한 외부정보를 이용하는건 예측불가능한 상황이 발생할 수 있기때문인데
월~금을 기준으로 특정요일에 차가 막히는경우, 날씨가 안좋아서 서행하는경우
해당구간에 교통사고가 발생한경우, 버스가 엔진이 꺼진경우 등등의 상황이 있기때문에
무시할 수 없기 때문이다
노선만해도 버스정류장이 정해져있기 때문에 특히나 탑승정류장의 도착시간만 계산한다고 했을때
쉬워보이지만 쉽지가 않다
105번 버스를 놓고 보면 비래동에서 어은동까지 지나치는 동이 다양하고
날씨, 교통체증, 교통사고등의 다양한 정보를 모아봐야
그 시점에 왜 버스가 늦게 도착했는지에 대해 알 수 있다
교통사고가 발생해서 10분 늦게 도착했을때, 혹은 공휴일 교통체증이라는 변수를 캐치할 수 없어
단순 평균 계산 시 전혀 의외의 시간이 나오기 때문이다
이러한 외부데이터를 연계하기 위해선 버스 노선에 대한 주소와 날씨정보, 공휴일 등를 복합적으로 사용해야
신뢰도가 높아지고, 당연하게도 신뢰성을 높이기위해선 데이터양이 많아야 된다
이런걸 빅데이터 분석이라고 부른다...
데이터 연계를 위해선 지번주소, 법정동, 행정동 등의 위치기반 데이터를 구축하고
교통체증 구간과, 사고구간, 날씨, 대한민국 공휴일 등의 변수를 대입해야한다
그리고 정류장에서 제공하는 도착예상시간이 단지 거리만 계산해서 나온건지
교통 체증, 날씨 등의 외부적인 요소를 포함된건지를 알 수 있기 때문이다
단순하게 시작했는데 전혀 단순하지가 않아서
일단 처음 의도한 대로 심플하게 구성하기로 했다(요일... 공휴일 따위...)
이것저것 섞는건 하나라도 제대로 하고, 연계방향을 세우고 한다음에 해도 늦지않으니...
이것저것 합치면 논문지 투고해도 될듯...
출처: https://www.data.go.kr/dataset/3034842/openapi.do
대전광역시 버스정보 API는 6종류를 제공함 (망할 XML만 지원...)
근데 보이는 순서랑 서비스명(국문)이 API 문서랑 다름, 영문명으로 구분해야함..
상세정보를 누르면 EndPoint 라던지 대략적인 정보를 제공하니 확인은 직접..
참고한 API문서는
No |
서비스명(국문) |
서비스명(영문) |
1 |
버스운행정보 조회 서비스 |
busRouteInfo |
2 |
버스정류장정보 조회 서비스 |
stationinfo |
3 |
버스위치정보 조회 서비스 |
busposinfo |
4 |
정류장 버스도착 정보 조회 서비스 |
arrive |
5 |
버스 차량 등록 정보 조회 서비스 |
busreginfo |
6 |
운수회사 등록 정보 조회 서비스 |
buscompinfo |
편의상 API문서기준으로 진행...
EndPoint는 서비스명(영문)과 각 서비스별 상세 기능으로 구분됨
차량등록정보, 운수회사는 조회할 일이 거의 없을것 같으니
4개의 서비스를 이용해보기로 했다
그래도 하는김에 전부 다 보지뭐
서비스 이용에 있어 사용되는 필수 Key 값은 4개로 보임
당연한 이야기지만 인증키인 serviceKey는 없으면 API를 사용못함..
No |
항목명(영문) |
항목명(국문) |
항목크기 |
항목설명 |
1 |
reqPage |
요청페이지 |
3 |
요청페이지 |
2 |
busRouteId |
노선ID |
8 |
노선의고유식별자 |
3 |
BusStopID |
정류소ID(7자리) |
7 |
정류소ID(7자리) |
4 |
|
정류소ID(5자리) |
5 |
정류소ID(5자리) |
No |
항목명(영문) |
항목명(국문) |
항목크기 |
항목설명 |
1 |
headerCd |
결과코드 |
2 |
결과코드 |
2 |
headerMsg |
결과메세지 |
50 |
결과메세지 |
3 |
msgBody |
결과리스트 |
4 |
결과리스트 |
4 |
currentPage |
요청된 페이지 |
3 |
요청된 페이지 |
5 |
itemCnt |
결과값 총 수 |
6 |
결과값 총 수 |
6 |
itemPageCnt |
결과 페이지 수 |
5 |
결과 페이지 수 |
출처: https://www.data.go.kr/
인증키를 받고 개발계정 상세페이지를 보면 응답 XML을 확인해볼수 있다
참고로 하단의 미리보기는 xml을 브라우져에서 볼수 있고
나머진 파일로 다운받는다
근데 XML만 지원하니 눌러볼 필요가없다(API 명세에도 XML 지원만써있다)
포탈공통 프레임이라 버튼이 있는듯 하다 기능이 없으면 안보이게 해주지
json 지원하는줄 알고 잠시 설례였음...
출처: https://www.data.go.kr/
실행해보면 아래처럼 샘플로 데이터를 볼수 있다
출처: http://openapitraffic.daejeon.go.kr
XML이니 트리(tree)구조로
XML 파싱은 JSOP(JAVA 기준)을 쓰면 된다
No |
오퍼레이션명(영문) |
오퍼레이션명(국문) |
필수 key |
1 |
getStaionByRoute |
노선별 경유 정류소 목록 조회 |
busRouteId |
2 |
getStaionByRouteAll |
전체 노선별 경유 정류소 목록 조회 |
reqPage |
3 |
getRouteInfo |
노선정보 상세 조회 |
busRouteId |
4 |
getRouteInfoAll |
전체 노선별 노선정보 조회 |
reqPage |
No |
항목명(영문) |
항목명(국문) |
항목크기 |
항목설명 |
1 |
BUSSTOP_ENG_NM |
정류소영문명 |
50 |
정류소영문명 |
2 |
BUSSTOP_NM |
정류소명 |
50 |
정류소명 |
3 |
BUSSTOP_SEQ |
경유정류소순번 |
3 |
경유정류소순번 |
4 |
BUSSTOP_TP |
정류소타입 |
1 |
정류장 유형(1:기점 2: 종점 3: 일반) |
5 |
BUS_NODE_ID |
정류소ID |
7 |
정류소ID |
6 |
BUS_STOP_ID |
정류소ARS-ID |
5~6 |
정류소ARS-ID 대전(5), 광역(6) |
7 |
GPS_LATI |
정류소 위도좌표 |
15 |
정류소 위도좌표 |
8 |
GPS_LONG |
정류소 경도좌표 |
15 |
정류소 경도좌표 |
9 |
ROAD_NM |
도로명 |
50 |
도로명 |
10 |
ROAD_NM_ADDR |
도로주소 |
200 |
도로주소 |
11 |
ROUTE_CD |
노선ID |
8 |
노선ID |
12 |
TOTAL_DIST |
누적거리 |
8 |
누적거리 |
전체 정류소 정보를 알아야 하니 실행해봤다 그것도 reqPage=0 으로
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <ServiceResult> <comMsgHeader/> <msgHeader> <currentPage>0</currentPage> <headerCd>0</headerCd> <headerMsg>정상적으로 처리되었습니다.</headerMsg> <itemCnt>9480</itemCnt> <itemPageCnt>95</itemPageCnt> </msgHeader> <msgBody/> </ServiceResult> |
결과는 예상을 뛰어넘었다... 에러따윈 없다
itemPageCnt가 95개로 나오는데.. msgBody는 내용이 없다
1-95페이지까지 있다는 소린가보다
혹시몰라 96을 시도해보니 0페이지랑 같다
No |
항목명(영문) |
항목명(국문) |
항목크기 |
항목설명 |
1 |
ALLO_INTERVAL |
배차간격 |
3 |
배차간격 |
2 |
ALLO_INTERVAL_SAT |
휴일배차간격 |
4 |
휴일배차간격 |
3 |
ALLO_INTERVAL_SUN |
공휴일배차간격 |
4 |
공휴일배차간격 |
4 |
BUSSTOP_CNT |
정류장개수 |
3 |
정류장개수 |
5 |
END_NODE_ID |
종점정류소ID(7자리) |
7 |
종점정류소ID(7자리) |
6 |
END_STOP_ID |
종점정류소ID(5자리) |
5 |
종점정류소ID(5자리) |
7 |
ORIGIN_END |
평일 기점 막차시간 |
4 |
평일 기점 막차시간 |
8 |
ORIGIN_END_SAT |
토요일 기점 막차시간 |
4 |
토요일 기점 막차시간 |
9 |
ORIGIN_END_SUN |
일요일 종점 막차시간 |
4 |
일요일 종점 막차시간 |
10 |
ORIGIN_START |
평일 기점 첫차시간 |
4 |
평일 기점 첫차시간 |
11 |
ORIGIN_START_SAT |
토요일 기점 첫차시간 |
4 |
토요일 기점 첫차시간 |
12 |
ORIGIN_START_SUN |
일요일 기점 첫차시간 |
4 |
일요일 기점 첫차시간 |
13 |
ROUTE_CD |
노선ID |
8 |
노선ID |
14 |
ROUTE_NO |
노선명칭 |
10 |
노선명칭 |
15 |
ROUTE_TP |
노선유형 |
1 |
노선타입 (1:급행, 2:간선,3:지선, 4:외곽, 5:마을, 6:첨단) |
16 |
RUN_DIST_HALF |
반환지점 거리(KM) |
20 |
반환지점 거리(KM) |
17 |
RUN_TM |
평균 운행시간 |
4 |
평균 운행시간 |
18 |
START_NODE_ID |
기점정류소ID(7자리) |
7 |
기점정류소ID(7자리) |
19 |
START_STOP_ID |
기점정류소ID(5자리) |
5 |
기점정류소ID(5자리) |
20 |
TURN_END |
평일 반환지점 막차시간 |
4 |
평일 반환지점 막차시간 |
21 |
TURN_END_SAT |
토요일 반환지점 막차시간 |
4 |
토요일 반환지점 막차시간 |
22 |
TURN_END_SUN |
일요일 반환지점 막차시간 |
4 |
일요일 반환지점 막차시간 |
23 |
TURN_NODE_ID |
반환정류소ID(7자리) |
7 |
반환정류소ID(7자리) |
24 |
TURN_START |
평일 반환지점 첫차시간 |
4 |
평일 반환지점 첫차시간 |
25 |
TURN_START_SAT |
토요일 반환지점 첫차시간 |
4 |
토요일 반환지점 첫차시간 |
26 |
TURN_START_SUN |
일요일 반환지점 첫차시간 |
4 |
일요일 반환지점 첫차시간 |
27 |
TURN_STOP_ID |
반환정류소ID(5자리) |
5 |
반환정류소ID(5자리) |
27개나 된다 참 많다
휴일과 공휴일의 차이가 뭘까 고민했는데 의미 없는 짓이었다
SAT, SUN 으로 끝나는데 설마설마 했는데
역시나 아래에는 토요일, 일요일이라고 명시해놨다, 통일좀 하지
노선은 몇개나 될까
역시나 reqPage=0 으로 시도해봤다
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <ServiceResult> <comMsgHeader/> <msgHeader> <currentPage>0</currentPage> <headerCd>0</headerCd> <headerMsg>정상적으로 처리되었습니다.</headerMsg> <itemCnt>122</itemCnt> <itemPageCnt>2</itemPageCnt> </msgHeader> <msgBody/> </ServiceResult> |
122개의 노선을 가지고 있나보다 page는 2개로 보인다
참고로 결과값을 보면 전부 숫자로 되어있는데 공백이 여기저기 포함되있다
trim으로 제거해줘야 정신건강에 좋다 아니면 전부 문자처리해도 될듯
우선 전체 노선별 경유 정류소목록조회를 시도하였다
정류소 ID랑 노선을 알아야 뭘 만들던가 하니까 말이다
정류소 데이터는 9489건으로 95페이지나 조회해야한다
API명세서를 보고 대충 DB 테이블을 만들고
(귀찮으니 위경도 빼고, 전부 varchar로 잡아줬다, PK설명이 없으니 PK도 안줬다)
XML 파서를 만들어서 INSERT 작업을 수행하게 하였다
근데 전체건수를 맞춰보는중 멘붕아닌 멘붕에빠졌다
9240건으로 249건이나 안맞았다
대충 보니 눈에 띄는 에러는 데이터 사이즈였다..
정류소영문명 과 정류소ARS-ID 컬럼을 명세서대로 해놨더니 자릿수가 넘어가는게 있었나보다
2-3번의 컬럼사이즈 조정후 건수확인하니 전체건수가 맞아 떨어진다
(9240건 insert문을 살펴보느니 error 메시지를 모아서 한번에 보여주도록 기능도 추가했다...)
자리수 비교를 위해 length 함수와 max 함수를 이용해서 실제 크기를 비교해봤다
No |
항목명(영문) |
항목명(국문) |
항목크기 |
실제 크기(Max 기준) |
1 |
BUSSTOP_ENG_NM |
정류소영문명 |
50 |
70 |
2 |
BUSSTOP_NM |
정류소명 |
50 |
41 |
3 |
BUSSTOP_SEQ |
경유정류소순번 |
3 |
3 |
4 |
BUSSTOP_TP |
정류소타입 |
1 |
1 |
5 |
BUS_NODE_ID |
정류소ID |
7 |
7 |
6 |
BUS_STOP_ID |
정류소ARS-ID |
5~6 |
7 |
7 |
GPS_LATI |
정류소 위도좌표 |
15 |
7 |
8 |
GPS_LONG |
정류소 경도좌표 |
15 |
7 |
9 |
ROAD_NM |
도로명 |
50 |
24 |
10 |
ROAD_NM_ADDR |
도로주소 |
200 |
9 |
11 |
ROUTE_CD |
노선ID |
8 |
8 |
12 |
TOTAL_DIST |
누적거리 |
8 |
6 |
정류소 영문명, 정류소ARS-ID 두개의 크기가 달랐다
사소한건 넘어가고 PK 를 잡아보기로 했다
대충봐서는 노선ID, 정류소ID 두개를 잡으면 될것 같았다
근데 실패했다...
노선ID 와 정류소ID 를 합친 문자열을 중복제거하니 9340건으로 140건이나 차이난다
노선ID 만 보면 122건으로 전체 노선별 노선정보 조회 건수랑 일치한다
정류소 ID 만보면 3165 건이다
정류소ARS-ID 가 NULL인게 2건이나오고, 중복제거하면 3061건(null 포함) 이다
노선ID, 정류소ID, 정류소ARS-ID 세개를 묶어도 9338건이다.. 142건이 차이난다..
PK잡지말까... 란 생각이 들었다..
일단 무시하고...
다음 으로 넘어가기로 했다
아.. 참고로 영문명이 없는경우 --- 가 들어있다
null로 치환했다...
전체 노선별 경유 정류소 목록 조회에서 노선ID만 봤을때는 중복제거 카운트가 일치하니
좀 안심하고 진행했다 설마...
응답 메시지 1-2개를 봤을땐 전부 숫자니
테이블도 숫자로 잡을까 하다가 varchar로 잡았다 나중에 삽질하기 싫었다..
역시 예상은 했지만 stop_id 로 끝나는 컬럼이 사이즈문제로 에러가났다 7로 조정해주고 다시 진행했다
(7로 조정했지만 다시확인해보니 6이었다)
노선ID가 중복이 없어서 깔끔하게 끝났다
참고로 전체노선별 경유 정류소 목록조회에서
정류소영문명 자릿수가 50이 넘어가는 항목은 97건이고
정류소ARS-ID 자릿수가 7인 항목은 141건이다
*PS.
설마 활용신청 자동승인인 서비스인데 무슨일이 있겠냐만은..
문제 있을시 알려주시면 내리겠습니다
공공데이터 API - 대전광역시 버스정보 3부 (정류소별 도착정보 조회 서비스) (0) | 2017.08.28 |
---|---|
공공데이터 API - 대전광역시 버스정보 2부 (정류소정보조회 서비스, 버스위치정보 조회 서비스) (0) | 2017.08.14 |
Tistory BlogAPI 중단 (MS WORD BLOGAPI) (4) | 2016.12.23 |
기상청 지진정보조회 API (지진정보조회 API) (9) | 2016.10.04 |
기상청 날씨정보 API(동네예보정보조회서비스) 활용을 위한 행정동코드 작업과 날씨조회 (0) | 2016.09.26 |
댓글 영역