컴공돌이의 취미 블로그

[2]. 공공데이터 포털 OpenAPI 사용 방법 - (2) 본문

Study/OpenAPI

[2]. 공공데이터 포털 OpenAPI 사용 방법 - (2)

컴공돌이​​ 2017. 8. 2. 12:00

[2]. 공공데이터 포털 OpenAPI 사용 방법 - (2)


오늘은 지난번에 작성한 공공데이터 포털 의 OpenAPI 의 사용법중에서도 실질적으로 사용하는 코드에 대한 글을 작성해보고자 한다.


이전 글의 순서대로 진행을 하면 공공데이터 포털의 OpenAPI 에 접근할 수 있는 Url을 받을 수 있을 것이고 또한 인증키 발급과 사용법도 알 수 있을 것이다.


이제 OpenAPI를 사용하여 데이터를 가져오는 코드를 분석해 보자.


<코드 분석>

(1). XML 패키지의 설치와 호출

1
2
install.packages("XML")
library(XML)
cs

이전 글에서 살펴보면 OpenAPI를 통해서 가져올수 있는 데이터의 형태는 xml 혹은 json 이다.

이번글에서는 xml파일의 형태로 데이터를 가져올 것이기 때문에, 데이터를 다루기 위해서 xml 패키지를 설치하고 호출하여 사용할 것이다.


(2). RCurl 패키지의 설치와 호출

1
2
install.packages("RCurl")
library(RCurl)
cs

코드의 중간에 페이지의 형태를 읽어들이는 함수 getForm() 이라는 함수가 있다.

이 함수는 RCurl의 패키지 안에 저장되어져 있는 함수이기 때문에 이를 사용하기 위해서 RCurl 패키지를 설치하고 호출한다.


(3). 요청주소의 인자들

1
2
3
4
5
6
7
8
url1 <- "http://api.visitkorea.or.kr/openapi/service/rest/KorService/"
category <- "searchFestival"
url2 <- "?serviceKey="
mykey <- "oooooooooo"
url3 <- "&numOfRows=100"
url4 <- "&MobileOS=ETC"
url5 <- "&MobileApp=TestApp"
url6 <- "&pageNo="
cs

OpenAPI에 접근할 Url을 구성하는 인자들이다.

url이라고 써져있는 인자들은 수정하면 안되는 인자들이고, category, mykey는 수정이 가능한 인자이다.

category는 어떠한 분야의 데이터를 가져오고 싶은지 공공데이터 포털 홈페이지에서 확인 후 원하는 코드를 적으면 된다.

mykey는 공공데이터 포털에서 발급받은 인증키를 복사하여 붙여넣기 하면 된다.

위의 인자들에서 페이지 번호만 집어넣으면 요청주소가 완성된다.


(4). 데이터를 저장할 데이터프레임 선언

1
table <- data.frame()
cs

OpenAPI를 통해서 읽어들인 데이터를 저장하기위해서 데이터 프레임을 선언해 준다.


