02.Python ํ™œ์šฉ - open API

ID์งฑ์žฌยท2021๋…„ 2์›” 9์ผ
0

Crawling

๋ชฉ๋ก ๋ณด๊ธฐ
3/5
post-thumbnail

๐ŸŒˆ open API

๐Ÿ”ฅ open API ์ดํ•ด

๐Ÿ”ฅ ๋„ค์ด๋ฒ„ developers ํ™œ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ JSON ํ˜•ํƒœ๋กœ ํด๋กœ๋งํ•˜๊ธฐ

๐Ÿ”ฅ ์ •๋ถ€์ œ๊ณต Open API ์‚ฌ์šฉํ•˜๊ธฐ



1. open API ์ดํ•ด

1) open API(Rest API)๋ž€?

  • API: Aplication Programming Interface์˜ ์•ฝ์ž๋กœ, ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์ œ๊ณต๋˜๋Š” ๋ชจ๋“ˆ(ํ•จ์ˆ˜ ๋“ฑ)์„ ์˜๋ฏธ
  • Open API : ๋ˆ„๊ตฌ๋“  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ณต๊ฐœ๋œ API(์ฃผ๋กœ REST API ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•จ)
  • REST API : Representational State Transfer API์˜ ์•ฝ์ž๋กœ, HTTP ํ”„๋กœํ† ์ปฌ์„ ํ†ตํ•ด ์„œ๋ฒ„ ์ œ๊ณต ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜
  • REST API๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ XML, JSON์˜ ํ˜•ํƒœ๋กœ ์‘๋‹ต์„ ์ „๋‹ฌ

2) JSON ์ด๋ž€?

  • JavaScript Object Notation ์ค„์ž„๋ง
  • ์›น ํ™˜๊ฒฝ์—์„œ ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด์— ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›์„ ๋•Œ ์ฃผ๋กœ ์‚ฌ์šฉ
  • JSON ํฌ๋งท ์˜ˆ : dict๊ณผ ๊ฐ™์€ ํ˜•ํƒœ
    • {"id":"01", "language":"python", "edition":"third", "author":"jaewon"}
  • key์—๋Š” ๋ฌธ์ž์—ด์ด ๋“ค์–ด๊ฐ€์ง€๋งŒ, value์—๋Š” ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ๋‹ด์„ ์ˆ˜ ์žˆ์Œ
  • JSON๋„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๊ธฐ ๋•Œ๋ฌธ์— ์„ค์น˜ ํ•„์š” : pip3 install json



2. ๋„ค์ด๋ฒ„ developers ํ™œ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ JSON ํ˜•ํƒœ๋กœ ํด๋กœ๋งํ•˜๊ธฐ

