본문 바로가기
코딩 연습/파이썬 크롤링

온채널 도매 사이트 명예의전당 우수상품 리스트

by good4me 2022. 5. 24.

goodthings4me.tistory.com

쇼핑몰 도매사이트 온 채널의 명예의 전당(매년 많이 팔린 상품)에 있는 우수상품 리스트를 파이썬으로 크롤링하는 코드이다. 작년에 짜 놓은 코드에서 오류 나는 부분만 수정해서 포스팅함

 

 

온채널 도매사이트 우수상품 크롤링

 

[파이썬 소스 코드]

import requests
from bs4 import BeautifulSoup as bts4
from urllib.parse import urljoin
import time
import random
import openpyxl
import os


def onch3_halloffame(page):
    onch3 = 'https://www.onch3.co.kr'

    ## 폴더 생성
    if not os.path.exists('./onch3'):
        os.makedirs('./onch3')

    if not os.path.exists('./image'):
        os.makedirs('./image')

    ## 엑셀 제목
    theme_list = ['no', 'prd_code', 'prd_name', 'prd_url', 'onch_category', 'product_name', \
        'keywords', 'smartstore_code', 'smartstore_category', 'product_name2', 'supp_grade', \
            'supp_title', 'price_type', 'deliver', 'deadline_time', 'product_status', 'entry_date']

    ## 엑셀 워크북(파일) 생성 후 열 제목 추가
    workbook_name = 'onch3_2021_best1000.xlsx'
    wb = openpyxl.Workbook()
    wb.save('./onch3/' + workbook_name)
    ws = wb['Sheet']
    ws.append(theme_list)
    wb.save('./onch3/' + workbook_name)    


    cnt = 0  # 추출 리스트 카운트 cnt = 0
    row = 1  # 행 번호
    for page in range(1, page + 1):
        url = 'https://www.onch3.co.kr/onch_hall_of_fame.html?sec=2021&page=' + str(page)
        # url = 'https://www.onch3.co.kr/onch_hall_of_fame.html?sec=best&page=' + str(page)  # 금년도
        response = requests.get(url)
        response.encoding = 'utf-8'
        soup = bts4(response.text, 'html.parser')
        
        ## 'ul.prd_list' 1개 / 'ul.prd_list > li' 40개
        ul_lis = soup.select('ul.prd_list > li')
        products = []

        for li in ul_lis:
            
            for ls in li.select('ul.prd_info'):
                cnt += 1
                row += 1
                details = {}
                
                prd_code = ls.find('li', class_='prd_code').get_text().split(' : ')[1].strip()
                prd_name = ls.find('li', class_='prd_name').text
                prd_link = ls.find('li', class_='btn_sale').find('a')['href']
                sub_url = urljoin(onch3, prd_link)
                # print(prd_code, prd_name, sub_url)
                details['prd_code'] = prd_code
                details['prd_name'] = prd_name
                details['prd_url'] = sub_url
                
                time.sleep(random.uniform(0.5, 1))
                
                ## 상품 상세페이지 스크래핑 - requests
                sub_response = requests.get(sub_url)
                sub_response.encoding = 'utf-8'
                sub_soup = bts4(sub_response.text, 'html.parser')
                
                ## 온채널 카테고리
                onch_cate = sub_soup.find('div', class_='detail_page_category').text.strip()
                details['onch_category'] = onch_cate
                
                ## 상품 상세정보
                prd_detail = sub_soup.select('div.prod_detail_box > ul > li')
                
                # 상품명
                product_name = prd_detail[0].text.strip()
                details['product_name'] = product_name
                
                # 추천키워드
                keywords = prd_detail[1].find('div', class_='prod_keyword').text.strip()
                # 온채널 추천키워드 내 '#'과 '공란' 제거 후 '#'으로 분리, 리스트 중 '공백' 제거하기
                keywords = [word for word in keywords.replace('#', '#').replace(' ', '').split('#') if word != '']
                details['keywords'] = keywords
                
                # 스마트스토어 카테고리 코드
                smartstore_code = prd_detail[1].find('div', class_='prod_ss_cate').find('span', class_='ss_cate_num').text.strip()
                details['smartstore_code'] = smartstore_code
                
                # 스마트스토어 카테고리
                smartstore_cate = prd_detail[1].find('div', class_='prod_ss_cate').text[9:].strip()
                details['smartstore_category'] = smartstore_cate
                
                ## 제품명/제품코드/공급업체분류/공급사페이지
                
                # 상품명
                product_name2 = prd_detail[2].find('div', class_='prod_detail_title_2').text.strip()
                details['product_name2'] = product_name2
                
                # 공급사 평점
                supp_grade = prd_detail[2].find('div', class_='sup_grade hidden_element').find('dt').text.strip()
                details['supp_grade'] = supp_grade
                
                # 공급업체분류
                supp_title = ' '.join(prd_detail[2].find_all('li')[2].text.strip().split())  # 다중 공백을 1개로 치환 - 문자열
                details['supp_title'] = supp_title
                
                # 공급사 페이지 - 인증 회원만 열람 가능
                #supp_hpage = prd_detail[2].find_all('li')[3].find('a')['href']
                
                
                ## 소비자가/판매자공급가/운영채널분류 등
                
                # 운영체제 분류
                price_type = prd_detail[3].find_all('li')[2].text.strip().split()  # 다중 공백을 1개로 치환 - 리스트
                details['price_type'] = price_type
                
                # 배송비/택배사
                deliver = ' '.join(prd_detail[4].find_all('li')[0].text.strip().split())
                details['deliver'] = deliver
                
                # 마감/발송처/기간
                deadline_time = ' '.join(prd_detail[4].find_all('li')[1].text.strip().split())
                details['deadline_time'] = deadline_time
                
                # 제품상태/입정일자
                product_status = prd_detail[5].find_all('li')[0].text.strip().split()
                details['product_status'] = product_status
                
                entry_date = prd_detail[5].find_all('li')[1].text.strip().split()
                details['entry_date'] = entry_date
                
                time.sleep(random.uniform(0.5, 1))
                
                ### 엑셀에 추출 데이터 저장하기
                for k, v in details.items():
                    ws.cell(row, 1).value = cnt
                    if k == 'prd_code':
                        ws.cell(row, 2).value = v
                    if k == 'prd_name':
                        ws.cell(row, 3).value = v               
                    if k == 'prd_url':
                        ws.cell(row, 4).value = v
                    if k == 'onch_category':
                        ws.cell(row, 5).value = v
                    if k == 'product_name':
                        ws.cell(row, 6).value = v
                    if k == 'keywords':
                        keyWords = ''
                        for word in keywords:
                            keyWords = keyWords + '$' + word
                        ws.cell(row, 7).value = keyWords
                    if k == 'smartstore_categCode':
                        ws.cell(row, 8).value = v
                    if k == 'smartstore_category':
                        ws.cell(row, 9).value = v               
                    if k == 'product_name2':
                        ws.cell(row, 10).value = v
                    if k == 'supp_grade':
                        ws.cell(row, 11).value = v
                    if k == 'supp_title':
                        ws.cell(row, 12).value = v                   
                    if k == 'price_type':
                        priceType = ''
                        for word in price_type:
                            priceType = priceType + '$' + word
                        ws.cell(row, 13).value = priceType
                    if k == 'deliver':
                        ws.cell(row, 14).value = v               
                    if k == 'deadline_time':
                        ws.cell(row, 15).value = v
                    if k == 'product_status':
                        productStatus = ''
                        for word in product_status:
                            productStatus = productStatus + '$' + word                    
                        ws.cell(row, 16).value = productStatus
                    if k == 'entry_date':
                        entryDate = ''
                        for word in entry_date:
                            entryDate = entryDate + '$' + word                    
                        ws.cell(row, 17).value = entryDate
                        
                wb.save('./onch3/' + workbook_name)
                
                time.sleep(random.uniform(0.5, 1))
                
                ## 대표 이미지 받기
                product_imgs = sub_soup.select('div.prod_detail_imgbox > a > img')
                img_cnt = 1
                for img in product_imgs:
                    try:  # 이미지가 없어서 발생하는 오류 방지
                        print(img['src'])
                        image = requests.get(img['src']).content
                    except:
                        print('Error - 이미지 오류!!')
                        pass
                    
                    # 폴더명 특수문자 제거
                    special_char = '\/:*?"<>|\t'  # 폴더명에 탭(\t) 들어간 경우
                    keywords[0] = ''.join(c for c in keywords[0] if c not in special_char)
                    # keyWords[0] = keyWords[0].replace('\t', '')
                                    
                    path = './image/' + prd_code + '_' + keywords[0]
                    if not os.path.exists(path):
                        os.mkdir(path)
                        
                    filename = prd_code + '_' + str(img_cnt) + '.jpg'
                    print(filename)
                    
                    with open(f'{path}/{filename}', 'wb') as img:
                        img.write(image)
                    
                    img_cnt += 1            
                    
                time.sleep(random.uniform(0.5, 1))
                
                ## 제품 상세 내용 이미지
                product_detail_imgs = sub_soup.select('div.content_section img')
                imgs_cnt = 1
                for img in product_detail_imgs:
                    try:  # 이미지가 없어서 발생하는 오류 방지
                        print(img['src'])
                        images = requests.get(img['src']).content
                    except:
                        print('Error - 이미지 오류!!')
                        pass
                        
                    file_name = prd_code + '_' + 'detail' + '_' + str(imgs_cnt) + '.jpg'
                    print(file_name)
                    
                    with open(f'{path}/{file_name}', 'wb') as image:
                        image.write(images)
                    
                    imgs_cnt += 1

            products.append(details)
            print(cnt)

        print(f'\n{products}\n\n{page}페이지 리스트 추출 및 엑셀 저장 완료!!\n')
                

