단순히 코딩 문법을 익히는 것을 넘어,
수집한 데이터를 어떻게 마케팅 액션과 성과로 연결할 것인가를 고민하는 것이
그로스 마케터의 진짜 역량일 것입니다.
총 5편에 걸친 웹 크롤링 시리즈의 마지막 장인 오늘은,
requests, BeautifulSoup, Selenium을 활용해 정적·동적 페이지를 넘나들며
실무 데이터를 자동화하는 최종 실습을 진행했습니다.
멋쟁이사자처럼 그로스 마케팅 부트캠프에서 보낸 19일간의 여정 중,
가장 짜릿했던 '데이터 수집 자동화'의 마침표를 지금 공유합니다.
실습 1. 구글 이미지 무한 스크롤 및 자동 다운로드 (Selenium)
마케팅 리서치를 하다 보면 경쟁사의 배너 이미지나 레퍼런스 이미지를 수백 장씩 수집해야 할 때가 있습니다.
일일이 우클릭해서 저장하는 리소스를 줄이기 위해,
'스크롤 3번 자동 다운로드' 코드를 구현했습니다.
import time
from selenium import webdriver as wb
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from urllib.request import urlretrieve
from tqdm import tqdm
# 1. 브라우저 실행 및 페이지 이동
driver = wb.Chrome()
driver.maximize_window()
time.sleep(2)
driver.get("https://search.naver.com/search.naver?...")
time.sleep(2)
- wb.Chrome(): 크롬 브라우저를 자동으로 제어할 수 있는 가상 창을 실행합니다.
- maximize_window(): 화면이 작으면 웹 요소를 찾지 못하는 오류가 발생할 수 있어 창을 최대화합니다.
- time.sleep(2): 페이지가 완전히 로딩될 때까지 컴퓨터에 2초간의 여유를 줍니다.
# 2. 예외 처리와 자동 스크롤 (try 내부)
try :
for _ in range(3) :
body = driver.find_element(By.TAG_NAME, "body")
body.send_keys(Keys.END)
time.sleep(2)
- try :: "일단 이 작업을 에러 없이 실행해봐!"라는 뜻으로, 예기치 못한 오류로 프로그램이 튕기는 것을 방지합니다.
- Keys.END: 웹페이지 바탕(<body>)을 선택해 키보드의 END 키를 누릅니다. 화면을 아래로 쓱 내리는 효과(스크롤 다운)를 주어 숨겨진 이미지를 추가로 로딩합니다. (3번 반복)
# 3. 이미지 태그 수집 및 필터링
imgs_sel = driver.find_elements(By.CSS_SELECTOR, "img._fe_image_tab_content_thumbnail_image")
imgs_src_list = [i.get_attribute("src") for i in imgs_sel]
imgs_src_list_new = [i for i in imgs_src_list if i[:5]=="https"]
- find_elements(): 네이버 이미지 중 썸네일에 해당하는 클래스명을 가진 모든 요소를 싹 긁어모읍니다.
- if i[:5]=="https": 수집된 주소 중 https로 시작하는 진짜 정상 이미지 링크만 골라내는 데이터 정제 작업입니다.
# 4. 이미지 다운로드 및 마무리 / 5. 에러 대처
for idx, img in tqdm(enumerate(imgs_src_list_new)) :
urlretrieve(img, "이미지/" + str(idx+1) + ".jpg")
time.sleep(0.5)
print("크롤링 완료!")
driver.quit()
except Exception as e :
print("에러명 :", e)
- tqdm: 다운로드 진행 상황을 시각적인 진행 바(Progress Bar)로 보여줍니다.
- urlretrieve(): 지정한 '이미지' 폴더에 1.jpg, 2.jpg 형태로 자동 저장합니다.
💡 마케터's Growth Tip (Selenium 활용기) 이미지 검색 엔진은 스크롤을 내려야 새로운 데이터가 로딩되는 '동적 페이지'가 많습니다. 마케터가 트렌드 분석을 위해 수백 장의 시각 자료를 리서치할 때, 이 스크롤 제어 코드를 활용하면 단 10초 만에 모든 이미지를 자산화할 수 있습니다.
실습 2. 서울시 데이터 광장 1~5page 대량 정보 수집 (POST 방식 & Pandas)
정적 페이지를 넘어, 눈에 보이지 않는 서버 데이터 요청 방식인
POST 문을 활용해 1페이지부터 5페이지까지의 대량 데이터를 수집하고,
이를 마케터들이 가장 사랑하는 표 형태(데이터프레임)로 시각화했습니다.
import pandas as pd
import requests as req
from bs4 import BeautifulSoup as bs
from tqdm import tqdm
url = "https://data.seoul.go.kr/dataList/datasetList.do"
# 데이터를 담을 빈 바구니 생성
titles_list, categories_list, dates_list, departements_list = [], [], [], []
# 1~5페이지 반복 데이터 수집
for i in tqdm(range(1, 6)) :
payload = {"pageIndex": i}
res_seoul = req.post(url, data=payload, headers=U_A)
soup = bs(res_seoul.text, "lxml")
- payload = {"pageIndex": i}: URL 주소가 변하지 않는 POST 방식 웹사이트에서 페이지를 전환하기 위해 핵심 파라미터(pageIndex)를 넘겨주는 마케터의 핵심 기술입니다
# 원하는 데이터 요소 선택 및 가공
title = soup.select("a.goView > strong")
category = soup.select("dl.type-b em:nth-child(2)")
date = soup.select("dd.list-statistics-info2 > span:nth-child(1)")
department = soup.select("dd.list-statistics-info2 > span:nth-child(3)")
for i in range(len(title)) :
titles_list.append(title[i].text)
categories_list.append(category[i].text)
dates_list.append(date[i].text.strip()[-10:]) # 뒤에서 10자리 (날짜만)
departements_list.append(department[i].text.strip()[19:]) # 불필요 문구 제거
- 문자열 슬라이싱 기법 ([-10:], [19:]): 크롤링 가공의 꽃입니다. 수집된 텍스트 중 불필요한 공백이나 제공부서 : 같은 앞 문구를 잘라내고 공공데이터의 '순수 부서명'과 '날짜'만 남기는 전처리 과정입니다.
# 데이터프레임(표)으로 변환 후 출력
seoul_dic = {"타이틀":titles_list, "분야":categories_list, "수정일자":dates_list, "제공부서":departements_list}
seoul_df = pd.DataFrame(seoul_dic, index=range(1, len(titles_list)+1))
seoul_df.index.name = "No."
seoul_df
마무리
5편의 시리즈를 통해 파이썬 기초부터 동적 크롤링,
그리고 데이터프레임 시각화까지 마쳤습니다.
비전공자 마케터였던 제가 19일 만에 스스로 데이터를 수집하고 정제할 수 있게 된 것은,
이론에 치우치지 않고 '진짜 마케터에게 필요한 데이터 역량'*을 쥐어준
멋쟁이사자처럼 그로스 마케팅 부트캠프 덕분이었습니다.
데이터 기반의 진짜 '그로스'를 만들어내고 싶다면 제가 몰입하고 있는 이 여정에 함께 참여해 보세요! 👇
🦁 데이터로 증명하는 그로스 마케터가 되고 싶다면?