1) ๋„ค์ด๋ฒ„ ๋‰ด์Šค ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ํฌ์ŠคํŠธ๋งจ์œผ๋กœ JSON ์ „๋‹ฌ๋ฐ›์•„ ๋‹ค๋ฃจ๊ธฐ

  • โญ๏ธ naver developers ์ฐธ๊ณ  : https://developers.naver.com/main/
  • ํฌ์ŠคํŠธ๋งจ ์„ค์น˜ ํ›„ ํŒŒ์ผ ์ƒ์„ฑํ•˜์—ฌ params์— ๊ฐ€์ ธ์˜ฌ ์ฃผ์†Œ GET์—์„œ ๋“ฑ๋ก
  • ์ดํ›„ Headers์— developers.naver ๊ฐ€์ž… ํ•  ๋•Œ ๋ฐ›์€ Id์™€ Secret ๋“ฑ๋ก
  • id์™€ Secret ๋“ฑ๋ก ํ•  ๋•Œ, KEY๊ฐ’์œผ๋กœ id์—๋Š” X-Naver-Client-Id์„ ์ ๊ณ , Secret์—๋Š” X-Naver-Client-Secret๋ฅผ ์ ์–ด VALUE์— ๊ฐ’์„ ์ ์–ด์ฃผ๋ฉด ๋จ
  • API๋ฅผ ๋ฐ›์•„์˜ค๋Š” ์‹ธ์ดํŠธ๋ณ„๋กœ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๋‹น ์›น์—์„œ ์ œ๊ณตํ•˜๋Š” API ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ์–ด๋–ป๊ฒŒ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์ƒํ™ฉ์— ๋”ฐ๋ผ ์ ์šฉํ•ด์•ผ ํ•จ
  • SEND๋ฅผ ๋ˆ„๋ฅด๋ฉด ์•„๋ž˜ BODY์ฐฝ์— JSONํ˜•ํƒœ๋กœ ๋ฐ›์•„ ๋ณด์—ฌ์คŒ
  • json.loads() : JSON ํ˜•์‹์˜ ์ž๋ฃŒ๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ ์‚ฌ์šฉ
  • JSON ๋‚ด ๋ฐ์ดํ„ฐ๋ฅผ ์ธ๋ฑ์‹ฑํ•  ๋•Œ์—๋Š” dict๋ฅผ ๋‹ค๋ฃจ๋ฅผ ๋ฐฉ์‹์œผ๋กœ key๊ฐ’์„ ํ†ตํ•ด ๋ถˆ๋Ÿฌ์˜ด

    โœ๐Ÿป python

    # postman์„ ์ด์šฉํ•˜์—ฌ ๋„ค์ด๋ฒ„ ๋‰ด์Šค์—์„œ android ํ‚ค์›Œ๋“œ๋กœ ๊ฒ€์ƒ‰ํ•œ ๊ฒฐ๊ณผ
    import json
    data = """
    {
       "lastBuildDate": "Fri, 05 Feb 2021 14:06:50 +0900",
       "total": 23784,
       "start": 1,
       "display": 10,
       "items": [
           {
               "title": "'๊ทธ๋ ค๋ผ, ํ„ฐ์น˜: ๋‘ ๊ฐœ์˜ ์™•๊ตญ' ๋ฌด๋ฃŒ ์—…๋ฐ์ดํŠธ ์ œ๊ณต",
               "originallink": "https://www.gamechosun.co.kr/webzine/article/view.php?no=172200",
               "link": "https://www.gamechosun.co.kr/webzine/article/view.php?no=172200",
               "description": "๋ฐ <b>Android</b>์—์„œ ์ œ๊ณตํ•œ๋‹ค. ํฌ๋ฆฌ์—์ดํ‹ฐ๋ธŒ ํŒฉ DLC๋Š” ๋‹Œํ…๋„ ์Šค์œ„์น˜ ํ”Œ๋ ˆ์ด์–ด๋ฅผ ์œ„ํ•œ 10๊ฐ€์ง€ ์ƒˆ๋กœ์šด ์ฑŒ๋ฆฐ์ง€... ๋ฐ <b>Android</b>์—๋งŒ ํ•ด๋‹น) โ€˜๊ทธ๋ ค๋ผ, ํ„ฐ์น˜: ๋‘ ๊ฐœ์˜ ์™•๊ตญโ€™์€ โ€˜๊ทธ๋ ค๋ผ, ํ„ฐ์น˜: ๋” ๋„ฅ์ŠคํŠธ ์ฑ•ํ„ฐโ€™๊ฐ€ ๋๋‚˜๊ณ  ๋ช‡ ๋…„... ",
               "pubDate": "Fri, 05 Feb 2021 11:33:00 +0900"
           },
           {
               "title": "'๊ทธ๋ ค๋ผ, ํ„ฐ์น˜: ๋‘ ๊ฐœ์˜ ์™•๊ตญ' ๋ฌด๋ฃŒ DLC ํ†ตํ•ด ๋‹Œํ…๋„ ์Šค์œ„์น˜ ์œ ์ € ์œ„ํ•œ ํ„ฐ์น˜ ...",
               "originallink": "http://gamefocus.co.kr/detail.php?number=114250",
               "link": "http://gamefocus.co.kr/detail.php?number=114250",
               "description": "๋ฐ <b>Android</b>์—์„œ ์ œ๊ณตํ•œ๋‹ค. ํฌ๋ฆฌ์—์ดํ‹ฐ๋ธŒ ํŒฉ DLC๋Š” ๋‹Œํ…๋„ ์Šค์œ„์น˜ ํ”Œ๋ ˆ์ด์–ด๋ฅผ ์œ„ํ•œ 10๊ฐ€์ง€ ์ƒˆ๋กœ์šด ์ฑŒ๋ฆฐ์ง€... ๋ฐ <b>Android</b>์—๋งŒ ํ•ด๋‹น) '๊ทธ๋ ค๋ผ, ํ„ฐ์น˜: ๋‘ ๊ฐœ์˜ ์™•๊ตญ'์€ '๊ทธ๋ ค๋ผ, ํ„ฐ์น˜: ๋” ๋„ฅ์ŠคํŠธ ์ฑ•ํ„ฐ'๊ฐ€ ๋๋‚˜๊ณ  ๋ช‡ ๋…„ ํ›„๋ฅผ... ",
               "pubDate": "Fri, 05 Feb 2021 10:45:00 +0900"
           },
           {
               "title": "โ€˜๊ตฌ๊ธ€๋ฒˆ์—ญโ€™์œผ๋กœ ๋‚˜์˜ ์นผ๋Ÿผ์ด ์™„์ „ ์˜๋ฌธํ™” โ€œ์ธ๊ณต์ง€๋Šฅ์„ ๋ณด๊ณ  ๋†€๋ผโ€",
               "originallink": "http://www.breaknews.com/784374",
               "link": "http://www.breaknews.com/784374",
               "description": "It is said to provide website interfaces for <b>Android</b> and iOS, mobile apps, and APIs that help developers develop browser extensions and application software. Other languages โ€‹โ€‹are translated into paragraphs of text... ",
               "pubDate": "Thu, 04 Feb 2021 10:37:00 +0900"
           },
           {
               "title": "์Šค์นด์ด์Šค์บ๋„ˆ, ์งํ•ญ์ˆ˜์š” ์˜ˆ์ธก B2B ์ „์šฉ โ€˜Unserved Routesโ€™ ๋ชจ๋“ˆ ์ถœ์‹œ ํ–ˆ๋‹ค.",
               "originallink": "http://www.tourtimes.net/353154",
               "link": "http://www.tourtimes.net/353154",
               "description": "์Šค์นด์ด์Šค์บ๋„ˆ๋Š” ์ปดํ“จํ„ฐ, ๋ชจ๋ฐ”์ผ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์•ฑ(<b>Android</b>/iOS)์€ 1์–ต ๋งŒ๋ฒˆ์˜ ๋‹ค์šด๋กœ๋“œ๋ฅผ ๊ธฐ๋กํ–ˆ๋‹ค. ์Šค์นด์ด์Šค์บ๋„ˆ์˜ ๋ชฉํ‘œ๋Š” 1200์—ฌ ์—ฌํ–‰ ํŒŒํŠธ๋„ˆ๋“ค๊ณผ ํ˜‘๋ ฅํ•˜์—ฌ, ํ˜„๋Œ€์ ์ด๊ณ  ์ง€์† ๊ฐ€๋Šฅํ•œ ์—ฌํ–‰์œผ๋กœ ์„ธ๊ณ„์ ์ธ ๋ณ€ํ™”๋ฅผ... ",
               "pubDate": "Thu, 04 Feb 2021 09:35:00 +0900"
           },
           {
               "title": "๋“œ๋ฆผ์—์ด์Šค, ํญ์Šค์ฝ˜ MIH์˜ ์ฃผ์š” ํŒŒํŠธ๋„ˆ์‚ฌ๋กœ ์„ ์ • ",
               "originallink": "http://www.businesskorea.co.kr/news/articleView.html?idxno=59828",
               "link": "http://www.businesskorea.co.kr/news/articleView.html?idxno=59828",
               "description": "์„ค๋ฆฝ ์ดˆ๊ธฐ๋ถ€ํ„ฐ ์‹ฑ๊ฐ€ํฌ๋ฅด์—์„œ ์—ด๋ฆฐ '2015 ์ธํ”ผ๋‹ˆ์–ธ ๋ฒค์ฒ˜ํฌ๋Ÿผ'์— ์ฐธ๊ฐ€ ํ•œ๊ตญ ๊ธฐ์—…์œผ๋กœ๋Š” ์œ ์ผํ•˜๊ฒŒ 2์œ„๋ฅผ ์ˆ˜์ƒํ•  ์ •๋„๋กœ ์ผ์ฐ์ด ๊ธฐ์ˆ ์„ ์ธ์ •์„ ๋ฐ›์€ ๊ธฐ์—…์ด๋ฉฐ, 2019๋…„์—๋Š” AGL Summit 2019 (ALS 2019)์—์„œ <b>Android</b> Container ๊ธฐ์ˆ ์„... ",
               "pubDate": "Thu, 04 Feb 2021 09:32:00 +0900"
           },
           {
               "title": "What Can You Actually Buy With Bitcoin?",
               "originallink": "https://www.nytimes.com/2021/02/03/style/what-can-you-actually-buy-with-bitcoin.html?partner=naver",
               "link": "https://www.nytimes.com/2021/02/03/style/what-can-you-actually-buy-with-bitcoin.html?partner=naver",
               "description": "Additionally, apps in the Apple and <b>Android</b> stores make it possible for crypto-connoisseurs to pay for airline tickets by converting Bitcoin to fiat money in real time. On Monday, a news release... ",
               "pubDate": "Thu, 04 Feb 2021 01:23:00 +0900"
           },
           {
               "title": "As Jeff Bezos Takes Off, Meet His Earthbound Successor",
               "originallink": "https://www.nytimes.com/2021/02/03/opinion/amazon-jeff-bezos-andy-jassy.html?partner=naver",
               "link": "https://www.nytimes.com/2021/02/03/opinion/amazon-jeff-bezos-andy-jassy.html?partner=naver",
               "description": "To hear more audio stories from publishers like The New York Times, download Audm for iPhone or <b>Android</b>. Who, you might ask at this moment, is Andy Jassy? Heโ€™s a talented entrepreneur, for sure... ",
               "pubDate": "Wed, 03 Feb 2021 19:02:00 +0900"
           },
           {
               "title": "Can We Please Stop Talking About Stocks, Please?",
               "originallink": "https://www.nytimes.com/2021/02/03/opinion/gamestop-stock-market-economy.html?partner=naver",
               "link": "https://www.nytimes.com/2021/02/03/opinion/gamestop-stock-market-economy.html?partner=naver",
               "description": "To hear more audio stories from publishers like The New York Times, download Audm for iPhone or <b>Android</b>. This column is not about GameStop, though not for lack of trying. Last week the aging... ",
               "pubDate": "Wed, 03 Feb 2021 19:02:00 +0900"
           },
           {
               "title": "The Many Lives of Steven Yeun",
               "originallink": "https://www.nytimes.com/2021/02/03/magazine/steven-yeun.html?partner=naver",
               "link": "https://www.nytimes.com/2021/02/03/magazine/steven-yeun.html?partner=naver",
               "description": "To hear more audio stories from publishers like The New York Times, download Audm for iPhone or <b>Android</b>. When I was growing up in the โ€™90s, the only Asian-American writer I knew was Amy Tan.... ",
               "pubDate": "Wed, 03 Feb 2021 19:02:00 +0900"
           },
           {
               "title": "Risking Everything to Come to America on the Open Ocean",
               "originallink": "https://www.nytimes.com/2021/02/03/magazine/customs-border-protection-migrants-pacific-ocean.html?partner=naver",
               "link": "https://www.nytimes.com/2021/02/03/magazine/customs-border-protection-migrants-pacific-ocean.html?partner=naver",
               "description": "To hear more audio stories from publishers like The New York Times, download Audm for iPhone or <b>Android</b>. The fiberglass skiff Lazora idled on the darkened Pacific Ocean a few miles south of... ",
               "pubDate": "Wed, 03 Feb 2021 19:02:00 +0900"
           }
       ]
    }
    """
    json_data = json.loads(data) # json์—์„œ ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๋Š” ํ•จ์ˆ˜ : loads()
    print(json_data)
    print(json_data['lastBuildDate'])
    print(json_data['items'])
    print(json_data['items'][-1]['title'])
    print(json_data['items'][-1]['pubDate'])

