Data Engineering/Crawling

[Crawling] NS SHOP 제품목록 크롤링

YSY^ 2020. 8. 5. 19:36

www.nsmall.com

 

ns shopping mall

 

www.nsmall.com

 

개요

  • NS SHOP에서 제품을 검색하고 제품 리스트를 크롤링 한다.
  • url : 'http://www.nsmall.com/NSSearchList?storeId=13001&langId=-9&searchTerm={}'
    • 마지막에 검색단어가 들어간다.(페이지는 따로 들어가지 않음)
  • 제품메이커, 제품정보링크, 제품명, 가격을 크롤링한다.
  • 가격은 기본적으로 할인된 가격을 크롤링하고 할인된 가격정보가 없으면 기본가격을 가지고 온다.

 

페이지 소스 살펴보기

  - 기본 : 'div.photo_list.plType2 li'
  - item_maker(메이커), : 'strong'
  - item_link(링크) : a href
  - item_name(품명) : 'span.inform.pr10 a:nth-child(2)'
  - item_price(가격) : 'dl.price dd.fc1'(할인가격이 있을 경우)
                       'dl.price dd.price'(할인 가격이 없는 경우)

 

제품리스트 크롤링 코드

base_url = 'http://www.nsmall.com/NSSearchList?storeId=13001&langId=-9&searchTerm={}'
keyword = input('검색키워드: ')
params = {
    '검색단어' : keyword,


}

#User-Agent header설정
headers = {
    'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'    
}
import requests
import pandas as pd
from bs4 import BeautifulSoup
from urllib import parse
from datetime import datetime
from selenium.webdriver import Chrome
from selenium.webdriver import ChromeOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
options = ChromeOptions()
options.add_argument('headless')

driver = Chrome()
url = base_url.format(keyword)
driver.get(url)
 result_list = []
 soup = BeautifulSoup(driver.page_source)
    item_list = soup.select('div.photo_list.plType2 li')
    error_cnt = 0
    for item in item_list:
        try:
            item_maker = item.select_one('strong').text.strip()
            item_link = item.select_one('a').get('href')
            item_name = item.select_one('span.inform.pr10 a:nth-child(2)').text.strip()
            try: #할인된 가격 정보가 있다면
                item_price = item.select_one('dl.price dd.fc1').text.strip()
            except: #할인된 가격정보가 없으면
                item_price = item.select_one('dl.price dd.price').text.strip()
            result_list.append([item_maker, item_link, item_name,item_price])
        except Exception as e:
            print(e)
            error_cnt += 1

 

페이징

nsshop의 페이징은 다른사이트와 다른데 nsshop에서는 url을 사용하여 페이징을 하지 않는다는 것이다.

2페이지로 넘어갔지만 url은 그대로이다.

대신에 자바스크립트를 이용하여 페이징을 한다.

따라서 해당 자바스크립트의 xpath를 조회하며 페이징을 한다.

//*[@id="all_search"]/div/div[6]/span/a[3] #2페이지
//*[@id="all_search"]/div/div[6]/span/a[4] #3페이지
  • 위의 xpath에서 페이지가 넘어갈때 마지막 테그 안에 있는 숫자가 변한다.
  • 2페이지면 a[3], 3페이지면 a[4]로 페이지숫자보다 1이 더 높다.
  • 따라서 selenium을 이용해 해당 페이지 버튼의 xpath를 찾은다음 click를 해주면서 페이지를 넘어간다.
  • 또한 <다음>버튼을 눌러 페이지가 11페이지로 넘어가면 테그 안에 있는 숫자가 초기화 되기 때문에 next버튼을 누를때마다 페이지를 초기화한다.

 

페이징 관련 코드

while True:

  # ......(크롤링)......

    page = page + 1
    try:        
        if page % 11 == 1: #다음버튼을 누를때
            driver.find_element_by_class_name('next').click()
            page = 2
        else: #페이지가 넘어갈때
            driver.find_element_by_xpath('//*[@id="all_search"]/div/div[6]/span/a[' + str(page) + ']').click()   
        print(page)
    except:
        break
    time.sleep(2) #페이지가 다 로드될때까지 기다린다.

 

전체코드

result_list = []

page = 2

while True:    
#     내용 가져오기

#      다음페이지 클릭
#        sleep(1)

    soup = BeautifulSoup(driver.page_source)
    item_list = soup.select('div.photo_list.plType2 li')
    error_cnt = 0
    for item in item_list:
        try:
            item_maker = item.select_one('strong').text.strip()
            item_link = item.select_one('a').get('href')
            item_name = item.select_one('span.inform.pr10 a:nth-child(2)').text.strip()
            try:
                item_price = item.select_one('dl.price dd.fc1').text.strip()
            except:
                item_price = item.select_one('dl.price dd.price').text.strip()
            result_list.append([item_maker, item_link, item_name,item_price])
        except Exception as e:
            print(e)
            error_cnt += 1
    page = page + 1
    try:        
        if page % 11 == 1:
            driver.find_element_by_class_name('next').click()
            page = 2
        else:
            driver.find_element_by_xpath('//*[@id="all_search"]/div/div[6]/span/a[' + str(page) + ']').click()   
        print(page)
    except:
        break
    time.sleep(2)

저장

date=datetime.now().strftime('%Y-%m-%d')
filename = f'NS SHOP{keyword}_조회결과_{date}'
df = pd.DataFrame(result_list, columns = ['item_maker', 'item_link', 'item_name','item_price'])
df.to_csv(filename+".csv", index=False, encoding='UTF-8')

 

#결과

728x90
반응형