LiJell's 성장기

__17.data.analyzing_Danawa_Find_Monitor (다나와 4편) 본문

Bigdata/Web Crawling

__17.data.analyzing_Danawa_Find_Monitor (다나와 4편)

All_is_LiJell 2022. 1. 23. 15:36
반응형
 

__14.data.analyzing_Danawa_Crawling (다나와 1편)

다나와 2편 전처리: https://lime-jelly.tistory.com/55 다나와 3편 시각화: https://lime-jelly.tistory.com/56 14. Danawa crawling (다나와 크롤링) 우리는 무선 청소기가 목표다! __15.data.analyzing_Danawa_..

lime-jelly.tistory.com

 

__15.data.analyzing_Danawa_preprocessing(다나와 2편)

다나와 1편 크롤링: https://lime-jelly.tistory.com/54 다나와 3편 시각화: https://lime-jelly.tistory.com/56 __14.data.analyzing_Danawa_Crawling (다나와 1편) 다나와 2편 전처리: https://lime-jelly.tisto..

lime-jelly.tistory.com

 

__16.data.analyzing_Danawa_Visualizing (다나와 3편)

다나와 1편 크롤링: https://lime-jelly.tistory.com/54 다나와 2편 전처리: https://lime-jelly.tistory.com/55 16. 다나와 데이터 시각화 __14.data.analyzing_Danawa_Crawling (다나와 1편) 다나와 2편 전처리:..

lime-jelly.tistory.com

17. 다나와 모니터 찾아보기!

17.1. 크롤링 준비

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from bs4 import BeautifulSoup

import pandas as pd
import numpy as np
import folium
import json

17.1.1. 컨트롤 할 브라우저 열기

driver = webdriver.Chrome(service = Service('../chromedriver/chromedriver.exe'))

url = 'http://search.danawa.com/dsearch.php?k1=%EB%AA%A8%EB%8B%88%ED%84%B0&module=goods&act=dispMain'
driver.get(url)

17.1.2. html parser

html = driver.page_source

soup = BeautifulSoup(html, 'html.parser')
soup

17.1.3. 원하는 정보 추출

  • 하나 뽑아보기
prod_items = soup.select('div.main_prodlist > ul.product_list > li.prod_item ')
len(prod_items)

prod_items[0].select('a.click_log_product_standard_title_')[0].text
title = prod_items[0].select('p.prod_name > a')[0].text
title
spec_list = prod_items[0].select('div.spec_list')[0].text.strip()
spec_list
price = prod_items[0].select('div.top5_price > em.num_c')[0].text
price

print(title, spec_list, price, sep = '   |||  ')
'''
LG전자 24MP400   |||  60.4cm(24인치) / 와이드(16:9) / 평면 / IPS / 광시야각 / 1920 x 1080(FHD) / 픽셀피치: 0.2745mm / 5ms(GTG) / 250cd / 1,000:1 / 최대 주사율: 75Hz / 안티글레어 / NTSC: 72% / HDMI / D-SUB / 플리커 프리 / 블루라이트 차단 / 눈부심 방지 / 게임모드 지원 / 조준선 표시 / 인풋랙 제어 / 블랙 이퀄라이저 / FreeSync / Adaptive Sync / SW 화면분할 / HDCP 지원 / 틸트(상하) / 75 x 75mm / 색약 지원 / 19W / 0.3W / 2.6kg   |||  188,900
'''
  • for 문으로 돌리기
prod_data = []

for prod_item in prod_items:
    try:
        title = prod_item.select('p.prod_name > a')[0].text
        spec_list = prod_item.select('div.spec_list')[0].text.strip()
        price = prod_item.select('div.top5_price > em.num_c')[0].text


    except:
        pass

    mylist = [title, spec_list, price]

    prod_data.append(mylist)