2) ๋„ค์ด๋ฒ„ ์‡ผํ•‘ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ vscode์—์„œ JSON ์ „๋‹ฌ๋ฐ›์•„ ๋‹ค๋ฃจ๊ธฐ

  • ํฌ์ŠคํŠธ๋งจ์—์„œ JSON์„ ์ „๋‹ฌ๋ฐ›์€ ๋ฐฉ๋ฒ•์„ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ†ตํ•ด ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์ž.
  • pprint ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ : JSON์œผ๋กœ ์ „๋‹ฌ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ์กฐ์ ์œผ๋กœ ์ •๋ ฌ๋˜์„œ ์ถœ๋ ฅํ•ด์คŒ
  • ๊ธฐ์กด print()๋กœ ์‚ฌ์šฉํ•˜๋˜ ๋ถ€๋ถ„์„ pprint.pprint() ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ์ •๋ ฌ๋˜์„œ ์ถœ๋ ฅํ•จ
  • enumerate() ํ•จ์ˆ˜ : for๋ฌธ์—์„œ index๋ฒˆํ˜ธ๋ฅผ ํ•จ๊ป˜ ์ถœ๋ ฅํ•ด์ฃผ๋Š” ํ•จ์ˆ˜

โœ๐Ÿป python

import requests
import pprint # json์„ ๋ณด๊ธฐ ํŽธํ•˜๊ฒŒ ๊ตฌ์กฐ์ ์œผ๋กœ ์ •๋ ฌํ•ด์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
client_id = '๋‚ด id์ž…๋ ฅ' 
client_secret = '๋‚ด secret ์ž…๋ ฅ' 
naver_open_api = 'https://openapi.naver.com/v1/search/shop.json?query=android'
header_params = {"X-Naver-Client-Id":client_id, "X-Naver-Client-Secret":client_secret} # id์™€ secret์„ json ํ˜•์‹์œผ๋กœ ๋งŒ๋“ค์–ด ๋ณ€์ˆ˜์— ์ €์žฅ 
res = requests.get(naver_open_api, headers=header_params) # JSON ํ˜•์‹์œผ๋กœ ๋ฐ›์•„์˜ฌ ์ฃผ์†Œ์™€ ๋‚ด ํ—ค๋” ์ •๋ณด ํ†ตํ•ด ์š”์ฒญ
# requests ํ•œ ๊ฒฐ๊ณผ์˜ ์‘๋‹ต์ด ์ •์ƒ์ผ ๋•Œ์™€, ์ •์ƒ์ด์•„๋‹ ๋•Œ
if res.status_code == 200:
    data = res.json() # ์ •์ƒ์ ์ด๋ฉด ์ถœ๋ ฅ
    pprint.pprint(data)  # print()๋กœ ๋ถˆ๋Ÿฌ์˜ค๋ฉด data๊ฐ€ ๋ณด๊ธฐ ์–ด๋ ค์›€. pprint๋กœ ๋ถˆ๋Ÿฌ์˜ค๋ฉด ๊ตฌ์กฐ์ ์œผ๋กœ ๋ณด์—ฌ์คŒ
    for index, item in enumerate(data['items']): # enumerate() ํ•จ์ˆ˜๋ฅผ ์จ์„œ ์ธ๋ฑ์Šค ๋ฒˆํ˜ธ๋„ ํ•จ๊ป˜ ๋ณผ ์ˆ˜ ์žˆ์Œ
        print(index+1, item['title'], item['link'])
