전체 피드백

2주차 과제

Important Feedback

  1. 의미가 있는 코드 블럭마다 주석 다는 습관을 가집시다.(코드 관리가 편해진다)
  2. 주석다는 방법중 docstring의 예시가 있음. vscode의 extension으로 편하게 작성 가능하다.
  3. 과제는 제출물이기 때문에 문서의 가독성에 신경을 더 써서 최종 결과물을 만드는 데 집중한다.
  4. 변수명 또한 shop1,shop2처럼 넘버링하는 것보다 데이터의 특성에 맞춰 가독성 있게 작성한다.
  5. 주피터 노트북의 경우 코드블럭에서 저장된 변수나 라이브러리들이 그대로 재사용되어 최종 코드에 빠트리게 되는 경우가 발생된다. 만약 시험이나 실제 과제에서 제출하게 된다면 반드시 RESTART를 한 다음에 최종 코드를 테스트해본다. 최종코드를 파이썬 파일로 만들어 실행해보는 방법도 좋습니다.

1. API 데이터를 함수를 통해 받는 코드 작성

import os
import urllib.parse
import urllib.request
from dotenv import load_dotenv
 
load_dotenv()
 
def searh_naver_shopping(keyword:str):
    """네이버 쇼핑 리스트를 추출하는 함수
    
    Args:
        keyword (str): 검색할 쇼핑 키워드
 
    Returns:
        str: 네이버 API로 받은 쇼핑 목록 결과
    """
 
    # OPEN API KEY 불러오기
    client_id = os.getenv("NAVER_CLIENT_ID")
    client_key = os.getenv("NAVER_CLIENT_KEY")
 
    # URL 만들기
    encrypt_text = urllib.parse.quote(keyword)
    url = "https://openapi.naver.com/v1/search/shop?query="+ encrypt_text +"&display=20&exclude=used:rental"
 
    # 요청
    req_url = urllib.request.Request(url)    
    req_url.add_header("X-Naver-Client-Id", client_id)
    req_url.add_header("X-Naver-Client-Secret", client_key)
    response = urllib.request.urlopen(req_url)
 
  
 
    # 요청 코드 확인(200: 정상, 그외: 비정상)
    resp_code = response.getcode()
    if resp_code == 200:
        shop_output = response.read().decode("utf-8")
    else:
        shop_output = "Error" + resp_code
    return shop_output

1. 중간 피드백

2nd Feedback

  1. 과제에서 주어지는 조건들은 되도록 변수로 지정해주는 것이 좋습니다.
  2. 코딩테스를 볼 때에도 채점하는 과정이 조건에 주어진 변수들의 값만을 바꿔 값이 바뀌어도 정답을 유지하는지 확인하기 때문입니다.
  3. 이번 과제에서의 조건은 20개, 중고, 렌탈이었기 때문에 이를 변수화 하면 가독성이 더 좋아집니다.
  • 3번같은 경우 데이터의 갯수가 20개, 제외하는 검색어 중고,렌탈이므로
    • data_num = 20
    • prod_used = 'used'
    • prod_rental = 'rental
    • 이런 식으로 변수를 만들어 사용하는게 더 낫다는 말이다.

2. 중간 피드백

  • json라이브러리에서
    • .loads()는 dictionary형태의 string을 dictionary 객체로 바꿔주는 역할이고,
    • .dump()는 파이썬의 dictionary 객체를 JSON 형식으로 파일에 저장할 때 사용한다.

3rd Feedback

  1. 이번 과제에서 json 라이브러리를 사용하는 이유는 네이버 API에서 결과를 받았을 때, dictionary 형태의 string이 출력되었기 때문에 이를 dictionary 객체로 바꿔줘야 했습니다.
  2. json파일을 저장해도 좋지만 과제의 목적으로만 한다면 .loads()만 사용해도 됩니다.

3. 중간 피드백

