KeyError 문제

조회수 898회
# coding: utf-8

import hmac
import hashlib
import os
import time
import requests
import json
import urllib.request
from selenium import webdriver
import secrets
from urllib.parse import urlencode
from wordpress_xmlrpc import Client
from wordpress_xmlrpc import WordPressPost
from wordpress_xmlrpc.methods import posts

__author__ = "wdgg<>"


class cupangMgr:
    DOMAIN = "https://api-gateway.coupang.com"

    def generateHmac(self, method, url, secretKey, accessKey):
        path, *query = url.split("?")
        os.environ["TZ"] = "GMT+0"
        datetime = time.strftime('%y%m%d') + 'T' + time.strftime('%H%M%S') + 'Z'
        message = datetime + method + path + (query[0] if query else "")
        signature = hmac.new(bytes(secretKey, "utf-8"), message.encode("utf-8"), hashlib.sha256).hexdigest()
        return "CEA algorithm=HmacSHA256, access-key={}, signed-date={}, signature={}".format(accessKey, datetime,
                                                                                              signature)

    def get_productsdata(self, request_method, authorization, keyword, limit):
        URL = "/v2/providers/affiliate_open_api/apis/openapi/products/search?keyword=" + urllib.parse.quote(
            keyword) + "&limit=" + str(limit)
        url = "{}{}".format(self.DOMAIN, URL)
        response = requests.request(method=request_method, url=url, headers={"Authorization": authorization,
                                                                             "Content-Type": "application/json;charset=UTF-8"})
        retdata = json.dumps(response.json(), indent=4).encode('utf-8')
        jsondata = json.loads(retdata)
        data = jsondata['data']
        productdata = data['productData']
        return productdata


