Sparta Coding Club/Today I Learned [TIL]

[TIL] #DAY - 056 - (3) 무신사 크롤링? 스크랩핑!(브랜드별 할인율)

양한마리 2022. 11. 23. 08:58
728x90



무신사 크롤링? 스크래핑! 3탄

이번에는 무신사안에 입점해있는 브랜드별 할인율을 알아보려고한다!

과연 어떤 브랜드들 얼만큼 할인중인지 알아보자!




[문제 요약]

1. 무신사 실시간 랭킹을 1~90위까지 출력해보자

 

[TIL] #DAY - 054 - (1) 무신사 크롤링? 스크랩핑!(실시간 랭킹)

무신사 크롤링? 스크래핑! BeautifulSoup 을 이용하여 무신사 랭킹을 출력해보자! [문제 요약] 1. 무신사 실시간 랭킹을 1~90위까지 출력해보자 # 순위 : (1) ((2)) # 상품번호 : (3) # 브랜드명 : (4) # 상품명

hanmari-code.tistory.com

 

2. 카테고리 정보 출력해보자

 

[TIL] #DAY - 055 - (2) 무신사 크롤링? 스크랩핑!(카테고리 정보)

무신사 크롤링? 스크래핑! 2탄 지난시간에 이어서 무신사에서 지정하고있는 카테고리 정보를 출력해보려고한다 카테고리 정보를 가져와서 뭐할까? 라는 생각도 들겠지만 사이트 구조를 자세히

hanmari-code.tistory.com

 

3. 브랜드별 할인율 출력해보자

- 무신사에는 정말 수 많은 브랜드들이 입점해있다.
 간혹 브랜드별로 얼마나 할인하는지 알아보고싶을때 유용하게 사용할수있는 브랜드별 할인율을 출력해보도록하자.

출력 예시)

브랜드명 : 키르시
 상품수 : 270개
 평균 할인율 : 17%
 최대 할인율 : 50%
 최소 할인율 : 0%

 

[풀이 요약]

1. 브랜드 링크 정보 : HTML, BeautifulSoup 를 이용하여 html 내용 출력하기
2. 브랜드 페이지안에 있는 각각 상품들 정보 출력하기
3. 출력한 정보 필터링해서 정리하기
4. 정리된 정보를 가지고 원하는 양식으로 출력하기
5. 출력된 정보 txt 파일로 저장하기

 

[첨부 파일]

nav_left_brand_menu.html
0.13MB

 

[코드]

1. nav_left_brand_menu.html

브랜드 정보는 위 파일에서 가져올수있다.

import requests
import math
import sys
from bs4 import BeautifulSoup


headers = {}# User Agent string 내용 확인하기

# 브랜드 정보 가져오기
page = open("nav_left_brand_menu.html", "rt", encoding="utf-8").read()
soup = BeautifulSoup(page, 'html.parser')

brand_list = soup.find_all("li", attrs={"class":"listItem"})                      # nav_left_brand_menu.html 에서 필요한 정보만 brand_list에 담아주기
urls_list = set()                                                                 # 최종 브랜드 정보를 담아줄 변수 (set 중복제거)
for brand in brand_list:                                                          
    brand_name_kr = brand.find("span", attrs={"class":"kor"}).get_text()          # 브랜드명(국문)
    brand_name_en = brand.find("span", attrs={"class":"eng"}).get_text()          # 브랜드명(영문)
    brand_urls = brand.find("a", attrs={"class":"command-brand-list"})["href"]    # 브랜드 페이지 링크 <- 이번에 사용할 정보
    urls_list.add(brand_urls)                                                     # 최종 urls_list 에 브랜드 링크 정보 담아주기
urls_list = list(urls_list)                                                       # set -> list 변환

