수동으로 쿠키 추가하기
일부 웹사이트는 동적 콘텐츠를 로드하기 때문에, 단순한 GET 요청만으로는 데이터를 가져올 수 없습니다. 이 경우 브라우저에서 세션 정보를 유지하기 위해 사용되는 Cookie 값을 직접 헤더에 포함시켜 요청을 보내야 합니다.
예를 들어, https://xq.com/ 사이트에 접근하면 서버는 클라이언트에 고유한 쿠키를 할당합니다. 개발자 도구의 "Network" 탭에서 XHR 요청의 헤더를 확인하여 해당 쿠키 값을 추출할 수 있습니다.
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Referer': 'https://xq.com/',
'Cookie': 'acw_tc=2760827f17089343372121360e927a734e1bae88ad5caad4dcc5f0863acd62; '
'xq_a_token=76d4e5ee97f60e0be2c9b6c094156d577fba5c5b; '
'xq_r_token=2537d01490f74c00d7d4a37578ac84f1b7481ca1; '
'device_id=1c65e977d259e2319d0dae23aaa6f673'
}
url = 'https://xq.com/statuses/hot/listV2.json?since_id=-1&max_id=598676&size=15'
res = requests.get(url, headers=headers)
print(res.json())
쿠키 자동 추출 및 재사용
하드코딩된 쿠키는 일회성이며 만료되면 작동하지 않습니다. 보다 유연한 방법은 첫 번째 요청 시 서버가 반환하는 쿠키를 자동으로 추출해 후속 요청에 사용하는 것입니다.
import requests
base_headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Referer': 'https://xq.com/'
}
# 초기 페이지 방문하여 쿠키 획득
home_url = 'https://xq.com/'
session = requests.Session()
initial_response = session.get(home_url, headers=base_headers)
# 응답에 포함된 쿠키를 딕셔너리 형태로 저장
auth_cookies = dict(session.cookies)
# API 엔드포인트에 쿠키와 함께 요청 전송
api_url = 'https://xq.com/statuses/hot/listV2.json?since_id=-1&max_id=598676&size=15'
result = session.get(api_url, headers=base_headers, cookies=auth_cookies)
print(result.json())
Session 객체를 이용한 상태 유지
가장 효율적인 방법은 requests.Session() 인스턴스를 사용하는 것입니다. 이 객체는 내부적으로 쿠키를 자동으로 관리하며, 연결 풀링을 통해 반복 요청 시 성능을 최적화합니다.
또한 다단계 인증(예: CAPTCHA)이 필요한 사이트에서는 세션 유지가 필수적입니다. 각각의 독립된 요청은 새로운 세션을 생성하여 인증 토큰 불일치 문제를 일으킬 수 있기 때문입니다.
import requests
# 공통 헤더 정의
common_headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Referer': 'https://xq.com/'
}
# 세션 기반 요청 처리
web_session = requests.Session()
web_session.headers.update(common_headers) # 기본 헤더 설정
# 1차 요청: 홈페이지 접속 및 쿠키 발급
homepage = 'https://xq.com/'
web_session.get(homepage)
# 2차 요청: 비동기 데이터 가져오기 (자동으로 쿠키 포함)
data_endpoint = 'https://xq.com/statuses/hot/listV2.json?since_id=-1&max_id=598676&size=15'
response = web_session.get(data_endpoint)
# JSON 형식으로 파싱하여 출력
if response.status_code == 200:
data = response.json()
print(data)
SSL 인증서 오류 처리
특정 사이트(예: 12306)는 자체 서명된 SSL 인증서를 사용하여 Python에서 기본적으로 보안 검사를 실패할 수 있습니다. 이를 해결하기 위해 verify=False 옵션을 사용할 수 있으나, 보안상 주의가 필요합니다.
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
# 경고 무시 설정
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
url = "https://www.12306.cn/mormhweb/"
response = requests.get(url, verify=False, headers=common_headers)
print(response.text)
타임아웃 설정을 통한 안정성 확보
불안정한 네트워크 환경에서는 요청이 무한히 대기 상태에 빠질 수 있습니다. 이를 방지하기 위해 timeout 매개변수를 지정하면, 지정된 시간 내 응답이 없을 경우 예외를 발생시켜 프로그램의 정상적인 흐름을 유지할 수 있습니다.
try:
response = requests.get(
data_endpoint,
headers=common_headers,
timeout=5 # 5초 초과 시 Timeout 발생
)
print(response.json())
except requests.exceptions.Timeout:
print("요청 시간 초과: 서버 응답이 지연되고 있습니다.")
except requests.exceptions.RequestException as e:
print(f"요청 중 오류 발생: {e}")
이 기법은 프록시 IP 풀의 유효성 검사에도 활용할 수 있습니다. 응답 속도가 느린 프록시는 타임아웃을 통해 자동으로 제거할 수 있어 크롤링 효율을 높일 수 있습니다.