else:
    print("Error Code: ", res.status_code) # ๋ฌธ์ œ ์žˆ์œผ๋ฉด ์—๋Ÿฌ ์ฝ”๋“œ

3) ์ƒํ’ˆ ๊ฒ€์ƒ‰ ์ƒ์œ„ ๋ฆฌ์ŠคํŠธ ์—‘์…€ ํŒŒ์ผ๋กœ ์ €์žฅํ•˜๊ธฐ

  • 1๋‹จ๊ณ„ : evelopers.naver.com๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ๋„ค์ด๋ฒ„ ์‡ผํ•‘ '์• ํ”Œ์›Œ์น˜' ๊ฒ€์ƒ‰์–ด ํฌ๋กค๋งํ•˜๊ธฐ
  • 2๋‹จ๊ณ„ : ํฌ๋กค๋ง ์กฐ๊ฑด์€ ์œ ์‚ฌ๋„ ๊ธฐ์ค€ ์ƒ์œ„ 1000๊ฐœ
  • 3๋‹จ๊ณ„ : ํฌ๋กค๋งํ•œ ๊ฒฐ๊ณผ๋ฅผ ์—‘์…€ ํŒŒ์ผ๋กœ ์ €์žฅ
  • ๋„ค์ด๋ฒ„ api ๊ฒ€์ƒ‰ ๊ฐœ๋ฐœ ๊ฐ€์ด๋“œ ์š”์ฒญ ๋ณ€์ˆ˜

