전체 피드백
Important Feedback
- 의미가 있는 코드 블럭마다 주석 다는 습관을 가집시다.(코드 관리가 편해진다)
- 주석다는 방법중
docstring의 예시가 있음. vscode의 extension으로 편하게 작성 가능하다.- 과제는 제출물이기 때문에 문서의 가독성에 신경을 더 써서 최종 결과물을 만드는 데 집중한다.
- 변수명 또한
shop1,shop2처럼 넘버링하는 것보다 데이터의 특성에 맞춰 가독성 있게 작성한다.- 주피터 노트북의 경우 코드블럭에서 저장된 변수나 라이브러리들이 그대로 재사용되어 최종 코드에 빠트리게 되는 경우가 발생된다. 만약 시험이나 실제 과제에서 제출하게 된다면 반드시 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_output1. 중간 피드백
2nd Feedback
- 과제에서 주어지는 조건들은 되도록 변수로 지정해주는 것이 좋습니다.
- 코딩테스를 볼 때에도 채점하는 과정이 조건에 주어진 변수들의 값만을 바꿔 값이 바뀌어도 정답을 유지하는지 확인하기 때문입니다.
- 이번 과제에서의 조건은 20개, 중고, 렌탈이었기 때문에 이를 변수화 하면 가독성이 더 좋아집니다.
- 3번같은 경우 데이터의 갯수가
20개, 제외하는 검색어중고,렌탈이므로data_num = 20prod_used = 'used'prod_rental = 'rental- 이런 식으로 변수를 만들어 사용하는게 더 낫다는 말이다.
2. 중간 피드백
json라이브러리에서.loads()는 dictionary형태의 string을 dictionary 객체로 바꿔주는 역할이고,.dump()는 파이썬의 dictionary 객체를 JSON 형식으로 파일에 저장할 때 사용한다.
3rd Feedback
- 이번 과제에서 json 라이브러리를 사용하는 이유는 네이버 API에서 결과를 받았을 때, dictionary 형태의 string이 출력되었기 때문에 이를 dictionary 객체로 바꿔줘야 했습니다.
- 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- 위의 코드들과 같이 변수를 만들어 설정하는 편이 나중을 위해 습관을 들이는게 좋을거 같다.