if __name__ == '__main__':
    method = 'GET'  # 정보를 얻는것이기 때문에 GET
    keyword = '아이패드'  # 검색할 키워드, 쿠팡에서 검색하는거랑 결과가 동일합니다.
    limit = 1  # 몇개의 정보를 가져올지 설정. 상위부터 가져옵니다.
    access_key = ''  # API access key
    secret_key = ''  # API secret key
    URL = "/v2/providers/affiliate_open_api/apis/openapi/products/search?keyword=" + urllib.parse.quote(
        keyword) + "&limit=" + str(limit)

    test = cupangMgr()
    authorization = test.generateHmac(method, URL, secret_key, access_key)  # HMAC 생성
    productdata = test.get_productsdata(method, authorization, keyword, limit)  # API 호출
    productCount = len(productdata)
    i = 0
    while i < productCount:
        print(productdata[i]['productId'])
        print(productdata[i]['productName'])
        print(productdata[i]['productPrice'])
        print(productdata[i]['productImage'])
        print(productdata[i]['productUrl'])
        print(productdata[i]['keyword'])
        print(productdata[i]['rank'])
        print(productdata[i]['isRocket'])
        print(productdata[i]['isFreeShipping'])
        #print(datetime.datetime.now())
        strProductId = str((productdata[i]['productId']))
        strProductName = (productdata[i]['productName'])
        strProductPrice = str((productdata[i]['productPrice']))
        strProductImage = (productdata[i]['productImage'])
        strProductUrl = (productdata[i]['productUrl'])
        strKeyword = (productdata[i]['keyword'])
        strRank = str((productdata[i]['rank']))
        strIsRocket = bool(productdata[i]['isRocket'])
        strIsFreeShipping = bool(productdata[i]['isFreeShipping'])
        if strIsRocket == True:
            strIFRocket = '로켓배송 가능 상품이라 로켓배송 지역이면, 로켓배송으로 빠르게 배송 받아보실 수 있습니다.'
        else:
            strIFRocket = '로켓배송 가능한지는 아래 배송도착일 확인 링크에서 확인 가능합니다.'

        if strIsFreeShipping == True:
            strIFFreeship = '배송비는 무료이며,'
        else:
            strIFFreeship = '배송비는 아래 배송도착일 확인 링크에서 확인 가능하며,'

            client = Client("", "", "")
            postx = WordPressPost()
            postx.title = '<p><span style="color:#ececec; background:#e81949; padding:9px 12px 7px 12px; border-radius:30px;">구매하기</span></p>' + strProductName
            postx.slug = strProductName
            postx.content = '''<p><span style="font-family: Helvetica;">오늘 소개해드릴 상품은 최근 소비자 검색량, 구매율이 급상승중인 ''' + strProductName + ''' 입니다.</span></p>
            <p><span style="font-family: Helvetica;">또한 이 상품은 쿠팡에서 ''' + strKeyword + ''' 조회시 추천 순위 ''' + strRank + '''위 입니다.</span></p>
            <p><span style="font-family: Helvetica;">''' + strKeyword + ''' 인기순위, ''' + strKeyword + ''' 가격정보는 아래 본문에서 확인 가능합니다.</span></p>
            <p><span style="font-family: Helvetica; color: rgb(40, 50, 78);">(업데이트 날짜 : ''' + time.strftime(
                '%y-%m-%d') + ''')</span></p>
            <p><span style="font-family: Helvetica;">상품별 추천순위, 판매가격, 배송비, 로켓배송 가능여부, 상품사진을 확인 하실 수 있습니다.</span></p>
            <p><span style="font-family: Helvetica;"><br></span></p>
            <h1><span style="font-family: Helvetica; font-size: 19px; color: rgb(209, 72, 65);">''' + strProductName + '''</span></h1>
            <p><span style="font-family: Helvetica;"><br></span></p>
            <h2><span style="font-family: Helvetica; font-size: 19px; color: rgb(243, 121, 52);">▶ 판매가격</span></h2>
            <p><span style="font-family: Helvetica;">가격은 <span style="color: rgb(44, 130, 201);">''' + strProductPrice + '''원</span> 입니다.</span></p>
            <p><span style="font-family: Helvetica;">(아래 링크에서 현재 가격을 확인 하세요.)</span></p>
            <p><a href="''' + strProductUrl + '''" rel="noopener noreferrer" target="_blank"><span style="font-family: Helvetica;"><strong>★ 현재가격 보기 ★</strong></span></a></p>
            <p><span style="font-family: Helvetica;"><br></span></p>
            <h2><span style="font-family: Helvetica; font-size: 19px; color: rgb(243, 121, 52);">▶ 배송비, 로켓배송</span></h2>
            <p><span style="font-family: Helvetica;">''' + strIFFreeship + ''',</span></p>
            <p><span style="font-family: Helvetica;">''' + strIFRocket + '''</span></p>
            <p><span style="font-family: Helvetica;">(배송비, 로켓배송 가능 여부가 변동될 수 있으니 아래 링크에서 확인하세요.)</span></p>
            <p><a href="''' + strProductUrl + '''" rel="noopener noreferrer" target="_blank"><span style="font-family: Helvetica;"><strong>★ 배송비, 로켓배송 보기 ★</strong></span></a></p>
            <p><span style="font-family: Helvetica;"><br></span></p>
            <h2><span style="font-family: Helvetica; font-size: 19px; color: rgb(243, 121, 52);">▶ 상품 상세정보, 구매후기</span></h2>
            <p><span style="font-family: Helvetica;">추가적인 상품정보, 상품사진 및 구매후기는 아래 상품 이미지를 클릭하시면 확인 가능합니다.</span></p>
            <p><a href="''' + strProductUrl + '''" rel="noopener noreferrer" target="_blank"><span style="font-family: Helvetica; font-size:24px;"><strong>바로 구매하기</strong></span></a></p>
            <p><span style="font-family: Helvetica;"><br></span></p>
            <h2><a href="''' + strProductUrl + '''" rel="noopener noreferrer" target="_blank"><span style="font-family: Helvetica; font-size: 19px; color: rgb(243, 121, 52);">▶ 상품사진</span></a></h2>
            <p><a href="''' + strProductUrl + '''" rel="noopener noreferrer" target="_blank"><img src="''' + strProductImage + '''"></a></p>
            <p><span style="font-family: Helvetica;">이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.</span></p>
            <p><br></p>'''
            postx.terms_names = {
                'post_tag': [strKeyword + ' 추천', strKeyword + ' 순위', strKeyword + ' 비교', strKeyword + ' 가격비교'],
                'category': ['Coupangs']
            }
            postx.post_status = 'publish'
            client.call(posts.NewPost(postx))
            time.sleep(5)
            i = i + 1

