호쌤
호쌤 Just For Fun

[Python 데이터 수집] 페이지번호를 활용한 쇼핑몰 상품 정보 수집

크리에이티브 커먼즈 라이선스 ITPAPER(호쌤,쭈쌤)에 의해 작성된 ≪[Python 데이터 수집] 페이지번호를 활용한 쇼핑몰 상품 정보 수집≫은(는) 크리에이티브 커먼즈 저작자표시-비영리-동일조건변경허락 4.0 국제 라이선스에 따라 이용할 수 있습니다.
이 라이선스의 범위 이외의 이용허락을 얻기 위해서는 leekh4232@gmail.com으로 문의하십시오.

[Python 데이터 수집] 페이지번호를 활용한 쇼핑몰 상품 정보 수집

웹 사이트들은 많은량의 컨텐츠를 한번에 표시할 경우 로딩 시간이 오래 걸리는 현상을 방지하기 위해 일정 수량씩 데이터를 끊어서 노출합니다. 그리고 페이지 번호라는 기능을 통해 이 데이터들에 순차적으로 접근할 수 있는 방법을 제공합니다.

page

이와 같이 페이지 번호로 구성된 컨텐츠의 경우 각 페이지의 URL 패턴을 통해 어떤 파라미터가 페이지를 구분하는데 사용되는지를 찾아 그 값을 변경해가며 반복적으로 컨텐츠를 수집해야 합니다.

이와 같이 페이지 번호로 구성된 웹 사이트의 컨텐츠를 수집하기 위해 아래와 같이 학생들에게 연습문제를 제시했습니다.

요구사항

http://itproject.ezenac.co.kr/springmyshop/product/best에서 특정 상품을 검색 한 후 모든 페이지에 대한 상품 목록을 출력하여 엑셀로 저장하시오.

단, 상품 정보의 모든 페이지를 반복적으로 수집해야 합니다.

#01 필요한 모듈 참조

1
2
3
4
import requests                     # -> 웹 페이지 요청 모듈
import urllib                       # -> URLEncoding을 위한 모듈
from bs4 import BeautifulSoup       # -> 웹 페이지 소스코드 분석 모듈
from pandas import DataFrame        # -> 데이터 프레임

#02. 수집 준비

1) 접속을 수행하기 위한 session 객체 생성

웹 페이지에서 데이터를 수집할 때 가장 처음에 위치해야 하는 코드입니다.

1
2
3
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
session = requests.Session()
session.headers.update( {'User-agent': user_agent, 'referer': None} )

2) 접근할 페이지 주소

필요한 변수들 정의

1
keyword = "팬츠"   # 검색어

기본 URL

브라우저에 표시되는 검색 결과 URL에서 ?전 까지만 지정

1
base_url = "http://itproject.ezenac.co.kr/springmyshop/product/best"

파라미터 구조

2페이지부터 3~4 페이지 정도 직접 이동하여 주소를 확인한 후 패턴을 찾는다.

page=1&keyword=검색어

1
2
base_param = {"page" : 1, "keyword" : keyword}
base_param
▶ 출력결과
1
{'page': 1, 'keyword': '팬츠'}

#03. 반복 수행으로 데이터 수집하기

개별 상품 정보들을 딕셔너리 형태로 수집한 다음 미리 준비한 빈 리스트에 추가한다.

검색 결과가 총 몇 페이지까지인지 알 수 없기 때문에 무한루프로 설정하고 반복 1회시마다 카운트값을 1씩 증가하도록 구성한다.

화면에서 전체 페이수를 의미하는 부분으로부터 전체 페이지 수를 추출하여 카운트값이 이 값보다 커지는 순간 break를 걸어 반복을 중단해야 한다.

page

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# 수집 결과를 누적할 빈 리스트
data_list = []

base_param["page"] = 1

# 직접 접속하기 전까지는 검색결과가 몇 페이지인지 모르는 상태
while True:
    #------------------------------------------
    # 1) 접속할 주소 준비하기
    #------------------------------------------
    # URLEncoding
    query = urllib.parse.urlencode(base_param)

    # 접속할 주소 확정
    content_url = base_url + "?" + query
    print(content_url)
    
    #------------------------------------------
    # 2) 페이지에 접속하기
    #------------------------------------------
    r = session.get(content_url)
    print(r)

    if r.status_code != 200:
        print("%d 에러가 발생했습니다." % r.status_code)
        continue

    r.encoding = "utf-8"  # 인코딩 설정

    # 웹 페이지의 소스코드 HTML 분석 객체로 생성
    soup = BeautifulSoup(r.text, 'html.parser')
        
    #------------------------------------------
    # 3) 상품정보 추출
    #------------------------------------------
    product_item = soup.select(".product-item")
    
    # 상품수만큼 반복
    for item in product_item:
        # 상품명
        name = item.select("h3")
        name = name[0].text.strip()
        #print(name)
        
        # 상품가격
        price = item.select(".price")
        price_str = price[0].text.strip()
        
        # 정가와 할인가가 나누어져 있는 경우
        if price_str.count("원") == 2:
            origin_price = price[0].select(".cancel-price")[0].text.strip()
            sale_price = price[0].select(".sale-price")[0].text.strip()
        # 정가만 있는 경우
        else:
            origin_price = price_str
            sale_price = None
            
        # 가격 문자열에서 불필요한 글자와 공백을 제거하고 정수로 변환
        origin_price = int(origin_price.replace("원", "").replace(",", "").strip())
        
        if sale_price:
            sale_price = int(sale_price.replace("원", "").replace(",", "").strip())
            
        #print("정가: %s, 할인가: %s" % (origin_price, sale_price))
        
        # 상품설명
        desc = item.select(".desc")[0].text.strip()
        #print(desc)
        
        product_dic = {"상품명": name, "정가": origin_price, "할인가": sale_price, "설명": desc}
        #print(product_dic)
        
        # 상품 개별 정보를 리스트에 병합
        data_list.append(product_dic)
    
    #------------------------------------------
    # 4) 전체 페이지수를 가져와서 반복 실행 여부 판단하기
    #------------------------------------------
    text_muted = soup.select(".text-muted")
    # -> (1/7Pages.)
    page_info = text_muted[0].text.strip()
    p = page_info.find("/")
    max_page = int(page_info[p+1:-7])
    
    # 페이지 번호 1 증가
    base_param["page"] += 1
    
    # 원하는 조건이 성립한 경우 처리 중단
    if base_param["page"] > max_page:
        break