prod_data[0:5]
'''
[['LG전자 24MP400',
  '60.4cm(24인치) / 와이드(16:9) / 평면 / IPS / 광시야각 / 1920 x 1080(FHD) / 픽셀피치: 0.2745mm / 5ms(GTG) / 250cd / 1,000:1 / 최대 주사율: 75Hz / 안티글레어 / NTSC: 72% / HDMI / D-SUB / 플리커 프리 / 블루라이트 차단 / 눈부심 방지 / 게임모드 지원 / 조준선 표시 / 인풋랙 제어 / 블랙 이퀄라이저 / FreeSync / Adaptive Sync / SW 화면분할 / HDCP 지원 / 틸트(상하) / 75 x 75mm / 색약 지원 / 19W / 0.3W / 2.6kg',
  '188,900'],
 ['BenQ GW2780 아이케어 무결점',
  '69cm(27인치) / 와이드(16:9) / 평면 / IPS / 광시야각 / 1920 x 1080(FHD) / 픽셀피치: 0.311mm / 5ms(GTG) / 250cd / 1,000:1 / 20,000,000:1 / 최대 주사율: 60Hz / NTSC: 72% / sRGB: 100% / HDMI / DP포트 / D-SUB / 플리커 프리 / 블루라이트 차단 / 스피커 / 헤드폰 아웃 / HDCP 지원 / 무결점 정책 / 틸트(상하) / 100 x 100mm / 고정종횡비 지원 / 색약 지원 / 18W / 0.5W / 5.1kg',
  '219,000'],
 ['삼성전자 F27T350',
  '68.6cm(27인치) / 와이드(16:9) / 평면 / IPS / 광시야각 / 1920 x 1080(FHD) / 픽셀피치: 0.3114mm / 5ms(GTG) / 250cd / 1,000:1 / 최대 주사율: 75Hz / HDMI / D-SUB / 플리커 프리 / 블루라이트 차단 / 게임모드 지원 / FreeSync / 틸트(상하) / 100 x 100mm / 0.5W / 3.4kg',
  '209,000'],
 ['NLCmlQoBsf', 'NLCmlQoBsf558421', '209,000'],
 ['삼성전자 F24T350',
  '60.4cm(24인치) / 와이드(16:9) / 평면 / IPS / 광시야각 / 1920 x 1080(FHD) / 픽셀피치: 0.2745mm / 5ms(GTG) / 250cd / 1,000:1 / 최대 주사율: 75Hz / HDMI / D-SUB / 플리커 프리 / 블루라이트 차단 / 게임모드 지원 / FreeSync / 틸트(상하) / 100 x 100mm / 0.5W / 2.7kg',
  '184,000']]
'''

17.1.4. 정보추출 함수화

def get_prod_items(pro_items):
    prod_data = []

    for prod_item in prod_items:
        try:
            title = prod_item.select('p.prod_name > a')[0].text
            spec_list = prod_item.select('div.spec_list')[0].text.strip()
            price = prod_item.select('div.top5_price > em.num_c')[0].text


        except:
            pass

        mylist = [title, spec_list, price]

        prod_data.append(mylist)


    return(prod_data)  

17.1.5. 페이지 넘기기

  • 패턴 찾기
    • page 부분만 바뀌는 점을 알 수 있고
    • 제품명 또한 포함되는 것을 알 수 있다
# http://search.danawa.com/dsearch.php?k1=%EB%AA%A8%EB%8B%88%ED%84%B0+144hz&module=goods&act=dispMain
# http://search.danawa.com/dsearch.php?query=%EB%AA%A8%EB%8B%88%ED%84%B0%20144hz&originalQuery=%EB%AA%A8%EB%8B%88%ED%84%B0%20144hz&volumeType=allvs&page=2&limit=40&sort=saveDESC&list=list&boost=true&addDelivery=N&recommendedSort=Y&defaultUICategoryCode=112757&defaultPhysicsCategoryCode=860%7C13735%7C14883%7C58972&defaultVmTab=705&defaultVaTab=10714&tab=goods
# http://search.danawa.com/dsearch.php?query=%EB%AA%A8%EB%8B%88%ED%84%B0%20144hz&originalQuery=%EB%AA%A8%EB%8B%88%ED%84%B0%20144hz&volumeType=allvs&page=3&limit=40&sort=saveDESC&list=list&boost=true&addDelivery=N&recommendedSort=Y&defaultUICategoryCode=112757&defaultPhysicsCategoryCode=860%7C13735%7C14883%7C58972&defaultVmTab=705&defaultVaTab=10714&tab=goods    
  • 함수화