이걸로 결국 워드프레스에 자동 포스팅 잘 실행하고 있었는데요, 갑자기 아래와 같은 에러가 발생합니다.. 어떻게 해결해야 할까요

Traceback (most recent call last):
  File "C:\Users\13mile\PycharmProjects\pythonProject\3.py", line 56, in <module>
    productdata = test.get_productsdata(method, authorization, keyword, limit)  # API 호출
  File "C:\Users\13mile\PycharmProjects\pythonProject\3.py", line 40, in get_productsdata
    data = jsondata['data']
KeyError: 'data'

1 답변

  • /v2/providers/affiliate_open_api/apis/openapi/products/search 에 대한 REST API 호출 과정 중 응답 JSON 에 'data' 항목이 없어서 발생하네요.

    다음 코드에서 jsondata가 어떤 값으로 되어 있는지 확인할 필요가 있습니다.

            retdata = json.dumps(response.json(), indent=4).encode('utf-8')
            jsondata = json.loads(retdata)
            data = jsondata['data']
    

    아마 해당 REST API가 요청에 대한 오류를 응답할 수 있는데 작성하신 코드는 그런 사항없이 무조건 data가 존재할 거라 가정하고 작성되어서 문제가 발생하는 것 같습니다.

    https://api-gateway.coupang.com/v2/providers/affiliate_open_api/apis/openapi/products/search 으로 쿼리를 날리면 다음과 같이 data가 없는걸 볼수 있습니다.

    {
      "code" : "ERROR",
      "message" : "Request is not authorized.",
      "transactionId" : "b3a3a62e-4407-435e-9ce7-43a06b5de632",
      "messages" : {
        "korean" : "미인증된 요청은 허용되지 않습니다. 클라이언트의 정보가 정상적으로 설정되어 있는지 확인 부탁드립니다. (CMDB, 컨수머 토큰 또는 HMAC)",
        "english" : "Unauthorized request is denied. Check if the client's credential meets the requirements (CMDB, consumer token or HMAC)."
      }
    }
    

    해당 API의 실패에 대한 내용이 jsondata에 담겨 있으니 확인이 필요합니다.


    다음 과 같이 print("jsondata=", jsondata)을 추가하고 콘솔에 나타나는 내용을 확인하시면 됩니다.

        def get_productsdata(self, request_method, authorization, keyword, limit):
            URL = "/v2/providers/affiliate_open_api/apis/openapi/products/search?keyword=" + urllib.parse.quote(
                keyword) + "&limit=" + str(limit)
            url = "{}{}".format(self.DOMAIN, URL)
            response = requests.request(method=request_method, url=url, headers={"Authorization": authorization,
                                                                                 "Content-Type": "application/json;charset=UTF-8"})
            retdata = json.dumps(response.json(), indent=4).encode('utf-8')
            jsondata = json.loads(retdata)
            print("jsondata=", jsondata)
            data = jsondata['data']
            productdata = data['productData']
            return productdata
    

    다음과 같이 'data'가 없을 때 jsondata를 출력하고 함수의 결과가 없는 식으로 처리하여 프로그램이 멈추지 않고 이어서 동작하도록 예외처리할 수 있습니다.

        def get_productsdata(self, request_method, authorization, keyword, limit):
            URL = "/v2/providers/affiliate_open_api/apis/openapi/products/search?keyword=" + urllib.parse.quote(
                keyword) + "&limit=" + str(limit)
            url = "{}{}".format(self.DOMAIN, URL)
            response = requests.request(method=request_method, url=url, headers={"Authorization": authorization,
                                                                                 "Content-Type": "application/json;charset=UTF-8"})
            retdata = json.dumps(response.json(), indent=4).encode('utf-8')
            jsondata = json.loads(retdata)
            if not 'data' in jsondata:
                print("jsondata=", jsondata)
                return []
    
            data = jsondata['data']
            productdata = data['productData']
            return productdata
    
    • 답변 감사드립니다~~ 그런데 제가 파이썬은 아예 할줄모르고 구글링 통해서통해서 했던거라서, jsondata에 내용을 어떻게 확인해야 할까요..? 알 수 없는 사용자 2021.12.1 16:01
    • 출력 방법 추가하겠습니다. 확인해 주세요. 유동욱 2021.12.1 16:03
    • 그리고 혹시 데이터가 없는 경우에도 어떻게해서 실행한다... 라는 코드를 추가할수도 있을까요,, ? 알 수 없는 사용자 2021.12.1 16:03
    • 일단 jsondata를 확인해 보고, 코드 수정 이외의 방법이 있을지 생객해 볼 필요가 있습니다. 유동욱 2021.12.1 16:05
    • 빠른 답변 감사드립니다. 알 수 없는 사용자 2021.12.1 16:11
    • jsondata= {'rCode': '403', 'rMessage': '검색 API의 시간당 사용 횟수 (API 가이드 - 문서 참고) 를 초과했습니다. 2021-12-02T11:12:05.601 이후에 다시 시도해 주시기 바랍니다. 총 3회 초과시 파트너스 이용이 제한됩니다. (현재 *1*회 초과)'} 알 수 없는 사용자 2021.12.1 16:11
    • 이렇게 나오는것을 보니 그냥 테스트하면서 쿠팡파트너스 api조회 회수를 초과한것 같습니다. 알 수 없는 사용자 2021.12.1 16:12
    • 네 그렇네요. 일단 예외 처리하는 방법을 본문에 추가해 드릴게요. 예외상황이 오면 jsondata를 출력하면 동작하도록 작성하면되겠네요. 유동욱 2021.12.1 16:14
    • 네 잘 실행됩니다~ 확실한 마무리 해결책까지,,정말 너무 감사드립니다^^ 알 수 없는 사용자 2021.12.1 16:22
    • 마지막으로 한가지만 더 여쭤볼게 있습니다. 저 코드가 실행됐을때, 이럴때가 있는데요, 만약 limit값이 10이라면 1에서~2? 3정도까지 실행되다 막 무한대로 3~4이상 안넘어가고 계속 출력되는 현상이 있는데 해결할 수 있는 방법은 없을까요 ? 알 수 없는 사용자 2021.12.1 16:40
    • REST API의 limit 쿼리에 대한 동작 및 응답은 해당 API문서를 확인해 봐야합니다. 검색해 봤는데 코드만 난무하고 잘 안보이네요. limit은 통산 쿼리할때 결과 값의 개수를 제한하는 용도로 사용하는데 10 입력해도 결과가 2개면 2개만 나올 거에요. 최대 개수를 정하는 용도로 사용될거에요. "막 무한대로 3~4이상 안넘어가고 계속 출력되는 현상"요 현상이란게 어떤걸 말씀하는지 잘 이해가 안되네요. 유동욱 2021.12.1 16:50
    • 아 찾았네요. https://partners.coupang.com/#help/open-api 여기에 문서가 있네요. 유동욱 2021.12.1 16:53
    • 저걸 컨트롤 쉬프트 f10으로 실행하면 그 아래 실행창? 거기서 계속 에러나면서 글 등록은 안되는데 계속 실행되고 있습니다. 계속 줄바꿈되면서 에러와 함께 반복 실행되고 실제 글은 안올라가고, 계속 api는 호출되는듯한?.. 리밋을 몇으로 주던 마찬가지 현상이 일어나더라구요~ 그리고 강제로 멈추면 그때 나오는 에러문구 뜨면서 멈추구요~ 알 수 없는 사용자 2021.12.1 17:01
    • 해당 내용을 글로 파악하기 어려우니, 사진하고 같이 새로운 질문으로 올려주세요. 유동욱 2021.12.1 17:03
    • 그 pip install 땡땡땡 누르면 자동으로 주르륵 실행되는거처럼 예로 리밋 10일때 1만 등록되고 이후로는 에러가 반복실행된다고 보시면 될듯합니다~ 알 수 없는 사용자 2021.12.1 17:03
    • 네 또 해당현상 발견되면 올리겠습니다~ 알 수 없는 사용자 2021.12.1 17:12

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)