โœ๐Ÿป python

# ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ import
import requests
import openpyxl
# ํ•„์š” ๋ณ€์ˆ˜ ์„ ์–ธ
client_id = '๋‚ด id๊ฐ’' 
client_secret = '๋‚ด secret๊ฐ’' 
start, num = 1, 0
excel_file = openpyxl.Workbook()
excel_sheet = excel_file.active
excel_sheet.column_dimensions["B"].width = 100
excel_sheet.column_dimensions["C"].width = 100
excel_sheet.append(['๋žญํฌ', '์ œ๋ชฉ', '๋งํฌ']) # ๋งจ์œ„์— ๋ผ๋ฒจ ์„ธํŒ…
# for๋ฌธ์„ ํ†ตํ•ด 1000๊ฐœ requests ์š”์ฒญํ•˜๊ธฐ 
# display๋Š” 100๊ฐœ์”ฉ ๊ฐ€์ ธ์˜ค๊ธฐ ๋•Œ๋ฌธ์— start ์‹œ์ž‘๊ฐ’์„ ๋ฐ”๊ฟ”์ฃผ๋ฉด 1000๊ฐœ๋ฅผ ํฌ๋กค๋ง ๊ฐ€๋Šฅ
for index in range(10):
    start_number = start + (index * 100)
    naver_open_api = 'https://openapi.naver.com/v1/search/shop.json?query=์• ํ”Œ์›Œ์น˜&display=100&start='+str(start_number) # ๋„ค์ด๋ฒ„ ์‡ผํ•‘์—์„œ ์• ํ”Œ์›Œ์น˜ ๊ฒ€์ƒ‰ํ•œ ์ฃผ์†Œ
    header_params = {"X-Naver-Client-Id":client_id, "X-Naver-Client-Secret":client_secret} 
    res = requests.get(naver_open_api, headers=header_params) 
    # requests ํ•œ ๊ฒฐ๊ณผ์˜ ์‘๋‹ต์ด ์ •์ƒ์ผ ๋•Œ์™€, ์ •์ƒ์ด์•„๋‹ ๋•Œ
    if res.status_code == 200:
        data = res.json() 
        for item in data['items']: # enumerate() ํ•จ์ˆ˜๋ฅผ ์จ์„œ ์ธ๋ฑ์Šค ๋ฒˆํ˜ธ๋„ ํ•จ๊ป˜ ๋ณผ ์ˆ˜ ์žˆ์Œ
            num += 1
            excel_sheet.append([num, item['title'], item['link']]) # ์ค‘์ฒฉ list๋กœ ์ฒ˜๋ฆฌํ•ด์ค˜์•ผ ํ•จ
    else:
        print("Error Code: ", res.status_code) # ๋ฌธ์ œ ์žˆ์œผ๋ฉด ์—๋Ÿฌ ์ฝ”๋“œ