def get_search_page_url(keyword, page):
    url = 'http://search.danawa.com/dsearch.php?query={0}&originalQuery={0}&volumeType=allvs&page={1}&limit=40&sort=saveDESC&list=list&boost=true&addDelivery=N&recommendedSort=Y&defaultUICategoryCode=112757&defaultPhysicsCategoryCode=860%7C13735%7C14883%7C58972&defaultVmTab=705&defaultVaTab=10714&tab=goods'.format(keyword, page)
    return(url)
  • 확인
url = get_search_page_url('모니터', '1')
print(url)
'''
http://search.danawa.com/dsearch.php?query=모니터&originalQuery=모니터&volumeType=allvs&page=1&limit=40&sort=saveDESC&list=list&boost=true&addDelivery=N&recommendedSort=Y&defaultUICategoryCode=112757&defaultPhysicsCategoryCode=860%7C13735%7C14883%7C58972&defaultVmTab=705&defaultVaTab=10714&tab=goods
'''

17. 2. 크롤링 시작

# delay를 주고 진행 상황을 확인하기 위한 라이브러리 가져오기
import time
from tqdm import tqdm_notebook
keyword = '모니터'
total_page = 10
prod_data_total = []

for page in tqdm_notebook(range(1, total_page+1)):
    url = get_search_page_url(keyword, page)
    driver.get(url)

    time.sleep(5)

    html = driver.page_source
    soup = BeautifulSoup(html, 'html.parser')

    prod_items = soup.select('div.main_prodlist > ul.product_list > li.prod_item ')
    prod_item_list = get_prod_items(prod_items)

    prod_data_total.append(prod_item_list)
  • 데이터가 리스트 안에 리스트로 들어가기 때문에 벗겨내보자
total = []
for temp in prod_data_total:
    total += temp
prod_data_total = total
prod_data_total

17.3. 엑셀 저장

data = pd.DataFrame(prod_data_total)

data.columns = ['상품명', '스펙 목록', '가격']
data.to_excel('./files/danawa_monitor_crawling_result.xlsx', index =False)

17.4. preprocessing (전처리)

import pandas as pd
import numpy as np

17.4.1 불러오기

data = pd.read_excel('./files/danawa_monitor_crawling_result.xlsx')
data.info()
data.head()
'''
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 440 entries, 0 to 439
Data columns (total 3 columns):
 #   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
 0   상품명     440 non-null    object
 1   스펙 목록   440 non-null    object
 2   가격      440 non-null    object
dtypes: object(3)
memory usage: 10.4+ KB
'''
'''    상품명    스펙 목록    가격
0    LG전자 24MP400    60.4cm(24인치) / 와이드(16:9) / 평면 / IPS / 광시야각 / 1...    188,900
1    BenQ GW2780 아이케어 무결점    69cm(27인치) / 와이드(16:9) / 평면 / IPS / 광시야각 / 192...    219,000
2    삼성전자 F27T350    68.6cm(27인치) / 와이드(16:9) / 평면 / IPS / 광시야각 / 1...    209,000
3    삼성전자 F24T350    60.4cm(24인치) / 와이드(16:9) / 평면 / IPS / 광시야각 / 1...    184,000
4    삼성전자 오디세이 G5 C27G54T    68.4cm(27인치) / 와이드(16:9) / 커브드 / 1000R / VA / ...    359,000

'''

17.4.2. 회사명, 모델명 정리

# data.head()
company_list = []
product_list = []

for title in data['상품명']:
    try:

        title_info  = title.split(" ", 1)
        company_name = title_info[0]
        product_name = title_info[1]

        company_list.append(company_name)
        product_list.append(product_name)

    except:
#         pass
        company_list.append(None)
        product_list.append(None)