4th Feedback

  • 데이터프레임을 만들 때에는 원본 데이터를 잘 살펴보고, 필요한 곳이 어디인지 파악해야 합니다.
  • 그리고 딕셔너리를 데이터프레임으로 만들때 다음과 같이 적용된다는 것을 알고 있어야 합니다.
  • 위를 고려하여 아래의 원본 데이터를 살펴보면 우리가 데이터프레임으로 하고자 하는 건 itemskey에 리스트로 되어 있는 것을 확인할 수 있습니다.
  • 또한, 현재 items의 value들은 한 행을 나타내고 있으며 이는 위에서 말한 데이터프레임 형식으로 하기에는 어려움이 있는 것으로 보입니다.
  • 여기서 생각할 수 있는 건 2가지 입니다.
    • 첫번째는 items의 value를 위에서 설명한 것처럼 데이터프레임에 넣기 위한 딕셔너리로 바꾸는 것. for loop사용
    • 두번째는 데이터프레임을 만들고 행을 계속 밑으로 추가하는 것입니다. pd.concat사용
{

    "lastBuildDate":"Tue, 11 Jun 2024 09:28:07 +0900",
    "total":19066208,
    "start":1,
    "display":20,
    "items":[
        {
            "title":"남여공용 스투시 베이직 로고 <b>반팔티셔츠<\/b> BLACKWHITE -",
            "link":"https:\/\/search.shopping.naver.com\/catalog\/40655140276",
            "image":"https:\/\/shopping-phinf.pstatic.net\/main_4065514\/40655140276.20240526074654.jpg",
            "lprice":"33450",
            "hprice":"",
            "mallName":"네이버",
            "productId":"40655140276",
            "productType":"1",
            "brand":"스투시",
            "maker":"",
            "category1":"패션의류",
            "category2":"남성의류",
            "category3":"티셔츠",
            "category4":""
        },
        ...
    ]
}

4. 피드백

5th Feedback

  • replace를 써서 문자열을 없애도 좋지만, 정규표현식으로도 할 수 있습니다.
  • 정규 표현식은 유효성 검사, 추출, 검색 등 많이 활용되니 알아두면 좋지만, 한번에 깊게 공부할 필요는 없으며, 나중에 자주 마주치게 되니 자연스럽게 익히면 된다.

정규 표현식

 
    import re
  
    text = "탑텐 남성 쿨에어 코튼 <b>반팔 티</b> 오버핏 MSD2TS1001"
  
    # HTML 태그 제거
    clean_text = re.sub(r'<(.*?)>', '', text)
 
    print(clean_text)
 
    ```
 
---
 
### 피드백을 이용한 코드 예시
 
- 과정에 대한 플로우 중시
```python
## 버전 1. 과정에 대한 플로우에 따라 하나의 함수를 만든다.
 
import os
import json
import urllib
from dotenv import load_dotenv
import pandas as pd
 
load_dotenv
 
def searh_naver_shopping(keyword:str, csv_path="./shopping_list.csv"):
 
    """네이버 쇼핑 리스트를 추출하는 함수
 
  
 
    Args:
 
        keyword (str): 검색할 쇼핑 키워드
 
        csv_path (str, optional): csv 저장 경로. 디폴트는 현재 디렉토리
 
  
 
    Returns:
 
        DataFrame: 네이버 API로 받은 쇼핑 목록 데이터프레임
 
    """
 
    # 데이터 불러오기
 
    ## OPEN API KEY 불러오기
    client_id = os.getenv("NAVER_CLIENT_ID")
    client_key = os.getenv("NAVER_CLIENT_KEY")
 
    ## URL 만들기
    display = 20
    exclude = ["used", "rental"]
    encrypt_text = urllib.parse.quote(keyword)
    base_url = "https://openapi.naver.com/v1/search/shop"
 
    url = base_url + f"?query={encrypt_text}&display={display}&exclude={':'.join(exclude)}"
 
    ## 요청
    req_url = urllib.request.Request(url)    
    req_url.add_header("X-Naver-Client-Id", client_id)
    req_url.add_header("X-Naver-Client-Secret", client_key)
    response = urllib.request.urlopen(req_url)
 
 
    ## 요청 코드 확인(200: 정상, 그외: 비정상)
    resp_code = response.getcode()
 
    if resp_code == 200:
        output_text = response.read().decode("utf-8")
    else:
        output_text = "Error" + resp_code
 
    ## dictionary 객체로 변환
    output_json = json.loads(output_text)
 
    # 데이터프레임 만들기
    select_vars = ["productId","title","brand","lprice","image","link"]
 
    ## 인덱싱
    df_shopping = pd.json_normalize(output_json["items"])[select_vars]
 
    ## 볼드 태그 제거(정규표현식 이용)
    df_shopping["title"] = df_shopping["title"].str.replace("<(.*?)>", "", regex=True)
 
    ## 인덱스 설정
    df_shopping.set_index("productId", inplace=True)
 
    ## 저장
    df_shopping.to_csv(csv_path)
 
  
 
    return df_shopping
  • 코드 블럭을 따라서 함수들을 만들어서 조합
