스타벅스 "커피가 아닌 '공간'을 판매한다"
https://kid.chosun.com/site/data/html_dir/2022/06/02/2022060202963.html
이디야·올리브영 "스벅 옆자리가 좋아"
커피 전문점 이디야커피는 한때 '스타벅스 옆자리를 사수하라'는 전략을 구사했어요. 점심시간과 같은 '피크 타임' 때 커피를 마시러 온 사람들이 자리가 없으면 자연스레 바로 옆 이디야 매장을 찾도록 한 겁니다. 저렴한 커피 가격으로 차별성도 강조했죠. 실제로 스타벅스 옆 매장의 매출은 다른 매장보다 높았다고 해요.
건강·미용 전문 매장인 CJ 올리브영도 스타벅스 커피점 인근에 위치한 모습을 쉽게 볼 수 있어요. 20~30대(代)가 주(主) 고객층이라는 점에서 서로 겹치죠.
위 기사 내용에 따르면 이디야와 올리브영은 스타벅스와 가까운 자리에 점포를 마련하여 매출을 높이는 전략을 구사한다고 합니다.
이번 포스팅에서는 그 입점 전략을 데이터를 분석해 확인해 보기 위해 먼저 스타벅스의 정보를 크롤링 하겠습니다.
스타벅스 정보 크롤링
필요한 모듈 설치 및 import
!pip install pandas
import time
import re
import pandas as pd
from selenium import webdriver
from selenium.webdriver import ActionChains # ActionChains: 마우스나 키보드와 같은 복잡한 사용자 상호작용을 시뮬레이션 하는데 사용 ex 드래그,드롭 등등
from selenium.webdriver.common.by import By # xpath string같은거 상수화 시키는 모듈
from selenium.webdriver.support.ui import WebDriverWait #실제 데이터 받을때 까지 기다림
from selenium.webdriver.support import expected_conditions as EC # 데이터 대기시켜서 불러오는거
from bs4 import BeautifulSoup
먼저 셀레니움을 사용하여 스타벅스 웹사이트에서 서울 지역 매장의 이름, 주소 위,경도를 스크래핑하여 데이터프레임으로 반환하는 함수를 정의하겠습니다.
def fetch_starbucks():
starbucks_url = 'https://www.starbucks.co.kr/index.do'
driver = webdriver.Chrome()
driver.maximize_window()
driver.get(starbucks_url)
time.sleep(1)
action = ActionChains(driver)
first_tag = driver.find_element(By.CSS_SELECTOR,'#gnb > div > nav > div > ul > li.gnb_nav03')
second_tag = driver.find_element(By.CSS_SELECTOR,'#gnb > div > nav > div > ul > li.gnb_nav03 > div > div > div > ul:nth-child(1) > li:nth-child(3) > a')
# perform() : ActionChains를 실행
action.move_to_element(first_tag).move_to_element(second_tag).click().perform()
seoul_tag = WebDriverWait(driver,10).until(
EC.element_to_be_clickable(
(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')
))
seoul_tag.click()
# 매장 정보 담기 위한 빈 리스트
store_list = []
addr_list = []
lat_list = []
lng_list = []
WebDriverWait(driver,5).until(EC.presence_of_all_elements_located((By.CLASS_NAME,'set_gugun_cd_btn')))
gu_elements = driver.find_elements(By.CLASS_NAME,'set_gugun_cd_btn')
WebDriverWait(driver,5).until(
EC.element_to_be_clickable(
(By.CSS_SELECTOR,'#mCSB_2_container > ul > li:nth-child(1) > a')
))
gu_elements[0].click()
# 매장정보가 뜨기까지 대기
WebDriverWait(driver, 5).until(EC.presence_of_all_elements_located((By.CLASS_NAME, 'quickResultLstCon')))
# 뷰티풀숲을 이용해 스크래핑 하기
req = driver.page_source
soup = BeautifulSoup(req, 'html.parser')
stores = soup.find('ul', 'quickSearchResultBoxSidoGugun').find_all('li')
for store in stores:
store_name = store.find('strong').text
store_addr = store.find('p').text
store_addr = re.sub(r'\d{4}-\d{4}$','',store_addr).strip()
store_lat = store['data-lat'] #속성으로 찾는거
store_lng = store['data-long'] #속성으로 찾는거
store_list.append(store_name)
addr_list.append(store_addr)
lat_list.append(store_lat)
lng_list.append(store_lng)
df = pd.DataFrame({
'store': store_list,
'addr': addr_list,
'lat': lat_list,
'lng': lng_list
})
driver.quit()
return df
코드 설명
Selenium 웹 드라이버 초기화
starbucks_url = 'https://www.starbucks.co.kr/index.do'
driver = webdriver.Chrome()
driver.maximize_window()
driver.get(starbucks_url)
time.sleep(1)
- starbucks_url: 스타벅스 코리아 웹사이트의 메인 URL.
- webdriver.Chrome(): Chrome 웹 드라이버를 사용하여 브라우저를 실행.
- driver.maximize_window(): 브라우저 창을 최대화.
- driver.get(): 브라우저를 열고 스타벅스 웹사이트로 이동.
- time.sleep(1): 페이지 로딩을 기다리기 위해 1초 대기.
메뉴 이동 (ActionChains 사용)
action = ActionChains(driver)
first_tag = driver.find_element(By.CSS_SELECTOR,'#gnb > div > nav > div > ul > li.gnb_nav03')
second_tag = driver.find_element(By.CSS_SELECTOR,'#gnb > div > nav > div > ul > li.gnb_nav03 > div > div > div > ul:nth-child(1) > li:nth-child(3) > a')
action.move_to_element(first_tag).move_to_element(second_tag).click().perform()
- ActionChains: Selenium에서 마우스 동작을 시뮬레이션하는 데 사용됩니다.
- move_to_element(): 특정 HTML 요소 위로 마우스를 이동.
- click(): 마우스 클릭 동작을 실행.
- perform(): 지정한 동작을 실행.
- CSS Selector: 메뉴에서 "매장 찾기"로 이동하기 위해 사용된 CSS 선택자입니다.
- first_tag: 상단 네비게이션 메뉴에서 "매장 찾기" 섹션에 해당.
- second_tag: "매장 찾기" 하위 메뉴로 이동하여 클릭.
서울 지역 클릭
seoul_tag = WebDriverWait(driver,10).until(
EC.element_to_be_clickable(
(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')
))
seoul_tag.click()
- WebDriverWait: 특정 조건이 만족될 때까지 대기.
- EC.element_to_be_clickable: 요소가 클릭 가능한 상태가 될 때까지 기다림.
- 서울 클릭: 매장 검색에서 서울 지역을 선택.
데이터 수집 준비
store_list = []
addr_list = []
lat_list = []
lng_list = []
- 각 정보를 저장할 리스트 초기화:
- store_list: 매장 이름.
- addr_list: 매장 주소.
- lat_list: 위도.
- lng_list: 경도.
구 선택
WebDriverWait(driver,5).until(EC.presence_of_all_elements_located((By.CLASS_NAME,'set_gugun_cd_btn')))
gu_elements = driver.find_elements(By.CLASS_NAME,'set_gugun_cd_btn')
gu_elements[0].click()
- find_elements: "구 선택" 버튼 목록을 가져옵니다.
- 구 클릭: 첫 번째 구(예: 강남구)를 선택.
매장 정보 로딩
WebDriverWait(driver, 5).until(EC.presence_of_all_elements_located((By.CLASS_NAME, 'quickResultLstCon')))
EC.presence_of_all_elements_located: 매장 정보가 모두 로드될 때까지 대기.
BeautifulSoup로 매장 정보 파싱
req = driver.page_source
soup = BeautifulSoup(req, 'html.parser')
stores = soup.find('ul', 'quickSearchResultBoxSidoGugun').find_all('li')
- driver.page_source: 현재 페이지의 HTML 소스 코드를 가져옵니다.
- BeautifulSoup 파싱: HTML을 분석하고 매장 정보를 추출.
- find('ul', 'quickSearchResultBoxSidoGugun'): 매장 목록을 포함한 <ul> 태그를 찾음.
- find_all('li'): 매장 정보를 포함하는 각 <li> 태그를 가져옴.
매장 정보 추출
for store in stores:
store_name = store.find('strong').text
store_addr = store.find('p').text
store_addr = re.sub(r'\d{4}-\d{4}$','',store_addr).strip()
store_lat = store['data-lat']
store_lng = store['data-long']
store_list.append(store_name)
addr_list.append(store_addr)
lat_list.append(store_lat)
lng_list.append(store_lng)
- 매장 정보 추출:
- store_name: 매장 이름 (<strong> 태그에서 추출).
- store_addr: 매장 주소 (<p> 태그에서 추출). 주소에서 전화번호 형식(0000-0000) 제거.
- store_lat, store_lng: 매장의 위도와 경도(data-lat, data-long 속성에서 추출).
- 추출한 데이터를 각각의 리스트에 저장.
DataFrame 생성
df = pd.DataFrame({
'store': store_list,
'addr': addr_list,
'lat': lat_list,
'lng': lng_list
})
pandas.DataFrame 생성:
- store: 매장 이름.
- addr: 매장 주소.
- lat: 위도.
- lng: 경도.
브라우저 종료 및 결과 반환
driver.quit()
return df
- driver.quit(): 웹 드라이버 종료.
- return df: 수집한 데이터를 DataFrame으로 반환.
starbucks_df.to_csv('starbucks_seoul.csv', index=False, encoding='utf-8-sig')
수집한 데이터를 csv파일로 저장
다음 포스팅에 이어서 크롤링으로 수집한 데이터를 이용해 커피 프랜차이즈들이 스타벅스와 가까운 자리에 점포를 마련하는지 확인해 보도록 하겠습니다
'인공지능 > 데이터분석' 카테고리의 다른 글
인공지능과 머신러닝, 딥러닝 (1) | 2025.01.29 |
---|---|
커피 프랜차이즈의 입점전략 - 스타벅스와 타 커피 프랜차이즈 데이터 분석 (1) | 2025.01.29 |
서울시 공공자전거 실시간 대여정보 (0) | 2025.01.24 |
소상공인시장진흥공단_상가정보 데이터셋 (4) | 2025.01.17 |
online Retail 데이터셋 - 캐글 (0) | 2025.01.17 |