이디야, 스타벅스 데이터 분석 - 23.02.14

박무연·2023년 2월 14일
0

🟣EDA

목록 보기
8/9
post-thumbnail

주제

이디야는 정말 스타벅스 근처에 매장을 오픈할까?

Step1. 스타벅스 가져오기

- 메인 페이지 열기

url = 'https://www.starbucks.co.kr/index.do'
driver = webdriver.Chrome('../driver/chromedriver.exe')
driver.get(url)

- 스토어 페이지 열기

driver.maximize_window()
storePage = driver.find_element(By.CSS_SELECTOR, '#gnb > div > nav > div > ul > li.gnb_nav03 > h2 > a')
action = ActionChains(driver)
action.move_to_element(storePage).perform()
time.sleep(1)

driver.find_element(By.CSS_SELECTOR,'#gnb > div > nav > div > ul > li.gnb_nav03 > div > div > div > ul:nth-child(1) > li.gnb_sub_ttl > a').click()
time.sleep(1.5)

# 지역검색 선택
driver.find_element(By.CSS_SELECTOR,'#container > div > form > fieldset > div > section > article.find_store_cont > article > header.loca_search > h3 > a').click()
time.sleep(1.5)

# 서울 선택
driver.find_element(By.CSS_SELECTOR, '#container > div > form > fieldset > div > section > article.find_store_cont > article > article:nth-child(4) > div.loca_step1 > div.loca_step1_cont > ul > li:nth-child(1) > a').click()
time.sleep(1.5)

# 전체 선택
driver.find_element(By.CSS_SELECTOR,'#mCSB_2_container > ul > li:nth-child(1) > a').click()

- 매장정보 가져오기

from bs4 import BeautifulSoup

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

content = soup.select('#mCSB_3 li.quickResultLstCon') 
  • 태그선택이 생각보다 어렵다
  • 여러개의 리스트 형태로 보여야 하니깐 이점을 잘 기억해두자
starbucksName = []
starbucksLat = []
starbucksLong = []
starbucksAddress = []
starbucksGu = []

for n in range(0, len(content)):
    name = content[n].select_one('strong').text.rstrip(' ')+'점'
    lat = content[n]['data-lat']
    long = content[n]['data-long']

    address_split = content[n].find('p').text.split()[:-1]
    address = ' '.join(address_split)
    #print(address)
    
    gu = address_split[1]

    starbucksName.append(name)
    starbucksLat.append(lat)
    starbucksLong.append(long)
    starbucksAddress.append(address)
    starbucksGu.append(gu)
 
 # 데이터 프레임 형태로 만들기
 starbucks = pd.DataFrame({
    '매장명' : starbucksName,
    '주소' : starbucksAddress,
    '구' : starbucksGu,
    '위도' : starbucksLat,
    '경도' : starbucksLong
})

# 구 정보 받아오기
guList = starbucks..unique().tolist()
guList
  • 더 단순하게 하기
data = []  #리스트 만들고
data.append({
	'name' : name,
    'aderess' : address,
    ...
}) # 리스트 안을 딕셔너리 형태로 만들고

pd.DataFrame(data) # 하면 데이터프레임 형태로 만들 수 있따
  • 리스트로 append 하지말고 바로

Step2. 스타벅스 가져오기

- 메인페이지 열기

url = 'https://ediya.com/'
driver = webdriver.Chrome('../driver/chromedriver.exe')
driver.get(url)

- 스토어 페이지 열기

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

# 매장찾기 클릭
driver.maximize_window()
driver.find_element(By.CSS_SELECTOR, 'body > header > div > div > div.gnb_wrap > div.top_util > ul.top_members > li.store > a').click()
time.sleep(2)

#주소찾기 클릭
driver.find_element(By.CSS_SELECTOR, '#contentWrap > div.contents > div > div.store_search_pop > ul > li:nth-child(2) > a').click()
time.sleep(2)
keyword = driver.find_element(By.CSS_SELECTOR, '#keyword').click()
time.sleep(2)


