웹 스크래핑 분야에서 파이썬은 가장 인기 있는 언어 중 하나입니다. 인터넷에서 가장 큰 정보원은 무엇일까요? 바로 구글입니다! 그래서 파이썬으로 구글을 스크래핑하는 방법이 널리 쓰이는 거죠. 핵심은 검색 결과 페이지(SERP) 데이터를 자동으로 수집하여 마케팅, 경쟁사 모니터링 등에 활용하는 것입니다.
이 가이드 튜토리얼을 따라 Selenium을 사용한 Python 구글 스크래핑 방법을 배워보세요. 시작해 보겠습니다!
구글에서 어떤 데이터를 스크래핑할까요?
구글은 인터넷에서 가장 방대한 공개 데이터 소스 중 하나입니다. 구글 맵스 리뷰부터 “사람들이 또한 묻는 질문” 답변까지, 여기서 얻을 수 있는 흥미로운 정보는 무궁무진합니다:

그러나 사용자와 기업이 주로 관심을 갖는 것은 SERP 데이터입니다. SERP는 “검색 엔진 결과 페이지(Search Engine Results Page)”의 약자로, 구글과 같은 검색 엔진이 사용자 쿼리에 응답하여 반환하는 페이지를 의미합니다. 일반적으로 검색 엔진이 제안하는 웹 페이지로의 링크와 텍스트 설명이 포함된 카드 목록으로 구성됩니다.
SERP 페이지의 모습은 다음과 같습니다:

SERP 데이터는 기업이 온라인 가시성을 파악하고 경쟁사를 분석하는 데 매우 중요합니다. 사용자 선호도, 키워드 성능, 경쟁사 전략에 대한 통찰력을 제공합니다. SERP 데이터를 분석함으로써 기업은 콘텐츠를 최적화하고, SEO 순위를 개선하며, 사용자 요구를 더 잘 충족시키기 위해 마케팅 전략을 맞춤화할 수 있습니다.
이제 SERP 데이터가 매우 가치 있다는 점을 알게 되었습니다. 남은 것은 이를 수집하기 위한 올바른 도구를 선택하는 방법입니다. Python은 웹 스크래핑에 가장 적합한 프로그래밍 언어 중 하나로, 이 목적에 완벽하게 부합합니다. 하지만 수동 스크래핑에 착수하기 전에, Google 검색 결과를 스크래핑하는 가장 우수하고 빠른 옵션인 Bright Data의 SERP API를 살펴보겠습니다.
Bright Data의 SERP API 소개
수동 스크래핑 가이드를 시작하기 전에, 효율적이고 원활한 데이터 수집을 위해 Bright Data의 SERP API 활용을 고려해 보세요. SERP API는 Google, Bing, DuckDuckGo, Yandex, Baidu, Yahoo, Naver 등 모든 주요 검색 엔진의 검색 결과를 실시간으로 제공합니다. 이 강력한 도구는 Bright Data의 업계 선도적인 프록시 서비스와 고급 봇 방지 솔루션 위에 구축되어, 웹 스크래핑과 관련된 일반적인 문제 없이 안정적이고 정확한 데이터 수집을 보장합니다.
수동 스크래핑 대신 Bright Data의 SERP API를 선택해야 하는 이유
- 실시간 결과 및 높은 정확도: SERP API는 실시간 검색 엔진 결과를 제공하여 정확하고 최신 데이터를 확보할 수 있도록 합니다. 도시 단위까지의 위치 정확도를 통해 전 세계 어디에서든 실제 사용자가 보는 것과 동일한 결과를 확인할 수 있습니다.
- 고급 봇 방지 솔루션: 차단되거나 CAPTCHA 문제를 처리할 필요가 없습니다. SERP API는 자동화된 CAPTCHA 해결, 브라우저 지문 인식, 완벽한 프록시 관리를 포함하여 원활하고 중단 없는 데이터 수집을 보장합니다.
- 사용자 정의 및 확장성: API는 다양한 맞춤형 검색 매개변수를 지원하여 특정 요구 사항에 맞게 쿼리를 조정할 수 있습니다. 대량 처리를 위해 설계되어 증가하는 트래픽과 피크 시간대를 손쉽게 처리합니다.
- 사용 편의성: 간단한 API 호출로 JSON 또는 HTML 형식의 구조화된 SERP 데이터를 가져올 수 있어 기존 시스템 및 워크플로에 쉽게 통합할 수 있습니다. 응답 시간은 일반적으로 5초 미만으로 매우 빠릅니다.
- 비용 효율성: SERP API를 사용하면 운영 비용을 절감할 수 있습니다. 성공적인 요청에 대해서만 비용을 지불하며, 스크래핑 인프라 유지 관리나 서버 문제 해결에 투자할 필요가 없습니다.
지금 무료 체험을 시작하고 Bright Data SERP API의 효율성과 신뢰성을 경험해 보세요!
파이썬으로 Google SERP 스크레이퍼 구축하기
이 단계별 튜토리얼을 따라 Python으로 Google SERP 스크래핑 스크립트를 구축하는 방법을 확인하세요.
1단계: 프로젝트 설정
이 가이드를 따라하려면 컴퓨터에 Python 3이 설치되어 있어야 합니다. 설치해야 하는 경우 설치 프로그램을 다운로드하고 실행한 후 마법사를 따라 설치하세요.
이제 Python으로 Google을 스크래핑하는 데 필요한 모든 것이 준비되었습니다!
가상 환경을 포함한 Python 프로젝트를 생성하려면 아래 명령어를 사용하세요:
mkdir google-scraper
cd google-scraper
python -m venv env
google-scraper는 프로젝트의 루트 디렉터리가 됩니다.
선호하는 Python IDE에서 프로젝트 폴더를 로드하세요. PyCharm Community Edition이나 Python 확장 프로그램이 설치된 Visual Studio Code가 모두 훌륭한 선택입니다.
Linux 또는 macOS에서는 다음 명령어로 가상 환경을 활성화하세요:
./env/bin/activate
Windows에서는 대신 다음을 실행하세요:
env/Scripts/activate
일부 IDE는 가상 환경을 자동으로 인식하므로 수동으로 활성화할 필요가 없습니다.
프로젝트 폴더에 scraper.py 파일을 추가하고 아래와 같이 초기화하세요:
print("Hello, World!")
이 스크립트는 단순히 “Hello, World!” 메시지를 출력하는 간단한 예제이지만, 곧 Google 스크래핑 로직이 포함될 예정입니다.
IDE의 실행 버튼 또는 다음 명령어로 스크립트가 정상 작동하는지 확인하세요:
python scraper.py
스크립트는 다음과 같이 출력해야 합니다:
Hello, World!
잘하셨습니다! 이제 SERP 스크래핑을 위한 Python 환경을 구축하셨습니다.
Python으로 Google 스크래핑을 시작하기 전에, Python을 활용한 웹 스크래핑 가이드를 참고해 보세요.
2단계: 스크래핑 라이브러리 설치
이제 Google에서 데이터를 스크래핑하기 위한 적절한 Python 스크래핑 라이브러리를 설치할 차례입니다. 몇 가지 옵션이 있으며, 최적의 접근법을 선택하려면 대상 사이트를 분석해야 합니다. 동시에 우리가 다루는 대상은 Google이며, Google이 어떻게 작동하는지 우리 모두 알고 있습니다.
구글의 반봇 기술이 의심하지 않는 검색 URL을 생성하는 것은 복잡합니다. 구글이 사용자 상호작용을 요구한다는 것은 잘 알려진 사실입니다. 따라서 검색 엔진과 상호작용하는 가장 쉽고 효과적인 방법은 실제 사용자의 행동을 모방하는 브라우저를 통해 접근하는 것입니다.
다시 말해, 제어 가능한 브라우저에서 웹 페이지를 렌더링하려면 헤드리스 브라우저 도구가 필요합니다. 셀레니움이 완벽한 선택이 될 것입니다!
활성화된 Python 가상 환경에서 아래 명령어를 실행해 셀레늄 패키지를 설치하세요:
pip install selenium
설치 과정은 시간이 다소 소요될 수 있으니 기다려 주세요.
훌륭합니다! 방금 프로젝트의 종속성에 셀레니움을 추가했습니다.
3단계: 셀레늄 설정
scraper.py 파일에 다음 줄을 추가하여 Selenium을 임포트하세요:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
헤드리스 모드에서 Chrome 창을 제어하기 위해 Chrome WebDriver 인스턴스를 초기화하세요:
# 헤드리스 모드로 Chrome 실행 옵션
options = Options()
options.add_argument('--headless') # 로컬 개발 시 주석 처리
# 지정된 옵션으로 웹 드라이버 인스턴스 초기화
driver = webdriver.Chrome(
service=Service(),
options=options
)
참고: --headless 플래그는 Chrome이 GUI 없이 실행되도록 합니다. 스크립트가 Google 페이지에서 수행하는 작업을 확인하려면 해당 옵션을 주석 처리하세요. 일반적으로 로컬 개발 시에는 --headless 플래그를 비활성화하고, 프로덕션 환경에서는 그대로 두세요. GUI로 Chrome을 실행하면 많은 리소스를 소모하기 때문입니다.
스크립트의 마지막 줄에서 웹 드라이버 인스턴스를 닫는 것을 잊지 마세요:
driver.quit()
이제 scraper.py 파일에는 다음 내용이 포함되어야 합니다:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
# Chrome을 헤드리스 모드로 실행하기 위한 옵션
options = Options()
options.add_argument('--headless') # 로컬 개발 시 주석 처리
# 지정된 옵션으로 웹 드라이버 인스턴스 초기화
driver = webdriver.Chrome(
service=Service(),
options=options)
# 스크래핑 로직...
# 브라우저 닫기 및 리소스 해제
driver.quit()
훌륭합니다! 동적 웹사이트를 스크래핑하는 데 필요한 모든 준비가 완료되었습니다.
4단계: Google 방문
파이썬으로 Google을 스크래핑하는 첫 단계는 대상 사이트에 연결하는 것입니다. 드라이버 객체의 get() 함수를 사용하여 Chrome이 Google 홈페이지를 방문하도록 지시하세요:
driver.get("https://google.com/")
지금까지 작성한 Python SERP 스크래핑 스크립트는 다음과 같아야 합니다:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
# 헤드리스 모드로 Chrome 실행 옵션
options = Options()
options.add_argument('--headless') # 로컬 개발 시 주석 처리
# 지정된 옵션으로 웹 드라이버 인스턴스 초기화
driver = webdriver.Chrome(
service=Service(),
options=options)
# 대상 사이트에 연결
driver.get("https://google.com/")
# 스크래핑 로직...
# 브라우저 종료 및 리소스 해제
driver.quit()
헤드드 모드로 스크립트를 실행하면 quit() 명령어가 종료하기 직전, 다음과 같은 브라우저 창이 순간적으로 표시됩니다:

EU(유럽 연합) 지역에 위치한 사용자의 경우 Google 홈페이지에 아래와 같은 GDPR 팝업이 추가로 표시됩니다:

두 경우 모두 “Chrome이 자동화된 테스트 소프트웨어에 의해 제어되고 있습니다.”라는 메시지는 Selenium이 원하는 대로 Chrome을 제어하고 있음을 알려줍니다.
훌륭합니다! Selenium이 원하는 대로 Google 페이지를 열었습니다.
참고: GDPR 관련 쿠키 정책 대화상자가 표시된 경우 다음 단계를 진행하세요. 그렇지 않으면 6단계로 건너뜁니다.
단계 5: GDPR 쿠키 대화상자 처리
다음 Google GDPR 쿠키 대화상자는 IP 위치에 따라 표시되거나 표시되지 않습니다. Selenium에 프록시 서버를 통합하여 원하는 국가의 출구 IP를 선택하고 이 문제를 피하세요.
개발자 도구로 쿠키 대화 상자의 HTML 요소를 검사하세요:

코드를 확장하면 아래 CSS 선택자로 이 HTML 요소를 선택할 수 있음을 확인할 수 있습니다:
[role='dialog']
“모두 수락” 버튼을 검사하면 간단한 CSS 선택 전략으로는 선택할 수 없음을 알 수 있습니다:

자세히 살펴보면 HTML 코드의 CSS 클래스가 무작위로 생성된 것으로 보입니다. 버튼을 선택하려면 쿠키 대화상자 요소 내의 모든 버튼을 가져온 후 “모두 수락” 텍스트가 있는 버튼을 찾아야 합니다. 쿠키 대화상자 내 모든 버튼을 가져오는 CSS 선택자는 다음과 같습니다:
[role='dialog'] button
find_elements() Selenium 메서드에 CSS 선택자를 전달하여 DOM에 적용합니다. 이 메서드는 지정된 전략(이 경우 CSS 선택자 )에 따라 페이지의 HTML 요소를 선택합니다:
buttons = driver.find_elements(By.CSS_SELECTOR, "[role='dialog'] button")
위 코드가 정상 작동하려면 다음 임포트가 필요합니다:
from selenium.webdriver.common.by import By
next() 를 사용하여 “Accept all” 버튼을 찾습니다. 그런 다음 클릭합니다:
accept_all_button = next((b for b in buttons if "Accept all" in b.get_attribute("innerText")), None)
# "Accept all" 버튼이 존재할 경우 클릭
if accept_all_button is not None:
accept_all_button.click()
이 명령어는 대화 상자에서 “Accept all” 문자열을 포함하는 텍스트를 가진 <button> 요소를 찾습니다. 존재할 경우 Selenium의 click() 메서드를 호출하여 클릭합니다.
훌륭합니다! 이제 Python으로 Google 검색을 시뮬레이션하여 SERP 데이터를 수집할 준비가 되었습니다.
6단계: Google 검색 시뮬레이션
브라우저에서 Google을 열고 개발자 도구(DevTools)에서 검색 양식을 검사하세요:

CSS 클래스는 무작위로 생성된 것처럼 보이지만, 다음 CSS 선택기로 action 속성을 타겟팅하여 양식을 선택할 수 있습니다:
form[action='/search']
Selenium에서 find_element() 메서드를 통해 이 폼 요소를 가져오도록 적용하세요:
search_form = driver.find_element(By.CSS_SELECTOR, "form[action='/search']")
5단계를 건너뛴 경우 다음 임포트를 추가해야 합니다:
from selenium.webdriver.common.by import By
양식의 HTML 코드를 확장하고 검색 텍스트 영역에 집중하세요:

CSS 클래스는 무작위로 생성되지만 aria-label 값을 대상으로 선택할 수 있습니다:
textarea[aria-label='Search']
따라서 양식 내 텍스트 영역을 찾아 send_keys() 버튼을 사용하여 Google 검색어를 입력합니다:
search_form_textarea = search_form.find_element(By.CSS_SELECTOR, "textarea[aria-label='Search']")
google_search_query = "bright data"
search_form_textarea.send_keys(google_search_query)
이 경우 Google 검색어는 “bright data”가 됩니다. 다른 검색어도 가능합니다.
이제 양식 요소에 submit() 을 호출하여 양식을 제출하고 Google 검색을 시뮬레이션합니다:
search_form.submit()
구글은 지정된 쿼리를 기반으로 검색을 수행하고 원하는 SERP 페이지로 리디렉션합니다:

Selenium을 사용한 Python에서 Google 검색을 시뮬레이션하는 코드는 다음과 같습니다:
# Google 검색 양식 선택
search_form = driver.find_element(By.CSS_SELECTOR, "form[action='/search']")
# 양식 내 텍스트 영역 선택
search_form_textarea = search_form.find_element(By.CSS_SELECTOR, "textarea[aria-label='Search']")
# 텍스트 영역에 지정된 쿼리 입력
google_search_query = "bright data"
search_form_textarea.send_keys(google_search_query)
# 양식 제출 및 Google 검색 실행
search_form.submit()
자, 시작합니다! Python으로 Google을 스크래핑하여 SERP 데이터를 가져올 준비를 하세요.
7단계: 검색 결과 요소 선택
결과 섹션의 오른쪽 열을 살펴보세요:

보시다시피, 아래 CSS 선택자로 선택할 수 있는 <div> 요소입니다:
#search
구글 페이지는 동적이라는 점을 잊지 마세요. 따라서 이 요소가 페이지에 존재할 때까지 기다린 후 상호작용해야 합니다. 다음 코드로 이를 구현하세요:
search_div = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#search')))
WebDriverWait는 명시적 대기 구현을 위해 Selenium이 제공하는 특수 클래스입니다. 특히 페이지에서 특정 이벤트가 발생할 때까지 대기할 수 있게 해줍니다.
이 경우 스크립트는 #search HTML 노드가 페이지에 나타날 때까지 최대 10초 동안 대기합니다. 이를 통해 Google 검색 결과 페이지(SERP)가 원하는 대로 로드되었는지 확인할 수 있습니다.
WebDriverWait는 추가 임포트가 필요하므로 scraper.py에 다음을 추가하세요:
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
이제 Google 검색 요소를 검사해 보세요:

다시 말하지만, CSS 클래스를 통한 선택은 좋은 방법이 아닙니다. 대신 특이한 HTML 속성에 집중하세요. Google 검색 요소를 가져오기 위한 적절한 CSS 선택자는 다음과 같습니다:
div[jscontroller][lang][jsaction][data-hveid][data-ved]
이는 jscontroller, lang, jsaction, data-hveid, data-ved 속성을 모두 가진 모든 <div> 를 식별합니다.
Selenium을 통해 Python에서 모든 Google 검색 요소를 선택하려면 find_elements() 에 전달하세요:
google_search_elements = search_div.find_elements(By.CSS_SELECTOR, "div[jscontroller][lang][jsaction][data-hveid][data-ved]")
전체 로직은 다음과 같습니다:
# 검색 div가 페이지에 나타날 때까지 최대 10초 대기
# 그리고 선택
search_div = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#search')))
# SERP 내 Google 검색 요소 선택
google_search_elements = search_div.find_elements(By.CSS_SELECTOR, "div[jscontroller][lang][jsaction][data-hveid][data-ved]")
훌륭합니다! 이제 Python으로 SERP 데이터를 스크래핑하기까지 단 한 걸음 남았습니다.
8단계: SERP 데이터 추출
모든 Google SERP가 동일하게 생성되는 것은 아닙니다. 경우에 따라 페이지의 첫 번째 검색 결과는 다른 검색 요소들과 다른 HTML 코드를 가질 수 있습니다:

예를 들어, 이 경우 첫 번째 검색 결과 요소는 다음 CSS 선택자로 가져올 수 있습니다:
div.g[data-hveid]
그 외에는 Google 검색 요소가 포함하는 내용은 거의 동일합니다. 여기에는 다음이 포함됩니다:
<h3>노드에 포함된 페이지 제목.- 위
<h3>의 부모 요소인<a>요소에 포함된 특정 페이지 URL. [data-sncf='1'] <div>내의 설명.