# ํด๋กค๋ง ๊ฒฐ๊ณผ ์ €์žฅ ๋ฐ ๋‹ซ๊ธฐ
excel_file.save('shopping_with_applewatch.xlsx')
excel_file.close()


3. ์ •๋ถ€์ œ๊ณต Open API ์‚ฌ์šฉํ•˜๊ธฐ


1) ํ™˜๊ฒฝ๊ณต๋‹จ ๋Œ€๊ธฐ์˜ค์—ผ ์ •๋ณด Postman์—์„œ XML ํฌ๋งท ๊ฐ€์ ธ์˜ค๊ธฐ

  • ๋Œ€๊ธฐ์˜ค์—ผ ์ •๋ณด์กฐํšŒ ์„œ๋น„์Šค : https://www.data.go.kr/data/15000581/openapi.do
  • ํฌ๋กค๋ง ํƒ€์ผ“ : ์‹œ๊ตฐ๊ตฌ๋ณ„ ์‹ค์‹œ๊ฐ„ ํ‰๊ท ์ •๋ณด ์กฐํšŒ
  • ์ผ๋ฐ˜์ธ์ฆํ‚ค๋Š” ์„œ๋น„์Šค ์‹ ์ฒญ์„ํ•˜๋ฉด ๋ฐœ๊ธ‰ ๋ฐ›์„ ์ˆ˜ ์žˆ์Œ
  • url์— ?๋ฅผ ๋ถ™์ธ ๋’ค "์š”์ฒญ๋ณ€์ˆ˜=๊ฐ’"์„ ์ˆœ์ฐจ์ ์œผ๋กœ ์จ์ฃผ๊ณ  ์š”์ฒญ ๋ณ€์ˆ˜ ์‚ฌ์ด์—๋Š” &๋ฅผ ๋„ฃ์–ด ์ด์–ด์คŒ
  • ์„œ๋น„์Šค url์— ์š”์ฒญ๋ณ€์ˆ˜์˜ ํ•ญ๋ชฉ๊ณผ ๊ฐ’์„ ์ž‘์„ฑ ํ›„ postman์œผ๋กœ ๊ฐ€์„œ ์ž˜ ์ž‘๋™ํ•˜๋Š”์ง€๋งŒ ํ™•์ธ
  • ์•„๋ž˜ ์ฒ˜๋Ÿผ ํฌ์ŠคํŠธ๋งจ์— ํ™•์ธ๋˜๋ฉด get์„ ์ž˜ํ•ด์˜จ ๊ฒƒ
  • XML์€ Extensible Markup Language์˜ ์•ฝ์ž๋กœ, ๋ฐ์ดํ„ฐ๋ฅผ ํƒœ๊ทธ๋กœ ๊ฐ์‚ฌ์„œ ๋งˆํฌ์—…ํ•˜๋Š” ๋ฒ”์šฉ์ ์ธ ํฌ๋งท