def scrapFunction(region,gu=False,*inputGu):    
    # gu : False  구 입력은 item
    # gu : True   구 입력은 inputGu
    
    # region : 입력넣을 동
    # list1 : 매장명
    # list2 : 주소
    # list3 : 구
    list1 = []
    list2 = []
    list3 = []
    dic = {}
    print(inputGu[0])
    for item in region:
        print(f'현재: {item}')
        # 클릭
        driver.find_element(By.CSS_SELECTOR, '#keyword').click()
        time.sleep(0.5)
        # 클리어
        driver.find_element(By.CSS_SELECTOR, '#keyword').clear()
        # 검색어보내기
        driver.find_element(By.CSS_SELECTOR, '#keyword').send_keys(item)
        time.sleep(3)
        # 클릭
        driver.find_element(By.CSS_SELECTOR, '#keyword_div > form > button').click()
        time.sleep(2)

        result = None
        try:
            result = driver.switch_to.alert
        except:
            pass

        if result:
            result.dismiss()
            print(f'데이터 없음 : {item}')
            continue

        else:
            page = driver.page_source
            soup = BeautifulSoup(page,'html.parser')
            contents = soup.select('#placesList dl')

            for content in contents:
                # 매장명
                name = content.select_one('dt').text
                # 주소를 가져오기 위한 작업
                address_split = content.select_one('dd').text.split(' ')
                
                if address_split[0] == '서울':
                    if address_split[-1] == '':
                        address_split.remove('')
                        print(f'remove address_split : {address_split}')


                    #print(f'address_split : {address_split}')
                    if address_split[-1][-1] == ')':
                        for idx, value in enumerate(address_split):
                            if value[0] =='(':
                                address =' '.join(address_split[:idx])
                    else:
                        address = ' '.join(address_split)

                    print(f'name: {name}')
                    print(f'ADDRESS : {address}')
                    list1.append(name)
                    list2.append(address)
                    if gu:
                        list3.append(inputGu[0])
                    else:
                        list3.append(item)
                else:
                    continue
            time.sleep(3)
    dic = {
        '매장명' : list1,
        '주소' : list2,
        '구' : list3
        }
    return dic
  • 첫 번째 : 일단 너무 어렵게 짠거 같다
  • 두 번째 : 주소가 바뀌지 않아도 parser를 해주어야 한다
  • 세 번째 : 경고창 끄기
  • 네 번째 : 서울 붙여주자

- 위키백과 가져오기

import urllib
from urllib.request import urlopen, Request

html = 'https://ko.wikipedia.org/wiki/{search_words}' 

req = Request(html.format(search_words=urllib.parse.quote('강서구_(서울특별시)'))) # 글자를 URL로 인코딩
response = urlopen(req)
response.status
soup = BeautifulSoup(response,'html.parser')
print(soup.prettify())
  • 한국어 가져오기 위해 format 사용!!!!!!

Step3. 분석하기

- 주소로 위도경도 가져오기

my_key = 
gmaps = googlemaps.Client(key=my_key)

for idx , row in tqdm_notebook(ediya.iterrows()):   
    tmp = gmaps.geocode(row['주소'], language="ko")
    print(tmp)
    lat = tmp[0].get("geometry")["location"]["lat"]
    lng = tmp[0].get("geometry")["location"]["lng"]
        
    ediya.loc[idx,'위도'] = lat
    ediya.loc[idx,'경도'] = lng

- 지도에 그리기

m = folium.Map(
    location=[37.535855, 126.991558],
    zoom_start=11,
    tiles='OpenStreetMap'
)

for idx, row in df_sum.iterrows():
    color = 'green' if row['브랜드'] == '스타벅스' else 'blue'

    folium.CircleMarker(
    location = [row['위도'],row['경도']],
    radius=3,
    fill=False,
    color = color
).add_to(m)

- 그래프

  • countplot , harh
plt.figure(figsize=(15,10))
sns.countplot(x='구', hue='브랜드', palette='Set2', data = df_sum)
plt.show()

plt.figure()
plt.barh(df_result.index, df_result['스타벅스 매장당 인구수(비율)'], label='스타벅스')
plt.barh(df_result.index, -df_result['이디야 매장당 인구수(비율)'], label='이디야')
plt.xlabel('구 별 매장당 인구수 비율')
plt.ylabel('구')
plt.xticks([-5,-2.5,0,5,10],(10,5,0,5,10))
plt.show()
  • 인구수를 괜히 들고 왔나 싶기도 하다
  • groupby 와 pivot table을 자유자재로 사용 할 수 있으면 편할거 같다

- 가설검정

  • 이건 아닌거 같으니 패스...!

Step4. 마무리

  • 다른 자치구에 매장을 오픈하는건 알겠는데 자치구 내에서 어떤가는 모르겠따,,
  • 자치구 내에서 가깝게 있는가를 알아보려면 뭐가 필요할까?
    - 1. 가깝다는 기준 : 가깝다는 기준이 없다! 이에대한 레퍼런스가 필요할듯? 현업에서도 많이 겪는 문제라고 한다.
    - 2. 스타벅스와 이디야 매장 오픈 시기 : 이디야가 근처에 있다면 스타벅스 매장 오픈 시기보다 늦어야 한다. 추가 분석을 한다면 꼭 필요하다
    - 3. 거리문제 : harvsin을 사용하여 직선거리를 구했지만 실제 도로상황을 고려해야한다. 이것을 어떤 변수로? 혹은 실제 지도 앱에서 찍히는 거리를 가져오거나? 해야하나? 이건 모르겠네.. 이것도 레퍼런스가 필요한것 같다
  • 코트는 조금 더러운거 같은데 어떻게 하면 데이터를 기반으로 근거를 제시하면 좋을지 생각해봤다는 점에서 의의를 둔다
profile
Easy day!

0개의 댓글