# 브랜드 페이지 링크를 가지고 상품 정보 가져오기
product_list = []                                                                 # 최종 상품정보를 담아줄 변수
for urls in urls_list:
    print(urls)
    for page in range(1, 4):                                                      # 1 ~ 3 페이지까지 상품 정보 가져오기
        url = f"{urls}?category3DepthCodes=&category2DepthCodes=&category1DepthCode=&colorCodes=&startPrice=&endPrice=&exclusiveYn=&includeSoldOut=&saleGoods=&timeSale=&includeKeywords=&sortCode=NEW&tags=&page={page}&size=90&listViewType=small&campaignCode=&groupSale=&outletGoods=false&boutiqueGoods="
        res = requests.get(url, headers)
        res.raise_for_status()
        soup = BeautifulSoup(res.text, 'lxml')
        
        # 각 브랜드 페이지에서 상품 정보가져오기
        all_products = soup.find_all("li", attrs={"class":"li_box"})
        for item in all_products:

            # 브랜드명
            brand_name = item.find("p", attrs={"class":"item_title"}).a
            if brand_name != None:
                brand_name = brand_name.get_text()
            else:
                pass
            
            # 상품명
            product_name = item.find("p", attrs={"class":"list_info"}).a.get_text()
            product_name = product_name.replace(" ", "")
            product_name = product_name.replace("\n", "")
            
            # 가격 (정상가/할인가)
            price = item.find("p", attrs={"class":"price"}).get_text()
            price = price.replace(",", "").replace("원", "").split()
            if len(price) == 2:
                original_price = price[0]
                discount_price = price[1]
            else:
                original_price = price[0]
                discount_price = price[0]
                
            # 할인율 구하기
            discount_rate = math.floor(round((1-int(discount_price)/int(original_price)) * 100, 0))  

            # 리뷰 갯수
            review_count = item.find("span", attrs={"class":"count"})
            if review_count != None:
                review_count = int(review_count.get_text().replace(",", ""))
            else:
                review_count = 0
            review_count = format(review_count, ",")
            
            # 최종 리스트에 추가
            product_list.append({
                "brand":brand_name,                    # 브랜드명
                "name":product_name,                   # 상품명
                "original_price":int(original_price),  # 정상가
                "discount_price":int(discount_price),  # 할인가
                "discount_rate":discount_rate,         # 할인율
                "review":review_count                  # 리뷰 갯수
            })
    

# 각 브랜드별 최종 할인율 구하기 위한 필터링
result = []
for rank in product_list:
    brand_list = {}
    brand_list["brand"] = rank["brand"]
    brand_list["discount_rate"] = rank["discount_rate"]
    result.append(brand_list)

brands = set()
for br in product_list:
    brand = br["brand"]
    brands.add(brand)

brand_list_ = list(brands)

list_sale = []
for n in brand_list_:
    list_br = []
    for i in result:  
        if i["brand"] == n:
            list_br.append(i["discount_rate"])
            
    list_sale.append({
        "brand":n,
        "sale":list_br
    })


sys.stdout = open("brand_page_sales.txt", "w")            # 여기부터 txt 파일로 저장
# 각 브랜드별로 필터링된 할인율 최종 양식으로 출력하기
for sale in list_sale:
    brand_name = sale["brand"]
    sales = sale["sale"]
    product_count = len(sales)
    rate = math.floor(round(sum(sales)/len(sales),0))
    max_rate = max(sales)
    min_rate = min(sales)
    print(f"\n브랜드명 : {brand_name}\n",                   # 브랜드명
          f"상품수 : {product_count}개\n",                  # 상품수
          f"평균 할인율 : {rate}%\n",                       # 평균 할인율 
          f"최대 할인율 : {max_rate}%\n",                   # 최대 할인율
          f"최소 할인율 : {min_rate}%\n",                   # 최소 할인율
          )

sys.stdout.close()                                        # 여기까지 txt 파일로 저장

 

[출력]

출력 예시)

브랜드명 : 질바이질스튜어트
 상품수 : 270개
 평균 할인율 : 22%
 최대 할인율 : 60%
 최소 할인율 : 0%


브랜드명 : 나이스고스트클럽
 상품수 : 270개
 평균 할인율 : 39%
 최대 할인율 : 70%
 최소 할인율 : 0%


브랜드명 : 던스트 포 우먼
 상품수 : 147개
 평균 할인율 : 7%
 최대 할인율 : 50%
 최소 할인율 : 0%


브랜드명 : 아디다스
 상품수 : 270개
 평균 할인율 : 11%
 최대 할인율 : 58%
 최소 할인율 : 0%


브랜드명 : 86로드
 상품수 : 85개
 평균 할인율 : 51%
 최대 할인율 : 76%
 최소 할인율 : 0%
728x90
반응형