단일 SERP에는 여러 검색 결과가 포함되므로, 스크랩한 데이터를 저장할 배열을 초기화하세요:
serp_elements = []
페이지 내 순위 추적을 위한 정수형 순위 변수도 필요합니다:
rank = 1
Python에서 Google 검색 요소를 스크래핑하는 함수를 다음과 같이 정의합니다:
def scrape_search_element(search_element, rank):
# 검색 요소 내 관심 요소를 선택하고
# 누락된 요소는 무시하며
# 데이터 추출 로직을 적용합니다
try:
title_h3 = search_element.find_element(By.CSS_SELECTOR, "h3")
title = title_h3.get_attribute("innerText")
except NoSuchElementException:
title = None
try:
# "h3" 자식 요소를 가진 "a" 요소 획득
url_a = search_element.find_element(By.CSS_SELECTOR, "a:has(> h3)")
url = url_a.get_attribute("href")
except NoSuchElementException:
url = None
try:
description_div = search_element.find_element(By.CSS_SELECTOR, "[data-sncf='1']")
description = description_div.get_attribute("innerText")
except NoSuchElementException:
description = None
# 새로운 SERP 데이터 요소를 반환
return {
'rank': rank,
'url': url,
'title': title,
'description': description
}
Google은 SERP 페이지를 자주 변경하는 경향이 있습니다. 검색 요소 내부의 노드가 사라질 수 있으므로 try ... catch 문으로 보호해야 합니다. 구체적으로, 요소가 DOM에 존재하지 않을 경우 find_element()는 NoSuchElementException 예외를 발생시킵니다.
예외를 임포트합니다:
from selenium.common import NoSuchElementException
특정 자식 요소를 가진 노드를 선택하기 위해 has() CSS 연산자를 사용한 점에 유의하세요. 자세한 내용은 공식 문서에서 확인하세요.
이제 첫 번째 검색 요소와 나머지 요소들을 scrape_search_element() 함수에 전달합니다. 그런 다음 반환된 객체들을 serp_elements 배열에 추가합니다:
# SERP의 첫 번째 요소에서 데이터 스크래핑
# (존재할 경우)
try:
first_search_element = driver.find_element(By.CSS_SELECTOR, "div.g[data-hveid]")
serp_elements.append(scrape_search_element(first_search_element, rank))
rank += 1
except NoSuchElementException:
pass
# SERP의 모든 검색 요소에서 데이터 스크래핑
for google_search_element in google_search_elements:
serp_elements.append(scrape_search_element(google_search_element, rank))
rank += 1
이 지침이 끝날 때쯤이면 serp_elements에는 관심 있는 모든 SERP 데이터가 저장될 것입니다. 터미널에 출력하여 이를 확인하세요:
print(serp_elements)
다음과 같은 결과가 출력됩니다:
[
{'rank': 1, 'url': 'https://brightdata.com/', 'title': 'Bright Data - All in One Platform for Proxies and Web Data', 'description': None},
{'rank': 2, 'url': 'https://il.linkedin.com/company/bright-data', 'title': 'Bright Data', 'description': "Bright Data는 모든 기업이 소비자와 잠재 고객과 동일한 시각으로 인터넷을 바라볼 수 있도록 지원하는 세계 최대의 데이터 수집 플랫폼입니다..."},
# 간결함을 위해 생략...
{'rank': 6, 'url': 'https://aws.amazon.com/marketplace/seller-profile?id=bf9b4324-6ee3-4eb3-9ca4-083e558d04c4', 'title': 'Bright Data - AWS Marketplace', 'description': 'Bright Data는 선도적인 데이터 수집 플랫폼으로, 고객이 수백만 웹사이트에서 구조화 및 비구조화 데이터 세트를 수집할 수 있도록 지원합니다...'},
{'rank': 7, 'url': 'https://techcrunch.com/2024/02/26/meta-drops-lawsuit-against-web-scraping-firm-bright-data-that-sold-millions-of-instagram-records/', 'title': '메타, 웹 스크래핑 업체 브라이트 데이터에 대한 소송 취하...', 'description': '2024년 2월 26일 — 메타는 몇 주 전 소송에서 핵심 주장을 기각당한 후 이스라엘 웹 스크래핑 기업 브라이트 데이터에 대한 소송을 취하했습니다.'}
]
놀랍네요! 이제 스크랩한 데이터를 CSV로 내보내기만 하면 됩니다.
9단계: 스크래핑한 데이터를 CSV로 내보내기
이제 Python으로 Google을 스크래핑하는 방법을 알았으니, 추출한 데이터를 CSV 파일로 내보내는 방법을 알아봅시다.
먼저 Python 표준 라이브러리에서 csv 패키지를 임포트합니다:
import csv
다음으로, csv 패키지를 사용하여 SERP 데이터로 출력 파일 serp_data.csv를 채웁니다:
header = ["rank", "url", "title", "description"]
with open("serp_data.csv", 'w', newline='', encoding='utf-8') as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=header)
writer.writeheader()
writer.writerows(serp_elements)
자, 이제 Google Python 스크래핑 스크립트가 완성되었습니다.
10단계: 모든 것을 합치기
다음은 scraper.py 스크립트의 최종 코드입니다:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common import NoSuchElementException
import csv
def scrape_search_element(search_element, rank):
# 검색 요소 내 관심 요소 선택 (누락된 요소 무시) 및
# 데이터 추출 로직 적용
try:
title_h3 = search_element.find_element(By.CSS_SELECTOR, "h3")
title = title_h3.get_attribute("innerText")
except NoSuchElementException:
title = None
try:
# "h3" 자식 요소를 가진 "a" 요소 획득
url_a = search_element.find_element(By.CSS_SELECTOR, "a:has(> h3)")
url = url_a.get_attribute("href")
except NoSuchElementException:
url = None
try:
description_div = search_element.find_element(By.CSS_SELECTOR, "[data-sncf='1']")
description = description_div.get_attribute("innerText")
except NoSuchElementException:
description = None
# 새로운 SERP 데이터 요소 반환
return {
'rank': rank,
'url': url,
'title': title,
'description': description
}
# 헤드리스 모드로 Chrome 실행 옵션
options = Options()
options.add_argument('--headless') # 로컬 개발 시 주석 처리
# 지정된 옵션으로 웹 드라이버 인스턴스 초기화
driver = webdriver.Chrome(
service=Service(),
options=options)
# 대상 사이트에 연결
driver.get("https://google.com/?hl=en-US")
# 쿠키 대화 상자의 버튼 선택
buttons = driver.find_elements(By.CSS_SELECTOR, "[role='dialog'] button")
accept_all_button = next((b for b in buttons if "Accept all" in b.get_attribute("innerText")), None)
# "Accept all" 버튼이 존재할 경우 클릭
if accept_all_button is not None:
accept_all_button.click()
# Google 검색 양식 선택
search_form = driver.find_element(By.CSS_SELECTOR, "form[action='/search']")
# 양식 내 텍스트 에리어 선택
search_form_textarea = search_form.find_element(By.CSS_SELECTOR, "textarea[aria-label='Search']")
# 지정된 쿼리로 텍스트 에리어 채우기
google_search_query = "bright data"
search_form_textarea.send_keys(google_search_query)
# 양식 제출 및 Google 검색 실행
search_form.submit()
# 검색 div가 페이지에 표시될 때까지 최대 10초 대기
# 그리고 선택
search_div = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#search')))
# SERP 내 Google 검색 요소 선택
google_search_elements = search_div.find_elements(By.CSS_SELECTOR, "div[jscontroller][lang][jsaction][data-hveid][data-ved]")
# 수집된 데이터 저장 위치
serp_elements = []
# 현재 순위 추적을 위한 변수
rank = 1
# SERP의 첫 번째 요소에서 데이터 스크랩 (존재할 경우)
# (존재할 경우)
try:
first_search_element = driver.find_element(By.CSS_SELECTOR, "div.g[data-hveid]")
serp_elements.append(scrape_search_element(first_search_element, rank))
rank += 1
except NoSuchElementException:
pass
# SERP의 모든 검색 요소에서 데이터 추출
for google_search_element in google_search_elements:
serp_elements.append(scrape_search_element(google_search_element, rank))
rank += 1
# 추출된 데이터를 CSV로 내보내기
header = ["순위", "URL", "제목", "설명"]
with open("serp_data.csv", 'w', newline='', encoding='utf-8') as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=header)
writer.writeheader()
writer.writerows(serp_elements)
# 브라우저 종료 및 리소스 해제
driver.quit()
와! 100줄 조금 넘는 코드로 파이썬으로 구글 검색 결과 페이지(SERP) 스크래퍼를 만들 수 있습니다.
IDE에서 실행하거나 다음 명령어로 예상 결과를 확인하세요:
python scraper.py
스크레이퍼 실행이 완료될 때까지 기다리면 프로젝트 루트 폴더에 serp_results.csv 파일이 생성됩니다. 파일을 열면 다음과 같은 내용을 확인할 수 있습니다:

축하합니다! 방금 Python으로 Google 스크래핑을 수행하셨습니다.
결론
이 튜토리얼에서는 Google에서 수집 가능한 데이터와 SERP 데이터가 가장 유용한 이유를 살펴보았습니다. 특히 Selenium을 활용해 Python으로 SERP 스크레이퍼를 구축하는 브라우저 자동화 기법을 익혔습니다.
이는 간단한 예제에서는 작동하지만, Python으로 Google을 스크래핑할 때 세 가지 주요 어려움이 있습니다:
- Google은 SERP 페이지 구조를 지속적으로 변경합니다.
- 구글은 시장에서 가장 진보된 봇 방지 솔루션을 보유하고 있습니다.
- 수많은 SERP 데이터를 병렬로 가져올 수 있는 효과적인 스크래핑 프로세스를 구축하는 것은 복잡하고 많은 비용이 듭니다.
Bright Data의 SERP API로 이러한 어려움을 잊으세요. 이 차세대 API는 모든 주요 검색 엔진의 실시간 SERP 데이터를 노출하는 일련의 엔드포인트를 제공합니다. SERP API는 최고 수준의 Bright Data프록시 서비스와 봇 방지 우회 솔루션을 기반으로 하여 여러 검색 엔진을 손쉽게 타겟팅합니다.
간단한 API 호출만으로 JSON 또는 HTML 형식의 SERP 데이터를 확보하세요. SERP API를 통해 지금 바로 무료 체험을 시작하세요!