## 버전 2. 코드 블럭에 따라 함수들을 만들어서 조합한다.
 
import os
import json
import urllib
from dotenv import load_dotenv
import pandas as pd
 
load_dotenv()
 
def searh_naver_shopping(keyword:str, csv_path="./shopping_list.csv"):
    """네이버 쇼핑 리스트를 추출하는 함수
    Args:
        keyword (str): 검색할 쇼핑 키워드
        csv_path (str, optional): csv 저장 경로. 디폴트는 현재 디렉토리
    Returns:
        DataFrame: 네이버 API로 받은 쇼핑 목록 데이터프레임
    """
 
    # 데이터 불러오기
    output_json = get_data(keyword)
 
    # 데이터프레임 만들기
    df_shopping = make_dataframe(output_json)
 
    # 저장
    df_shopping.to_csv(csv_path)
    return df_shopping
 
  
  
 
def get_data(keyword:str):
    """네이버 API에 데이터를 받아 dictionary 객체로 출력하는 함수
    Args:
        keyword (str): 검색할 쇼핑 키워드
    Returns:
        dict: 네이버 API로 받은 쇼핑 목록 데이터
    """
 
    ## OPEN API KEY 불러오기
    client_id = os.getenv("NAVER_CLIENT_ID")
    client_key = os.getenv("NAVER_CLIENT_KEY")
 
    ## URL 만들기
    display = 20
    exclude = ["used", "rental"]
    encrypt_text = urllib.parse.quote(keyword)
    base_url = "https://openapi.naver.com/v1/search/shop"
 
    url = base_url + f"?query={encrypt_text}&display={display}&exclude={':'.join(exclude)}"
 
  
 
    ## 요청
    req_url = urllib.request.Request(url)    
    req_url.add_header("X-Naver-Client-Id", client_id)
    req_url.add_header("X-Naver-Client-Secret", client_key)
    response = urllib.request.urlopen(req_url)
 
    ## 요청 코드 확인(200: 정상, 그외: 비정상)
    resp_code = response.getcode()
 
    if resp_code == 200:
        output_text = response.read().decode("utf-8")
    else:
        output_text = "Error" + resp_code
 
    ## dictionary 객체로 변환
    output_json = json.loads(output_text)
 
    return output_json
 
def make_dataframe(output_json:dict):
    """dictionary 객체를 DataFrame으로 만드는 함수
    Args:
        output_json (dict): 네이버 API의 출력 결과
 
    Returns:
        DataFrame: 네이버 API로 받은 쇼핑 목록 데이터프레임
    """
 
    select_vars = ["productId","title","brand","lprice","image","link"]
 
    ## 인덱싱
    df_shopping = pd.json_normalize(output_json["items"])[select_vars]
 
    ## 볼드 태그 제거
    df_shopping["title"] = df_shopping["title"].str.replace("<(.*?)>", "", regex=True)
 
    ## 인덱스 설정
    df_shopping.set_index("productId", inplace=True)
 
  
 
    return df_shopping
  • 위의 코드들과 같이 변수를 만들어 설정하는 편이 나중을 위해 습관을 들이는게 좋을거 같다.