Postman

<?xml version="1.0" encoding="UTF-8"?>
<response>
   <header>
       <resultCode>00</resultCode>
       <resultMsg>NORMAL SERVICE.</resultMsg>
   </header>
   <body>
       <items>
           <item>
               <dataTime>2021-02-05 19:00</dataTime>
               <cityName>๊ฐ•๋‚จ๊ตฌ</cityName>
               <so2Value>0.003</so2Value>
               <coValue>0.5</coValue>
               <o3Value>0.022</o3Value>
               <no2Value>0.029</no2Value>
               <pm10Value>23</pm10Value>
               <pm25Value>19</pm25Value>
           </item>
           <item>
               <dataTime>2021-02-05 19:00</dataTime>
               <cityName>๊ฐ•๋™๊ตฌ</cityName>
               <so2Value>0.003</so2Value>
               <coValue>0.4</coValue>
               <o3Value>0.023</o3Value>
               <no2Value>0.028</no2Value>
               <pm10Value>30</pm10Value>
               <pm25Value>21</pm25Value>
           </item>
           <item>
               <dataTime>2021-02-05 19:00</dataTime>
               <cityName>๊ฐ•๋ถ๊ตฌ</cityName>
               <so2Value>0.003</so2Value>
               <coValue>0.5</coValue>
               <o3Value>0.023</o3Value>
               <no2Value>0.027</no2Value>
               <pm10Value>27</pm10Value>
               <pm25Value>12</pm25Value>
           </item>
           <item>
               <dataTime>2021-02-05 19:00</dataTime>
               <cityName>๊ฐ•์„œ๊ตฌ</cityName>
               <so2Value>0.003</so2Value>
               <coValue>0.4</coValue>
               <o3Value>0.021</o3Value>
               <no2Value>0.035</no2Value>
               <pm10Value>25</pm10Value>
               <pm25Value>16</pm25Value>
           </item>
           <item>
               <dataTime>2021-02-05 19:00</dataTime>
               <cityName>๊ด€์•…๊ตฌ</cityName>
               <so2Value>0.003</so2Value>
               <coValue>0.5</coValue>
               <o3Value>0.018</o3Value>
               <no2Value>0.042</no2Value>
               <pm10Value>26</pm10Value>
               <pm25Value>13</pm25Value>
           </item>
           <item>
               <dataTime>2021-02-05 19:00</dataTime>
               <cityName>๊ด‘์ง„๊ตฌ</cityName>
               <so2Value>0.003</so2Value>
               <coValue>0.5</coValue>
               <o3Value>0.013</o3Value>
               <no2Value>0.030</no2Value>
               <pm10Value>25</pm10Value>
               <pm25Value>16</pm25Value>
           </item>
           <item>
               <dataTime>2021-02-05 19:00</dataTime>
               <cityName>๊ตฌ๋กœ๊ตฌ</cityName>
               <so2Value>-</so2Value>
               <coValue>-</coValue>
               <o3Value>-</o3Value>
               <no2Value>-</no2Value>
               <pm10Value>30</pm10Value>
               <pm25Value>12</pm25Value>
           </item>
           <item>
               <dataTime>2021-02-05 19:00</dataTime>
               <cityName>๊ธˆ์ฒœ๊ตฌ</cityName>
               <so2Value>0.003</so2Value>
               <coValue>0.5</coValue>
               <o3Value>0.015</o3Value>
               <no2Value>0.044</no2Value>
               <pm10Value>38</pm10Value>
               <pm25Value>24</pm25Value>
           </item>
           <item>
               <dataTime>2021-02-05 19:00</dataTime>
               <cityName>๋…ธ์›๊ตฌ</cityName>
               <so2Value>0.004</so2Value>
               <coValue>0.5</coValue>
               <o3Value>0.026</o3Value>
               <no2Value>0.032</no2Value>
               <pm10Value>31</pm10Value>
               <pm25Value>16</pm25Value>
           </item>
           <item>
               <dataTime>2021-02-05 19:00</dataTime>
               <cityName>๋„๋ด‰๊ตฌ</cityName>
               <so2Value>0.003</so2Value>
               <coValue>0.3</coValue>
               <o3Value>0.029</o3Value>
               <no2Value>0.022</no2Value>
               <pm10Value>20</pm10Value>
               <pm25Value>9</pm25Value>
           </item>
       </items>
       <numOfRows>10</numOfRows>
       <pageNo>1</pageNo>
       <totalCount>600</totalCount>
   </body>