print(company_list[:5])
print(product_list[:5])
'''
['LG전자', 'BenQ', '삼성전자', '삼성전자', '삼성전자']
['24MP400', 'GW2780 아이케어 무결점', 'F27T350', 'F24T350', '오디세이 G5 C27G54T']
'''
spec_list = data['스펙 목록'][0].split(' / ')
spec_list[0].strip()
'''
'60.4cm(24인치)'
'''
spec_list = data['스펙 목록'][0].split(' / ')
category = spec_list[0].strip()

for spec in spec_list:
    if '주사율' in spec:
        frequency_spec = spec
    elif 'ms' in spec:
        response_spec = spec
print(frequency_spec)
print(response_spec)

frequency_value = frequency_spec.split(':')[1].strip()
response_value = response_spec.split('(')[0].strip()

print(frequency_value)
print(response_value)
'''
최대 주사율: 75Hz
5ms(GTG)
75Hz
5ms
'''
  • for 문
category_list = []
frequency_list = []
response_list = []

for spec_data in data['스펙 목록']:
    spec_list = spec_data.split(' / ')

    category = spec_list[0].strip()
    category_list.append(category)

    for spec in spec_list:
        if '주사율' in spec:
            frequency_spec = spec
        elif 'ms' in spec:
            response_spec = spec


    frequency_value = frequency_spec.split(':')[1].strip()
    response_value = response_spec.split('(')[0].strip()

    frequency_list.append(frequency_value)
    response_list.append(response_value)
print(category_list[:5])
print(frequency_list[:5])
print(response_list[:5])
'''
['60.4cm(24인치)', '69cm(27인치)', '68.6cm(27인치)', '60.4cm(24인치)', '68.4cm(27인치)']
['75Hz', '60Hz', '75Hz', '75Hz', '144Hz']
['5ms', '5ms', '5ms', '5ms', '1ms']
'''

17.4.3. 데이터 생성

pd_data = pd.DataFrame()
pd_data['카테고리'] = category_list
pd_data['회사명'] = company_list
pd_data['제품'] = product_list
pd_data['가격'] = data['가격']
pd_data['주사율'] = frequency_list
pd_data['응답속도'] = response_list
pd_data.head()
'''
    카테고리    회사명    제품    가격    주사율    응답속도
0    60.4cm(24인치)    LG전자    24MP400    188,900    75Hz    5ms
1    69cm(27인치)    BenQ    GW2780 아이케어 무결점    219,000    60Hz    5ms
2    68.6cm(27인치)    삼성전자    F27T350    209,000    75Hz    5ms
3    60.4cm(24인치)    삼성전자    F24T350    184,000    75Hz    5ms
4    68.4cm(27인치)    삼성전자    오디세이 G5 C27G54T    359,000    144Hz    1ms
'''

17.4.4. 원하는 정보 찾아보기

condition = pd_data['카테고리'] == '68.4cm(27인치)'

pd_data_final = pd_data[condition]
pd_data_final.reset_index(drop = True, inplace = True)
pd_data_final

17.5. 시각화

17.5.1. 시각화를 위한 type 변화와 필요한 정보 추출

map(lambda x: x.replace(',',''),pd_data_final['가격'])
pd_data_final['가격'] = pd_data_final['가격'].str.replace(',','').astype(int)
# 잘 안되서 이렇게 해결함.. 

pd_data_final['주사율'] = pd_data_final['주사율'].str.replace('Hz','').astype(int)
pd_data_final['응답속도'] = pd_data_final['응답속도'].str.replace('ms','').astype(int)

17.5.2. 저장후 불러오기

pd_data_final.to_excel('./files/danawa_monitor_final.xlsx', index = False)