(5). 페이지 번호를 1로 해서 접근한 후 총 데이터 개수와 데이터 개수를 이용하여 총 페이지 개수를 구함
1
2
3
4
5
requestUrl <- paste(url1, category, url2, mykey, url3 , url4, url5, url6, sep="")
page = getForm(paste(requestUrl, "1", sep=""), query="")
doc = xmlToDataFrame(page)
totaldataNumber = as.numeric(doc[2,6])
totalPageNumber = (totaldataNumber%/%100+ 1
cs

requestUrl에 앞에서 적은 요청주소 인자들을 합쳐서 요청주소를 완성한다.

그리고 요청주소의 맨 뒤에 페이지 번호 1을 붙여서 OpenAPI에 우선 접근을 한다.

OpenAPI를 사용해서 접근한 페이지에는 데이터의 양이 한정되어 있다.

따라서 위에서 만든 요청주소 뒤에 페이지의 번호를 붙여서 완벽한 요청주소를 만들어야한다.

기본 요청주소를 통하여 접근한 페이지를 보면 전체 데이터의 수가 나와 있다.

이때 우리는 한 페이지에 보이는 데이터 수를 위에서 100으로 설정하였으므로, 한 페이지에는 100개의 데이터가 나와있다.

따라서전체 데이터수에 100을 나누어서 전체 페이지 개수를 구할수 있는 것이다.


(6). 모든 페이지의 데이터를 구하기 위해서 반복문을 사용하여 요청 주소를 설정하기

1
2
3
4
for(pageNumber in 1:totalPageNumber){
      Url <- paste(requestUrl, pageNumber, sep="")
      ......
}
cs

requestUrl과 반복문에서 사용된 페이지 번호를 합쳐서 요청주소를 완성한다.


(7). 반복문 내부 코드 1 - 페이지 정보 리스트화 & 페이지에 들어있는 데이터 개수 확인

1
2
3
4
5
6
7
page = getForm(Url, query="")
doc = xmlParse(page)
doc = xmlToList(doc)
index = 100
if(pageNumber == totalPageNumber){
    index = totaldataNumber - ((totalPageNumber-1)*100)
}
cs

접근한 OpenAPI에서 데이터를 읽어들인 후 xmlParse와 xmlToList 함수를 거쳐서 데이터를 리스트화 시킨다.

위에서 설정한 것처럼 한 페이지에는 100개의 데이터가 들어있는데 마지막 페이지에는 데이터의 개수가 100개보다 부족할 수 있다.

이것을 체크하기 위해서 마지막 페이지 번호가 아니라면 데이터의 개수는 100개, 마지막 페이지 번호라면 전체 데이터 개수에 (페이지수-1)*100 을 빼서 데이터의 개수를 구한 후 저장해 둔다.


(8). 반복문 내부 코드 2 - 모든 페이지의 데이터를 하나의 테이블에 저장하기

1
2
3
4
5
6
7
8
9
10
library(plyr)
for(i in 1:index){
    ex <- data.frame(doc[2]$body$items[i])
    if(length(table)==0){
        table <- ex
    }
    else{
        table <- rbind.fill(table, ex)
    }
}
cs

위에서 리스트화 시킨 페이지의 데이터에서 실질적인 데이터가 들어있는 부분을 추출하여 ex에 저장한다.

그리고 table을 검사하여 비어있는 경우는 현재 읽어들인 페이지의 데이터를 테이블에 저장하고 만약 비어있지 않은 경우에는 데이터를 table에 이어서 붙인다.

이때, 공공데이터 포털의 데이터는 데이터 마다 데이터 열의 개수가 다를 수 있으므로 rbind.fill() 함수를 하용하여 table에 이어서 붙여준다.

이때 rbind.fill() 함수를 사용하기 위해서 plyr 패키지를 호출해준다.


<전체 코드>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// xml 형식의 데이터를 다루기 위해서 패키지를 다운 후 호출
install.packages("XML")
library(XML)
 
// 특정 함수를 사용하기 위해서 패키지를 다운 후 호출
install.packages("RCurl")
library(RCurl)
 
// rbind.fill() 함수를 사용하기 위해서 패키지를 호출
library(plyr)
 
//////요청주소 요소들
////바꿀 필요 없는 부분
url1 <- "http://api.visitkorea.or.kr/openapi/service/rest/KorService/"
url2 <- "?serviceKey="
url3 <- "&numOfRows=100"
url4 <- "&MobileOS=ETC"
url5 <- "&MobileApp=TestApp"
url6 <- "&pageNo="
 
//// 원하는 값을 입력하는 부분
// 데이터를 가져올 카테고리 명
category <- "searchFestival"
// 발급받은 인증키
mykey <- "oooooooooo"
 
// 데이터를 저장할 데이터 프레임을 선언
table <- data.frame()
 
// 위에 설정해 놓은 요청주소에 필요한 모든것을 이어붙여서 요청주소를 생성
requestUrl <- paste(url1, category, url2, mykey, url3 , url4, url5, url6, sep="")
// 데이터의 총개수와 페이지 개수를 구하기 위해서 우선적으로 페이지 번호를 1으로 설정하여 데이터를 읽어들임
page = getForm(paste(requestUrl, "1", sep=""), query="")
// xml형식의 파일을 Data frame의 형태로 변환하여 저장 
doc = xmlToDataFrame(page)
// 데이터의 총 개수를 가져옴
totaldataNumber = as.numeric(doc[2,6])
// 데이터가있는 페이지 번호를 구하기 위해서 전체 데이터 개수를 구한 후 100으로 나눔
totalPageNumber = (totaldataNumber%/%100+ 1
try(
  {
    // 1번째 페이지부터 마지막 페이지까지 반복문을 실행
    for(pageNumber in 1:totalPageNumber){
      //요청주소뒤에 페이지 번호를 붙여서 완벽한 주소를 생성
      Url <- paste(requestUrl, pageNumber, sep="")
      // 주소로 부터 데이터를 읽어 들임
      page = getForm(Url, query="")
      // 데이터를 우선적으로 xml 형식으로 가져옴
      doc = xmlParse(page)
      // xml 형식의 데이터를 List 형태의 데이터로 변환후 저장
      doc = xmlToList(doc)
      // 현재 페이지의 데이터 개수를 확인
      index = 100
      //마지막 페이지 번호인지 확인
      if(pageNumber == totalPageNumber){
        // 마지막 페이지이면 데이터의 개수가 100보다 작을 수 있으므로 총 데이터 개수에 (총 페이지개수-1)*100 을 빼서 데이터 개수를 구한다.
        index = totaldataNumber - ((totalPageNumber-1)*100)
      }
      // 페이지에 있는 데이터 수만큼 반복문 실행
      for(i in 1:index){
        // 실질적인 데이터부분을 저장
        ex <- data.frame(doc[2]$body$items[i])
        // table이 비어있는지를 확인
        if(length(table)==0){
          // 비어있다면 데이터를 테이블에 저장
          table <- ex
        }
        else{
          //비어있지 않다면 rbind.fill 함수를 사용하여 table의 뒤에 이어서 붙임
          table <- rbind.fill(table, ex)
        }
      }
    }
  },
  silent = TRUE
)
cs


<코드 실행 시 얻는 데이터>

반응형