지난 시간에는 Get방식으로 제공하는 웹 서비스로부터 json형태의 정보를 얻어와서 내재화하는 방법에 대해서 알아보았습니다. 하지만 모든 서비스가 json으로 제공하는 것은 아니고... xml형태도 있고 제목과 같이 binary로 제공하는 경우도 존재합니다.
따라서, 새로운 방법을 대하였을때 그에 맞춰서 개발을 해주면 됩니다. 그럼 이번에는 binary로 제공하는 서비스를 통해서 나에게 필요한 데이터를 추출해서 사용해 보도록 하겠습니다. 이 경우에는, 추가로 몇가지의 모듈을 import 해주어야 합니다. 다행히 requests외에는 추가로 pip를 통해서 설치할 대상은 없습니다.
- binary를 처리할 모듈
- ZipFile을 처리할 모듈
- ZipFile내부에 xml파일이 있으므로, xml를 파싱할 모듈
1. 서비스 파악하기
Zip FILE (binary)로 제공하는 서비스에 대해서 확인이 먼저 필요합니다. 해당 서비스는 OPEN DART에서 제공하는 API중 한가지로 [공시정보] -> [고유번호]를 제공하는 API입니다. 이 고유번호가 있어야... [상장기업 재무정보] -> [재무제표] 를 구할 수 있습니다.
해당 API를 확인해 보면 아래와 같습니다.
요청 URL이 있으며, 이 API는 GET방식을 사용합니다. 또한, 인코딩이 UTF-8인거보면... 한글이 포함되어 있나보네요?? 출력 포멧이!!! 아까 이야기 했던 Zip FILE (binary) 입니다. 마지막으로 요청인자로는 발급받은 API인증키만 있으면 되네요. 그럼 준비가 끝났습니다.
2. 어떻게 가져올지 고민
기존에 json의 정보를 받을때는 pypi.org에서 모듈설치를 위해 pip 명령어를 받을때, 옆에 간략하게 나온 설명으로 처리가 가능했습니다. 하지만... 거기에는 binary에 대해서는 이야기가 없습니다. 하지만 좌절하지 않고 그 페이지를 자세히 살펴봅니다.
하단에 해당 모듈에 대한 자세한 Document를 제공하는 주소를 제공합니다.
Documentation
Fantastic documentation is available at http://docs.python-requests.org/, for a limited time only.
들어가보면...
이런 사이트가 뜨고... 수많은 정보를 얻을 수 있습니다. 그리고 좌측에 메뉴를 보면 [Quick Start]라는 링크를 제공합니다.
저는 여기서 binary에 대한 처리 방법을 찾을 수 있었습니다. 궁금하신 분들은 찬찬히 살펴보시고... 해당 내용은 아래와 같이 구현이 가능합니다.
import requests
from io import BytesIO
from zipfile import ZipFile
from xml.etree.ElementTree import parse
# Zip FILE (binary)
url = 'https://opendart.fss.or.kr/api/corpCode.xml'
params = {'crtfc_key':'<my api key>'}
res = requests.get(url,params)
print(res.content)
json과 다른점은 response에 json( )을 사용해서 해당 타입으로 변환을 했지만, binary는 response에 content 메서드를 사용해주면 됩니다.
[결과]
x1a]\x01\xce\x10\xfcG\x90\xc69| \xf7\x13x\xee\x18\xc7P0B*F\xad\xd3\xc2\x856\x96\xffU~\x89\
xc5\x03\x99\x9b\x0b\xa3\x11\xe9\x9c\x00\xd8\xb2\xd9\xd7\r\xad\xaa\xa7\x04_*\x04\xf3\xa8|\xbf\
x86\x80\x89k\x8a\x82\x04\x9fz-\x9bvP)\xc4\xf8g\xc0\x80\'8N\x0c\xe9T?a.\xd8\xa6\x13\x9b\xf8L\
xcd\xca~N\xe6\xd4\x08i\xd3cz`\xebq\xff\x85\x14F\x0b\xb88\xbc\xb1\xe9\xba\xdb\xd9\x10\x02\xfch\
xf0\xecn\x90>\xf20(\xc2^+3QZ\xa6\x15C\xce\x8e\xca\xe9=\xb9\xcc\xc48\xc1\xd3\xae\xb2\xc5\xd5\
xd7roI\x0e\xa2q&yZ\x81\x00\xb8\x82#2\xb0\x00\x84\xdb\x10\xa6N\xa0o\x02\x8fk\xfbB\x91\x8d\xa2\
xbbq\x18\x17\xb0hiS\xcf\xa7\x16\x07]\xc8L\xe8\x1cx.=K\xd7\x7f\xa0nr\x9d!\x83%<\xdb\x9c\xbd\xd6\
x91\xe7\xd6`\x0c1\xea2y\xcb2\xc0\x8dR\x12\xcb\xa5J\x83\xf9\xc9\xb2\xc8~\xeeP\t0V2\xc4\xe8X@\xbf\
xfb\xab\'\xa1\xc2<\xdc\xdd\xdaE\x8b\xcaW\x84\xbfm0\xdc\xc6\x1c\xd2\xf0I\x8f\\\x98\x0f\x98\xd8\
xa7\xa7\xe2\xab\x9dc@\x93;\
막 이렇게 생긴 아이들이 출력됩니다. 해당 결과는 바이트스트림으로 원시데이터가 들어와서 출력이 되는 것 입니다. 따라서 byte stream을 우리가 알아볼 수 있는 형태로 변환을 시켜 주어야 합니다.
3. Byte Stream 변환 및 ZipFile 제작
이제 출력포맷인 ZipFile (binary)에서 binary는 처리가 되었고, 이제 그 원시데이터를 잘 변환해서 ZipFile로 만들어 주면 됩니다. 이제 그냥 제목 그대로 따라가면 됩니다. 저는 python에서 원하는 것을 찾을 때는 항상 아래 주소를 통해서 검색해서 이거저거 해봅니다.
그렇다면 binary로 한번 찾아볼까요??
우리가 해주어야 하는 일은 io에 대해서 import를 하고, 그냥 사용해주면 됩니다. 기왕 하는김에 ZipFile로 검색을 해 봅니다.
그렇다면, 여기서 얻은 정보들을 토대로 소스코드를 구성해 보겠습니다.
[소스 코드]
import requests
from io import BytesIO
from zipfile import ZipFile
# Zip FILE (binary)
url = 'https://opendart.fss.or.kr/api/corpCode.xml'
params = {'crtfc_key':'<API KEY>'}
res = requests.get(url,params)
with ZipFile(BytesIO(res.content)) as zipfile:
zipfile.extractall('c:\\corpCode')
처음에 추가할 것이라고 예상되는 모듈에서 2가지를 사용했습니다. BytesIO와 ZipFile입니다. 사용방법은 매우 간단하니 소스 코드를 봐주시면 됩니다. 이렇게 작성하면, API로 부터 받은 내용에 대해서 지정한 경로로 파일이 생성됩니다.
[결과]
크으 감격적이지 않나요?? 그렇다면 이제 생성됨 xml파일에 대해서 읽어오고 처리를 하면 됩니다.
4. xml 파일 처리
왕도는 없습니다. 그냥 마냥 검색하고 Tutorial보고 사용법 확인해서 구현해 보는 방법밖에요... XML 파싱은 상당히 간단하게 기능을 제공합니다. parse라는 메서드를 통해서 xml문서를 가져오고 Tree의 개념으로 찾아가면 되는 방식입니다. 역시나 이런건 소스와 결과를 비교해 보면서 확인하면 되는 것이지용~~~
지금까지의 모든것을 구현한 코드는 아래와 같습니다.
[소스 코드]
import requests
from io import BytesIO
from zipfile import ZipFile
from xml.etree.ElementTree import parse
# Zip FILE (binary)
url = 'https://opendart.fss.or.kr/api/corpCode.xml'
params = {'crtfc_key':'<API KEY>'}
res = requests.get(url,params)
with ZipFile(BytesIO(res.content)) as zipfile:
zipfile.extractall('c:\\corpCode')
# xml 호출하여 읽어오기
xmlTree = parse('c:\\corpCode\corpCode.xml')
root = xmlTree.getroot()
list = root.findall('list')
print(list[0].findtext('corp_code'))
print(list[0].findtext('corp_name'))
print(list[0].findtext('stock_code'))
print(list[0].findtext('modify_date'))
print(root)
[XML 원문양식]
-<result>
-<list>
<corp_code>00434003</corp_code>
<corp_name>다코</corp_name>
<stock_code> </stock_code>
<modify_date>20170630</modify_date>
</list>
-<list>
<corp_code>00434456</corp_code>
<corp_name>일산약품</corp_name>
<stock_code> </stock_code>
<modify_date>20170630</modify_date>
</list>
</result>
[결과]
00434003
다코
20170630
이렇게 마음대로 활용이 가능해 졌습니다.
- Ayotera Lab -
댓글