diff --git a/PublicDataReader/PublicDataPortal/nts.py b/PublicDataReader/PublicDataPortal/nts.py new file mode 100644 index 0000000..cca5cf5 --- /dev/null +++ b/PublicDataReader/PublicDataPortal/nts.py @@ -0,0 +1,77 @@ +import requests +import pandas as pd + + +class Nts: + """ + NTS Open API 클래스 + """ + + def __init__(self, serviceKey=None): + self.serviceKey = serviceKey + self.url_dict = { + "진위확인": "https://api.odcloud.kr/api/nts-businessman/v1/validate", + "상태조회": "https://api.odcloud.kr/api/nts-businessman/v1/status", + } + + def validate(self, businesses): + """ + 사업자등록정보 진위확인 API + + Parameters + ---------- + businesses : list, DataFrame + 사업자등록정보 리스트 (1회 호출 시 최대 100개까지 조회 가능) + + Returns + ------- + DataFrame + 진위확인 결과 + """ + url = self.url_dict["진위확인"] + params = { + "serviceKey": self.serviceKey, + } + if type(businesses) == pd.DataFrame: + businesses = businesses.to_dict("records") + json_data = { + "businesses": businesses, + } + try: + response = requests.post(url, params=params, json=json_data) + df = pd.json_normalize(response.json()['data']) + except Exception as e: + print("Error") + print(e) + return + return df + + def status(self, b_no): + """ + 사업자등록정보 상태조회 API + + Parameters + ---------- + b_no : list + 사업자등록번호 (1회 호출 시 최대 100개까지 조회 가능) + + Returns + ------- + DataFrame + 상태조회 결과 + """ + url = self.url_dict["상태조회"] + params = { + "serviceKey": self.serviceKey, + } + data = { + "b_no": b_no, + } + try: + response = requests.post(url, params=params, json=data) + df = pd.DataFrame(response.json()['data']) + except Exception as e: + print("Error") + print(e) + return + return df diff --git a/PublicDataReader/__init__.py b/PublicDataReader/__init__.py index d198843..696c18a 100644 --- a/PublicDataReader/__init__.py +++ b/PublicDataReader/__init__.py @@ -3,6 +3,6 @@ __all__ = [ "__version__", "__author__", "__contact__", "__github__", - "Transaction", "Building", "StoreInfo", "Transportation", "Kosis", "VworldData", + "Transaction", "Building", "StoreInfo", "Transportation", "Kosis", "VworldData", "Kamco", "Nts", "code_bdong", "get_vworld_data_api_info_by_dataframe", "get_vworld_data_api_info_by_dict", ] diff --git a/PublicDataReader/config/info.py b/PublicDataReader/config/info.py index 76a26b6..fe447af 100644 --- a/PublicDataReader/config/info.py +++ b/PublicDataReader/config/info.py @@ -1,4 +1,4 @@ -__version__ = "1.0.5" +__version__ = "1.0.6" __author__ = "정우일(Wooil Jeong)" __contact__ = "wooil@kakao.com" __github__ = "https://github.com/WooilJeong/PublicDataReader" diff --git a/PublicDataReader/data.py b/PublicDataReader/data.py index 9f5c5f6..66dd45e 100644 --- a/PublicDataReader/data.py +++ b/PublicDataReader/data.py @@ -16,5 +16,8 @@ # 한국자산관리공사 Open API 통합 from PublicDataReader.PublicDataPortal.kamco import Kamco +# 국세청 Open API +from PublicDataReader.PublicDataPortal.nts import Nts + # 코드 데이터 조회 from PublicDataReader.utils.code import code_bdong, get_vworld_data_api_info_by_dataframe, get_vworld_data_api_info_by_dict diff --git a/README.md b/README.md index d015c3a..f315819 100644 --- a/README.md +++ b/README.md @@ -16,14 +16,18 @@ ## PublicDataReader -**PublicDataReader**는 **Open API를 통해 공공 데이터를 조회하는 과정을 자동화하는 오픈소스 로우코드 파이썬 라이브러리**입니다. 즉시 분석에 활용할 수 있는 형태로 데이터를 조회할 수 있어 생산성 향상에 도움을 주는 도구입니다. 공공 데이터 제공처 마다 서로 다른 API 명세를 확인하는 작업, 명세에 따라 적합한 형식으로 데이터를 요청하는 코드를 작성하는 작업 그리고 반환된 데이터를 분석 가능한 형태로 가공하는 작업 등의 번거로운 작업들을 단 몇 줄의 코드로 자동화할 수 있습니다. 발급받은 **Open API 서비스 인증키**와 **PublicDataReader** 라이브러리만으로 원하는 데이터를 쉽게 조회할 수 있습니다. +PublicDataReader는 Open API를 사용하여 공공 데이터를 자동으로 조회할 수 있는 파이썬 라이브러리입니다. 이 도구를 사용하면 생산성을 높일 수 있게 됩니다. PublicDataReader는 Open API 서비스 인증키와 함께 사용하면 간편하게 공공 데이터를 조회할 수 있습니다. 일반적인 공공 데이터 조회 과정에서는 API 명세를 찾고, 적절한 형식으로 요청을 작성하고, 반환된 데이터를 정리하는 과정이 필요합니다. PublicDataReader는 이러한 과정을 자동화해주기 때문에 코드 작성이 간결해집니다.
## 설치 방법 -- Windows: CMD(명령 프롬프트)를 열어 아래 Shell 명령어를 입력 -- Mac: Terminal(터미널)을 열어 아래 Shell 명령어를 입력 +1. 운영체제(OS)에 따라 아래 중 하나를 선택합니다. + +- Windows: CMD(명령 프롬프트) 실행 +- Mac: Terminal(터미널) 실행 + +2. 아래 Shell 명령어를 입력 후 실행합니다. ```bash pip install PublicDataReader --upgrade @@ -40,6 +44,7 @@ pip install PublicDataReader --upgrade - 국토교통부 건축물대장정보 서비스 - 소상공인 상가업소 정보 조회 서비스 - 한국자산관리공사 공매물건 조회 서비스 + - 국세청 사업자등록정보 진위확인 및 상태조회 서비스 - [KOSIS 국가통계포털 데이터 조회 방법 예시](https://github.com/WooilJeong/PublicDataReader/blob/main/assets/docs/kosis.md) - KOSIS 통계 자료 조회 방법 - [서울 열린데이터광장 데이터 조회 방법 예시](https://github.com/WooilJeong/PublicDataReader/blob/main/assets/docs/seoul.md) diff --git a/assets/docs/portal.md b/assets/docs/portal.md index 0c4bdeb..c760162 100644 --- a/assets/docs/portal.md +++ b/assets/docs/portal.md @@ -9,7 +9,7 @@ PublicDataReader를 통해 공공데이터포털에서 제공하는 Open API 서 - [국토교통부 건축물대장정보 서비스](#국토교통부-건축물대장정보-서비스) - [소상공인 상가업소 정보 조회 서비스](#소상공인-상가업소-정보-조회-서비스) - [한국자산관리공사 공매물건 조회 서비스](#한국자산관리공사-공매물건-조회-서비스) - +- [국세청 사업자등록정보 진위확인 및 상태조회 서비스](#국세청-사업자등록정보-진위확인-및-상태조회-서비스) ## 국토교통부 실거래가 정보 조회 서비스 @@ -348,4 +348,66 @@ params = { df = API.get_data(service, function, **params) df.head() -``` \ No newline at end of file +``` + + +## 국세청 사업자등록정보 진위확인 및 상태조회 서비스 + +- [국세청 사업자등록정보 진위확인 및 상태조회 서비스 신청 페이지](https://www.data.go.kr/tcs/dss/selectApiDataDetailView.do?publicDataPk=15081808) + +- 사업자등록정보 진위확인 서비스 + +```python +import PublicDataReader as pdr +print(pdr.__version__) + +# 공공 데이터 포털 OpenAPI 서비스 인증키 입력하기 (디코딩키로 입력) +serviceKey = "공공 데이터 포털에서 발급받은 서비스 키(디코딩 키)" + +# 조회 대상 목록 +businesses = [{ + 'b_no': '0000000000', + 'start_dt': '20000101', + 'p_nm': '홍길동', + 'p_nm2': '', + 'b_nm': '', + 'corp_no': '', + 'b_sector': '', + 'b_type': ''}, + {'b_no': '1111111111', + 'start_dt': '20100101', + 'p_nm': '홍길동', + 'p_nm2': '', + 'b_nm': '', + 'corp_no': '', + 'b_sector': '', + 'b_type': ''}, + {'b_no': '2222222222', + 'start_dt': '20200101', + 'p_nm': '홍길동', + 'p_nm2': '', + 'b_nm': '', + 'corp_no': '', + 'b_sector': '', + 'b_type': '' +}] + +# 진위확인 +df = API.validate(businesses) +``` + +- 사업자등록정보 상태조회 서비스 + +```python +import PublicDataReader as pdr +print(pdr.__version__) + +# 공공 데이터 포털 OpenAPI 서비스 인증키 입력하기 (디코딩키로 입력) +serviceKey = "공공 데이터 포털에서 발급받은 서비스 키(디코딩 키)" + +# 조회 대상 목록 (사업자등록번호 리스트) +b_no = ['0000000000', '1111111111'] + +# 상태조회 +df = API.status(b_no) +``` diff --git a/test/develop.ipynb b/test/develop.ipynb new file mode 100644 index 0000000..e1cef0c --- /dev/null +++ b/test/develop.ipynb @@ -0,0 +1,290 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "ExecuteTime": { + "end_time": "2022-12-02T08:23:39.858809Z", + "start_time": "2022-12-02T08:23:39.839859Z" + } + }, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "from pathlib import Path\n", + "sys.path.append(str(Path(os.getcwd()).parent))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from config import API_KEY_INFO\n", + "serviceKey1 = API_KEY_INFO.get(\"portal\")\n", + "serviceKey2 = API_KEY_INFO.get(\"portal2\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import requests\n", + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class Nts:\n", + "\n", + " def __init__(self, serviceKey=None):\n", + " self.serviceKey = serviceKey\n", + " self.url_dict = {\n", + " \"진위확인\": \"https://api.odcloud.kr/api/nts-businessman/v1/validate\",\n", + " \"상태조회\": \"https://api.odcloud.kr/api/nts-businessman/v1/status\",\n", + " }\n", + "\n", + " def validate(self, businesses):\n", + " \"\"\"\n", + " 사업자등록정보 진위확인 API\n", + "\n", + " Parameters\n", + " ----------\n", + " businesses : list, DataFrame\n", + " 사업자등록정보 리스트 (1회 호출 시 최대 100개까지 조회 가능)\n", + " \n", + " Returns\n", + " -------\n", + " DataFrame\n", + " 진위확인 결과\n", + " \"\"\"\n", + " url = self.url_dict[\"진위확인\"]\n", + " params = {\n", + " \"serviceKey\": self.serviceKey,\n", + " }\n", + " if type(businesses) == pd.DataFrame:\n", + " businesses = businesses.to_dict(\"records\")\n", + " json_data = {\n", + " \"businesses\": businesses,\n", + " }\n", + " try:\n", + " response = requests.post(url, params=params, json=json_data)\n", + " df = pd.json_normalize(response.json()['data'])\n", + " except Exception as e:\n", + " print(\"Error\")\n", + " print(e)\n", + " return\n", + " return df\n", + " \n", + " def status(self, b_no):\n", + " \"\"\"\n", + " 사업자등록정보 상태조회 API\n", + "\n", + " Parameters\n", + " ----------\n", + " b_no : list\n", + " 사업자등록번호 (1회 호출 시 최대 100개까지 조회 가능)\n", + "\n", + " Returns\n", + " -------\n", + " DataFrame\n", + " 상태조회 결과\n", + " \"\"\"\n", + " url = self.url_dict[\"상태조회\"]\n", + " params = {\n", + " \"serviceKey\": self.serviceKey,\n", + " }\n", + " data = {\n", + " \"b_no\": b_no,\n", + " }\n", + " try:\n", + " response = requests.post(url, params=params, json=data)\n", + " df = pd.DataFrame(response.json()['data'])\n", + " except Exception as e:\n", + " print(\"Error\")\n", + " print(e)\n", + " return\n", + " return df" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- 진위확인" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# 예제 데이터\n", + "data_list = [\n", + " {\n", + " 'b_no': '',\n", + " 'start_dt': '',\n", + " 'p_nm': '',\n", + " 'p_nm2': '',\n", + " 'b_nm': '',\n", + " 'corp_no': '',\n", + " 'b_sector': '',\n", + " 'b_type': ''\n", + " },\n", + " {\n", + " 'b_no': '',\n", + " 'start_dt': '',\n", + " 'p_nm': '',\n", + " 'p_nm2': '',\n", + " 'b_nm': '',\n", + " 'corp_no': '',\n", + " 'b_sector': '',\n", + " 'b_type': ''\n", + " },\n", + "]\n", + "\n", + "data_frame = pd.DataFrame(data_list)\n", + "data_frame" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# NTS API 인스턴스 생성\n", + "API = Nts(serviceKey2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# 진위확인 API 호출\n", + "data = API.validate(data_frame)\n", + "data" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- 상태조회" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# 사업자등록번호 리스트 (1회 호출 시 최대 100개까지 가능)\n", + "b_no = [\n", + " \"\",\n", + "]\n", + "\n", + "# 진위확인 API 호출\n", + "data = API.status(b_no=b_no)\n", + "data" + ] + } + ], + "metadata": { + "hide_input": false, + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.12 (main, Apr 4 2022, 05:22:27) [MSC v.1916 64 bit (AMD64)]" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": { + "height": "calc(100% - 180px)", + "left": "10px", + "top": "150px", + "width": "234.707px" + }, + "toc_section_display": true, + "toc_window_display": true + }, + "varInspector": { + "cols": { + "lenName": 16, + "lenType": 16, + "lenVar": 40 + }, + "kernels_config": { + "python": { + "delete_cmd_postfix": "", + "delete_cmd_prefix": "del ", + "library": "var_list.py", + "varRefreshCmd": "print(var_dic_list())" + }, + "r": { + "delete_cmd_postfix": ") ", + "delete_cmd_prefix": "rm(", + "library": "var_list.r", + "varRefreshCmd": "cat(var_dic_list()) " + } + }, + "oldHeight": 237.13578, + "position": { + "height": "440.117px", + "left": "491.674px", + "right": "20px", + "top": "85.9445px", + "width": "613.965px" + }, + "types_to_exclude": [ + "module", + "function", + "builtin_function_or_method", + "instance", + "_Feature" + ], + "varInspector_section_display": "block", + "window_display": false + }, + "vscode": { + "interpreter": { + "hash": "bf36e43d91273cda28ef8173803dc98b9ff2c112c9a311d9da2b51870a73ee88" + } + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/test/test_kamco.ipynb b/test/test_kamco.ipynb index 021b89e..e950b6f 100644 --- a/test/test_kamco.ipynb +++ b/test/test_kamco.ipynb @@ -1287,7 +1287,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.12" + "version": "3.9.12 (main, Apr 4 2022, 05:22:27) [MSC v.1916 64 bit (AMD64)]" }, "toc": { "base_numbering": 1, diff --git a/test/test_nts.ipynb b/test/test_nts.ipynb new file mode 100644 index 0000000..540ba93 --- /dev/null +++ b/test/test_nts.ipynb @@ -0,0 +1,168 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "ExecuteTime": { + "end_time": "2022-12-02T08:23:39.858809Z", + "start_time": "2022-12-02T08:23:39.839859Z" + } + }, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "from pathlib import Path\n", + "sys.path.append(str(Path(os.getcwd()).parent))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import PublicDataReader as pdr\n", + "from config import API_KEY_INFO\n", + "print(pdr.__version__)\n", + "serviceKey = API_KEY_INFO.get(\"portal2\")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# NTS API Instance" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from PublicDataReader import Nts\n", + "API = Nts(serviceKey)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "\n", + "# 결측치는 공백으로 처리\n", + "businesses = pd.read_excel(\"./dataset.xlsx\", dtype=str, na_values=\"\").fillna(\"\")\n", + "businesses\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df = API.validate(businesses)\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "b_no = ['0000000000', '1111111111']\n", + "df = API.status(b_no)\n", + "df" + ] + } + ], + "metadata": { + "hide_input": false, + "kernelspec": { + "display_name": "Python 3.9.12 ('venv': venv)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.12 (main, Apr 4 2022, 05:22:27) [MSC v.1916 64 bit (AMD64)]" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": { + "height": "calc(100% - 180px)", + "left": "10px", + "top": "150px", + "width": "234.707px" + }, + "toc_section_display": true, + "toc_window_display": true + }, + "varInspector": { + "cols": { + "lenName": 16, + "lenType": 16, + "lenVar": 40 + }, + "kernels_config": { + "python": { + "delete_cmd_postfix": "", + "delete_cmd_prefix": "del ", + "library": "var_list.py", + "varRefreshCmd": "print(var_dic_list())" + }, + "r": { + "delete_cmd_postfix": ") ", + "delete_cmd_prefix": "rm(", + "library": "var_list.r", + "varRefreshCmd": "cat(var_dic_list()) " + } + }, + "oldHeight": 237.13578, + "position": { + "height": "440.117px", + "left": "491.674px", + "right": "20px", + "top": "85.9445px", + "width": "613.965px" + }, + "types_to_exclude": [ + "module", + "function", + "builtin_function_or_method", + "instance", + "_Feature" + ], + "varInspector_section_display": "block", + "window_display": false + }, + "vscode": { + "interpreter": { + "hash": "fcea6e6e55b259976681c8a35a3648f8ff7299129df47a05aebb6686c5e7010e" + } + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/test/test_vworld.ipynb b/test/test_vworld.ipynb index 281dca2..f1bd543 100644 --- a/test/test_vworld.ipynb +++ b/test/test_vworld.ipynb @@ -9,7 +9,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -21,22 +21,14 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2021-11-15T16:15:05.203055Z", "start_time": "2021-11-15T16:15:05.189494Z" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1.0.3\n" - ] - } - ], + "outputs": [], "source": [ "import PublicDataReader as pdr\n", "from config import API_KEY_INFO\n", @@ -46,7 +38,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -55,67 +47,16 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
서비스명서비스ID
21도로명주소 도로LT_L_SPRD
22도로명주소 건물LT_C_SPBD
\n", - "
" - ], - "text/plain": [ - " 서비스명 서비스ID\n", - "21 도로명주소 도로 LT_L_SPRD\n", - "22 도로명주소 건물 LT_C_SPBD" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "code.loc[code['서비스명'].str.contains(\"주소\")]" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -125,20 +66,9 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "- 결과 타입: \n", - "- 키 종류: dict_keys(['type', 'features'])\n", - "\n" - ] - } - ], + "outputs": [], "source": [ "# 파라미터\n", "params = {\n", @@ -157,20 +87,9 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "- 결과 타입: \n", - "- 키 종류: dict_keys(['type', 'features'])\n", - "\n" - ] - } - ], + "outputs": [], "source": [ "# 파라미터\n", "params = {\n", @@ -189,7 +108,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": {}, "outputs": [], "source": [