파이썬으로 웹 크롤링 코드를 다 작성하고 기쁜 마음으로 실행 버튼을 눌렀을 때, 원하는 데이터 대신 403 Forbidden이나 406 Not Acceptable 같은 서버 에러 코드만 덩그러니 출력되는 상황을 마주해본 적 있으신가요?
어제까지만 해도 잘 돌아가던 크롤링 스크립트가 갑자기 작동을 멈추고 에러를 내뿜으면 당황스럽기 마련입니다. 내 코드에 오타가 있거나 문법이 틀린 것이 아니라, 접속 대상 웹사이트의 보안 시스템이 파이썬 프로그램의 접근을 강제로 차단(Block)했기 때문에 발생하는 현상입니다.
저 역시 초보 시절, 뉴스 기사를 크롤링하다가 갑자기 403 에러가 뜨면서 IP가 일시 차단되어 당황했던 경험이 있습니다. 오늘은 웹서버가 파이썬 프로그램을 거부하는 이유와, 브라우저인 척 위장하여 차단을 안전하게 우회하는 User-Agent 및 HTTP 헤더(Header) 설정법을 정리해 드립니다.
1. 웹서버가 파이썬을 차단하는 이유 (403 Forbidden)
웹사이트를 운영하는 서버 입장에서는 사람 사용자가 아닌 봇(Bot)이나 크롤러 프로그램이 순식간에 수천 번의 접속 요청을 보내면 서버가 마비되거나 데이터가 무단 유출될 위험을 느끼게 됩니다.
따라서 대부분의 웹서버는 들어오는 요청을 검사하여 "이 요청이 실제 사람이 크롬이나 엣지 브라우저로 들어온 것인가, 아니면 파이썬 코드(Bot)로 들어온 것인가?"를 판단합니다.
파이썬의 requests 라이브러리로 요청을 보낼 때 아무런 설정을 하지 않으면, 서버에 전달되는 기본 신분증(User-Agent) 정보에 python-requests/2.xx라고 대놓고 적혀서 전달됩니다. 서버는 이 신분증을 보자마자 "사람이 아니구나!" 하고 판단하여 차단(403 Forbidden)을 내려버리는 것입니다.
2. 해결책: User-Agent로 일반 브라우저 위장하기
차단을 피하는 가장 기본적이면서 확실한 방법은, 파이썬 코드가 보내는 요청 헤더에 실제 크롬 브라우저의 신분증(User-Agent) 값을 실어 보내는 것입니다.
내 실제 크롬 브라우저의 User-Agent 찾는 법
크롬 브라우저를 열고 주소창에
about:version을 입력합니다.화면 아래쪽 항목 중 '사용자 대리인(User Agent)'에 적힌 긴 문자열을 복사합니다.
또는 아무 웹사이트에서
F12(개발자 도구)를 누른 뒤Console탭에navigator.userAgent를 입력하면 나오는 값을 사용해도 됩니다.
보통 아래와 같은 형태의 긴 문자열로 이루어져 있습니다.
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
3. 실전 예제: Requests 및 BeautifulSoup에 헤더 적용하기
이제 복사한 User-Agent 정보를 파이썬 requests 코드의 headers 매개변수로 전달해 보겠습니다.
import requests
from bs4 import BeautifulSoup
import time
# 1. 크롬 브라우저 신분증(User-Agent) 정의
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Accept-Language": "ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7", # 언어 설정 추가
"Referer": "https://www.google.com/" # 이전 방문 페이지 위장
}
url = "https://example.com/protected-page"
try:
# 2. headers 매개변수를 포함하여 요청 전달
response = requests.get(url, headers=headers)
# HTTP 상태 코드가 200(정상)인지 확인
if response.status_code == 200:
soup = BeautifulSoup(response.text, "html.parser")
title = soup.select_one("h1").text
print(f"수집 성공! 페이지 제목: {title}")
else:
print(f"접근 실패 - 상태 코드: {response.status_code}")
except Exception as e:
print(f"오류 발생: {e}")
코드 핵심 포인트: 3대 헤더 값 설정
User-Agent: 요청 주체가 일반 PC 크롬 브라우저임을 증명합니다.Accept-Language: 한국어 웹 브라우저 사용자임을 알려주어 깨짐 없이 정상적인 한국어 페이지를 응답받게 해줍니다.Referer: 구글 검색 등을 통해 해당 페이지로 들어온 것처럼 유입 경로(참조 주소)를 만들어주어 보안 시스템의 의심을 더욱 줄여줍니다.
4. 셀레니움(Selenium)에서 차단 회피 옵션 추가하기
브라우저를 직접 띄우는 셀레니움 역시 자동화 제어 기법(Automation control)을 감지하는 보안 프로그램에 걸릴 수 있습니다.
셀레니움에서는 Options() 객체를 활용해 크롬이 '자동화 소프트웨어에 의해 제어되고 있다'는 플래그 신호를 지워주는 설정을 추가해야 합니다.
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
# 1. User-Agent 직접 지정
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
options.add_argument(f"user-agent={user_agent}")
# 2. 자동화 제어 감지 신호 비활성화 (보안 우회)
options.add_argument("--disable-blink-features=AutomationControlled")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option("useAutomationExtension", False)
driver = webdriver.Chrome(options=options)
driver.get("https://example.com")
이렇게 옵션을 지정해 주면 브라우저 상단에 뜨는 "Chrome이 자동화된 테스트 소프트웨어에 의해 제어되고 있습니다"라는 안내 띠가 사라지며, 보안 시스템의 탐지를 효과적으로 회피할 수 있습니다.
핵심요약
크롤링 중 발생하는
403 Forbidden에러는 파이썬 기본 접속 신분증(python-requests)을 보안 시스템이 차단하기 때문에 발생합니다.requests.get()호출 시 실제 크롬 브라우저의User-Agent및Referer정보를headers사전으로 전달하여 사람으로 위장해야 합니다.셀레니움 활용 시에는
AutomationControlled감지 비활성화 옵션을 추가해야 한층 강화된 방화벽 시스템을 안전하게 통과할 수 있습니다.


0 댓글