</response>

2) ํ™˜๊ฒฝ๊ณต๋‹จ ๋Œ€๊ธฐ์˜ค์—ผ ์ •๋ณด vsCode์—์„œ JSON ํฌ๋งท ๊ฐ€์ ธ์˜ค๊ธฐ

  • Postman์—์„œ ์ž˜ ๊ฐ€์ ธ์˜ค๋Š”์ง€ ํ™•์ธํ•˜์˜€์œผ๋ฉด, vsCode์—์„œ requests ์ฃผ์†Œ ๋ณ€์ˆ˜๋กœ ๋Œ€์ž…
  • ์•„๋ž˜ ์ถœ๋ ฅ ๊ฒฐ๊ณผ๋Š” Postman์—์„œ ๊ฐ€์ ธ์˜จ XML๊ณผ ์ผ์น˜ํ•จ
  • API url์ด ๊ธธ๊ธฐ ๋•Œ๋ฌธ์— Service_Key์™€ ์š”์ฒญ๋ณ€์ˆ˜๋ฅผ ๋ณ€์ˆ˜์— ๋‹ด์€ ํ›„ ์ฃผ์†Œ์— ์—ฐ๊ฒฐ์‹œํ‚ด
    โœ๐Ÿป python
    import requests
    Service_Key = 'API ์‹ ์ฒญ ํ›„ ๋ฐ›์€ Key'
    params = '&numOfRows=10&pageNo=1&sidoName=์„œ์šธ&searchCondition=DAILY'
    open_api = 'http://openapi.airkorea.or.kr/openapi/services/rest/ArpltnInforInqireSvc/getCtprvnMesureSidoLIst?ServiceKey=' + Service_Key + params
    res = requests.get(open_api)
    print(res.text) #Postman์—์„œ ๊ฐ€์ ธ์˜จ XML๊ณผ ์ผ์น˜ํ•จ 

3) XMLํ˜•์‹์œผ๋กœ ๊ฐ€์ ธ์˜จ ๊ณต๊ณต API ํ™œ์šฉํ•˜๊ธฐ

  • ์ผ๋ฐ˜์ ์œผ๋กœ JOSN ์ด๋‚˜ XML ํ˜•์‹์ด ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์Œ
  • XML์€ CSS์†์„ฑ์ด ์•„๋‹Œ ํƒœ๊ทธ์ด๋ฏ€๋กœ find๋‚˜ find_all์„ ์ด์šฉํ•ด ํƒ€๊ฒŒํŒ… ํ•จ

โœ๐Ÿป python

import requests
from bs4 import BeautifulSoup
Service_Key = 'HbJoqYXuPaywwa%2BAWgpMFjmgwbLwqM63jQtmD%2FgLOhWBeMo%2BFas33cpofjKIplNiuh3l4JQdxdDGDzVyBX6hdA%3D%3D'
params = '&numOfRows=10&pageNo=1&sidoName=์„œ์šธ&searchCondition=DAILY'
open_api = 'http://openapi.airkorea.or.kr/openapi/services/rest/ArpltnInforInqireSvc/getCtprvnMesureSidoLIst?ServiceKey=' + Service_Key + params
res = requests.get(open_api)
soup = BeautifulSoup(res.content, 'html.parser')
# ์ง€์—ญ, pm์ง€์ˆ˜ ์ถ”์ถœ
data = soup.find_all('item')
for item in data:
   cityname = item.find('cityname')
   pm10value = item.find('pm10value')
   print(cityname.get_text(), pm10value.get_text())
profile
Keep Going, Keep Coding!

0๊ฐœ์˜ ๋Œ“๊ธ€