▶ 출력결과
1
2
3
4
5
6
7
8
9
10
11
12
13
14
http://itproject.ezenac.co.kr/springmyshop/product/best?page=1&keyword=%ED%8C%AC%EC%B8%A0
<Response [200]>
http://itproject.ezenac.co.kr/springmyshop/product/best?page=2&keyword=%ED%8C%AC%EC%B8%A0
<Response [200]>
http://itproject.ezenac.co.kr/springmyshop/product/best?page=3&keyword=%ED%8C%AC%EC%B8%A0
<Response [200]>
http://itproject.ezenac.co.kr/springmyshop/product/best?page=4&keyword=%ED%8C%AC%EC%B8%A0
<Response [200]>
http://itproject.ezenac.co.kr/springmyshop/product/best?page=5&keyword=%ED%8C%AC%EC%B8%A0
<Response [200]>
http://itproject.ezenac.co.kr/springmyshop/product/best?page=6&keyword=%ED%8C%AC%EC%B8%A0
<Response [200]>
http://itproject.ezenac.co.kr/springmyshop/product/best?page=7&keyword=%ED%8C%AC%EC%B8%A0
<Response [200]>

#04. 수집 결과를 데이터프레임으로 변환

1
2
df = DataFrame(data_list)
df
▶ 출력결과
상품명 정가 할인가 설명
0 블린체휘트니스팬츠 25900 NaN ★휘트니스룩★텐션좋은 쫀쫀한 스판기에 기능성원단으로 부담없이 입기 좋은 휘트니스 팬...
1 플러튼휘트니스팬츠 25900 NaN 다리 라인을 매끄럽게 정리해주는 쫀쫀한 신축성에 아랫배까지 잡아주는 긴 밑위기장으로...
2 메이건7부트레이닝팬츠 15900 NaN ★휘트니스룩★ 곡선 옆라인이 바디라인을 더욱 날씬하게! 쫀쫀한 허리밴딩이 아랫배를 ...
3 루더스휘트니스치마팬츠 19900 NaN 스커트가 레이어드된 피트니스팬츠입니다. 배색라인 포인트와 쫀쫀한 텐션으로 다리라인을...
4 론사선트레이닝팬츠 21900 13140.0 ★휘트니스룩★옆라인 사선 배색 포인트로 더욱 얇아보이는 다리라인으로 만들어준답니당 ...
... ... ... ... ...
240 헬로디밴딩팬츠 9900 8910.0 신축성 좋은 허리밴딩으로 편안하게~ 9가지 다양한 컬러로 넓은 초이스~ one si...
241 코븐 4부데님팬츠 16800 NaN 은은한 워싱디자인과 밑단 컷팅스타일로 빈티지하게! size(S~XXL)
242 [인싸팬츠12탄]레트로 플라워 패턴팬츠 36800 33120.0 찰랑찰랑 시원한 느낌의 패턴 소재로 편안한 밴딩 팬츠 아이템! FREE(44~66)
243 러뷰드 린넨와이드팬츠 49800 44820.0 ★자체제작 + 루즈핏★ 허리는밴딩으로 편안하게~ 입어주면 우아한 룩으로 완성시켜주는...
244 마렌 밴딩팬츠 26800 24120.0 쫀득한 스판원단으로 다리라인에 편안하게 입기 좋은 밴딩팬츠! FREE,L size

245 rows × 4 columns

#05. 데이터프레임을 엑셀로 저장

1
df.to_excel("상품정보(%s).xlsx" % keyword, index=False)
Rating:

크리에이티브 커먼즈 라이선스 ITPAPER(호쌤,쭈쌤)에 의해 작성된 ≪[Python 데이터 수집] 페이지번호를 활용한 쇼핑몰 상품 정보 수집≫은(는) 크리에이티브 커먼즈 저작자표시-비영리-동일조건변경허락 4.0 국제 라이선스에 따라 이용할 수 있습니다.
이 라이선스의 범위 이외의 이용허락을 얻기 위해서는 leekh4232@gmail.com으로 문의하십시오.

comments powered by Disqus