if __name__ == '__main__':
    page = 2
    onch3_halloffame(page)
  • 우수상품 하단에 페이지 번호가 있다. 이 부분에서 끝 페이지 번호를 알아낸 후 page 변수에 페이지 번호를 대입하고 프로그램을 실행하면 된다. (단, 전체 페이지를 한번에 추출하는 것은 자제!)
  • 우수상품을 클릭하면 상세페이지가 나오는데, 추천 키워드, 스마트 스토어 카테고리, 제품명, 제품 코드 공급사 평점, 배송비/택배비, 입점 일자 등의 내용을 추출하여 엑셀에 저장을 한다.
  • 이미지 폴더를 생성하고 제품명을 폴더명으로 하여 생성 후 대표이미지와 상세 이미지를 다운로드한다. 

 

good4me.co.kr

 

[실행 결과]

https://image.onch3.co.kr/img_data/2021/1622682235_img80.jpg
CH1506009_1.jpg
https://image.onch3.co.kr/img_data/2021/1627956429_img75.jpg
CH1506009_detail_1.jpg
https://image.onch3.co.kr/img_data/2021/1627956494_img25.jpg
CH1506009_detail_2.jpg
1
https://image.onch3.co.kr/img_data/2020/1599619131_img89.jpg
CH1320982_1.jpg
https://image.onch3.co.kr/ext_image/2017/2017_06/CH1320982_20170602_0169.jpg
CH1320982_detail_1.jpg
https://image.onch3.co.kr/ext_image/2017/2017_06/CH1320982_20170602_0170.gif
CH1320982_detail_2.jpg
https://image.onch3.co.kr/ext_image/2017/2017_06/CH1320982_20170602_0171.jpg
CH1320982_detail_3.jpg
https://image.onch3.co.kr/ext_image/2017/2017_06/CH1320982_20170602_0172.jpg
CH1320982_detail_4.jpg
https://image.onch3.co.kr/ext_image/2017/2017_06/CH1320982_20170602_0173.jpg
CH1320982_detail_5.jpg
https://image.onch3.co.kr/ext_image/2017/2017_06/CH1320982_20170602_0174.jpg
CH1320982_detail_6.jpg
https://image.onch3.co.kr/ext_image/2017/2017_06/CH1320982_20170602_0175.jpg
CH1320982_detail_7.jpg
https://image.onch3.co.kr/ext_image/2017/2017_06/CH1320982_20170602_0176.jpg
CH1320982_detail_8.jpg
https://image.onch3.co.kr/ext_image/2017/2017_06/CH1320982_20170602_0177.jpg
CH1320982_detail_9.jpg
https://image.onch3.co.kr/ext_image/2017/2017_06/CH1320982_20170602_0178.jpg결과
.
.

 

이미지 폴더
이미지 폴더

 

 

 

추출 데이터 저장한 엑셀 자료
추출 데이터 저장한 엑셀 자료

 

 

댓글