monitor = pd.read_excel('./files/danawa_monitor_final.xlsx')
monitor
'''

카테고리    회사명    제품    가격    주사율    응답속도
0    68.4cm(27인치)    삼성전자    오디세이 G5 C27G54T    359000    144    1
1    68.4cm(27인치)    LG전자    27UL550    448900    60    5
2    68.4cm(27인치)    LG전자    27UP850    628550    60    5
3    68.4cm(27인치)    삼성전자    C27R502    207290    60    4
4    68.4cm(27인치)    삼성전자    C27R500    205630    60    4
5    68.4cm(27인치)    LG전자    27UL500    384990    60    5
6    68.4cm(27인치)    한성컴퓨터    TFG27U14F 4K IPS 리얼 144 HDR 게이밍    599000    144    1
7    68.4cm(27인치)    한성컴퓨터    TFG27F24G 리얼 240 광시야각 게이밍    249000    240    3
8    68.4cm(27인치)    한성컴퓨터    TFG27F24G 리얼 240 광시야각 게이밍    249000    240    3
9    68.4cm(27인치)    삼성전자    C27JG54    338990    144    4
10    68.4cm(27인치)    한성컴퓨터    TFG27Q14P QHD IPS 144 게이밍 캘리브레이션 무결점    349000    144    1
11    68.4cm(27인치)    큐닉스그룹    큐닉스 QHD27L REAL 165 NANO IPS 무결점    359000    165    1
12    68.4cm(27인치)    삼성전자    C27HG70    358950    144    1
'''

17.5.3. 원하는 정보 우선순위 순으로 정렬

top_list = monitor.sort_values(['응답속도','가격'], ascending = True)
top_list.head()
'''
    카테고리    회사명    제품    가격    주사율    응답속도
10    68.4cm(27인치)    한성컴퓨터    TFG27Q14P QHD IPS 144 게이밍 캘리브레이션 무결점    349000    144    1
12    68.4cm(27인치)    삼성전자    C27HG70    358950    144    1
0    68.4cm(27인치)    삼성전자    오디세이 G5 C27G54T    359000    144    1
11    68.4cm(27인치)    큐닉스그룹    큐닉스 QHD27L REAL 165 NANO IPS 무결점    359000    165    1
6    68.4cm(27인치)    한성컴퓨터    TFG27U14F 4K IPS 리얼 144 HDR 게이밍    599000    144    1
'''

17.5. 4. 가성비 찾기

price_mean_value = monitor['가격'].mean()
frequency_mean_value = monitor['주사율'].mean()
response_mean_value = monitor['응답속도'].mean()
print("가격 평균값", price_mean_value)
print("주사율 평균값", frequency_mean_value)
print("응답속도 평균값", response_mean_value)
'''
가격 평균값 364407.6923076923
주사율 평균값 128.07692307692307
응답속도 평균값 2.923076923076923
'''
condition_data = monitor[
    (monitor['가격'] <= price_mean_value) &  # 평균가보다 싸고
    (monitor['주사율'] >= frequency_mean_value) & # 주사율은 평균보다 좋으며
    (monitor['응답속도'] <= response_mean_value)] # 응답속도가 평균보다 빠른 
condition_data.reset_index(drop = True, inplace = True)
condition_data
'''

카테고리    회사명    제품    가격    주사율    응답속도
0    68.4cm(27인치)    삼성전자    오디세이 G5 C27G54T    359000    144    1
1    68.4cm(27인치)    한성컴퓨터    TFG27Q14P QHD IPS 144 게이밍 캘리브레이션 무결점    349000    144    1
2    68.4cm(27인치)    큐닉스그룹    큐닉스 QHD27L REAL 165 NANO IPS 무결점    359000    165    1
3    68.4cm(27인치)    삼성전자    C27HG70    358950    144    1
'''
from matplotlib import font_manager, rc
import matplotlib.pyplot as plt
import seaborn as sns
# import platform 

rc('font', family = 'Malgun Gothic')
plt.figure(figsize = (10, 10))
sns.scatterplot(x = '가격', y = '주사율',
               size = '응답속도', hue = monitor['회사명'],
               data = monitor, legend = False,
               sizes = (50, 200))
plt.hlines(frequency_mean_value, 0,700000,  color='red', 
           linestyle='dashed', linewidth=1)
plt.vlines(price_mean_value, 0, 300,color='blue', 
           linestyle='dashed', linewidth=1)
for index, row in monitor.iterrows():
    x = row['가격']
    y = row['주사율']
    s = row['제품'].split(' ')[0]
    plt.text(x, y, s, size=10)

plt.show()

  • 가격은 싸고 주사율은 높은 왼쪽 위 분면을 참고하는게 좋다.
  • 그래프는 노력했지만 이게 최선이였다...
반응형
Comments