본문 바로가기
일반IT

🐍 파이썬 웹 크롤러/스캐너 Requests와 BeautifulSoup 날개 달기

by gasbugs 2025. 8. 16.

안녕하세요! 👋 오늘은 웹 크롤러의 핵심적인 두 날개, RequestsBeautifulSoup 라이브러리의 구체적인 활용법을 알아보겠습니다. 이 두 가지만 잘 다뤄도 웹에 있는 대부분의 정보를 손쉽게 가져올 수 있답니다. 자, 그럼 함께 웹 세상을 탐험할 준비, 되셨나요? 🚀

 


🌐 Requests: 웹에 말을 거는 세련된 방법

Requests는 파이썬으로 HTTP 요청을 보내는 가장 인간적인(?) 방법이라고 불립니다. 복잡한 네트워크 연결이나 인코딩 문제를 신경 쓸 필요 없이, 아주 직관적으로 웹페이지에 데이터를 요청하고 받아올 수 있게 해주죠.

1. 기본 중의 기본: GET 요청 보내기

가장 흔한 웹 요청 방식인 GET은 특정 웹페이지의 정보를 가져올 때 사용됩니다.

import requests

# 타겟 URL
url = "https://paullab.co.kr/book.html"

# GET 요청 보내기
response = requests.get(url)

# 응답 상태 확인 (200이면 성공!)
print("Status Code:", response.status_code)

# 응답 내용(HTML) 확인
# .text는 UTF-8로 자동 인코딩/디코딩 해줍니다.
print("HTML Content:", response.text[:200]) # 너무 기니까 200자만 출력

 

단 세 줄의 코드로 웹페이지의 HTML을 모두 가져왔습니다! 정말 간단하죠? 😉

2. 똑똑한 크롤러의 필수 스킬: Headers와 Params

어떤 웹사이트는 요청을 보낸 주체가 브라우저인지, 아니면 우리 같은 크롤러 봇인지 확인합니다. 이럴 때 Headers에 User-Agent 정보를 담아 보내면 "저는 일반 브라우저에서 접속했어요~"라고 속일(?) 수 있습니다.

Params는 URL에 쿼리 문자열(Query String)을 추가할 때 유용합니다. 예를 들어 ?page=2&sort=popular 같은 부분을 딕셔너리 형태로 깔끔하게 전달할 수 있죠.

import requests

url = "https://search.example.com/search"

# 헤더 설정: "저는 크롬 브라우저입니다."
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
}

# 파라미터 설정: 검색어는 'python', 페이지는 2
params = {
    "q": "python",
    "page": 2
}

# 헤더와 파라미터를 함께 보내기
response = requests.get(url, headers=headers, params=params)

# 실제 요청된 URL 확인
print("Requested URL:", response.url)
# 결과: https://search.example.com/search?q=python&page=2

3. 로그인, 세션(Session)으로 해결!

로그인이 필요한 페이지를 크롤링해야 할 때가 있습니다. 이때는 세션(Session) 객체를 사용하면 됩니다. 세션 객체는 로그인 상태(쿠키 등)를 계속 유지해주기 때문에, 매번 로그인 정보를 보내지 않아도 됩니다. 🍪

import requests

# 세션 객체 생성
session = requests.Session()

# 로그인 정보 (예시)
login_data = {
    "username": "my_id",
    "password": "my_password"
}

# 1. 로그인 페이지에 POST 요청으로 로그인
session.post("https://example.com/login", data=login_data)

# 2. 로그인 후 접근 가능한 마이페이지에 GET 요청
# 세션이 쿠키를 기억하고 있으므로 로그인 상태가 유지됨
mypage_response = session.get("https://example.com/mypage")

print(mypage_response.text)

🥣 BeautifulSoup: 복잡한 HTML 속 보물찾기

Requests로 HTML을 성공적으로 가져왔다면, 이제 BeautifulSoup 차례입니다. 이 라이브러리는 HTML 코드(죽)를 보기 좋고 다루기 쉬운 수프(Soup)로 만들어, 우리가 원하는 정보만 쏙쏙 골라낼 수 있게 도와줍니다.

1. 수프 만들기 (객체 생성)

먼저, 가져온 HTML 텍스트를 BeautifulSoup 객체로 만들어야 합니다. 이때 어떤 파서(parser)를 사용할지 지정해주는 것이 좋습니다. html.parser는 파이썬 기본 파서로, 별도 설치 없이 사용할 수 있습니다.

from bs4 import BeautifulSoup

# Requests로 가져온 HTML 텍스트 (response.text)
html_doc = """

 

2. 원하는 요소 찾기: find()와 find_all()

가장 기본적이고 강력한 기능입니다.

  • find('태그명'): 조건에 맞는 첫 번째 태그 하나만 찾아줍니다.
  • find_all('태그명'): 조건에 맞는 모든 태그를 리스트 형태로 반환합니다.
# 첫 번째 <a> 태그 찾기
first_link = soup.find('a')
print("First link:", first_link)

# 모든 <a> 태그 찾기
all_links = soup.find_all('a')
print("All links:")
for link in all_links:
    print(f"  - {link}")

 

3. 속성으로 더 정밀하게 찾기

태그의 속성(attribute)을 이용하면 더 정확하게 원하는 요소를 찾을 수 있습니다.

# id가 'link3'인 태그 찾기
link_tillie = soup.find('a', id='link3')
print("ID link3:", link_tillie)

# class가 'sister'인 모든 태그 찾기
sisters = soup.find_all('a', class_='sister') # class는 파이썬 예약어이므로 _를 붙입니다.
print("Sisters:")
for sister in sisters:
    print(f"  - {sister}")

 

4. CSS 선택자(Selector)로 한번에! select()

CSS에 익숙하다면 select() 메서드가 훨씬 편할 수 있습니다. 마치 CSS에서 요소를 선택하듯, 복잡한 조건도 간결하게 표현할 수 있습니다.

  • select_one('선택자'): 조건에 맞는 첫 번째 요소 하나만 찾습니다. (find와 유사)
  • select('선택자'): 조건에 맞는 모든 요소를 리스트로 반환합니다. (find_all과 유사)
# <p> 태그 안의 class가 'sister'인 모든 요소 선택
sisters_in_p = soup.select('p .sister')
print("Sisters in <p>:", sisters_in_p)

# id가 'link1'인 요소 선택
link_elsie = soup.select_one('#link1')
print("ID link1:", link_elsie)

 

5. 찾은 요소에서 정보 추출하기

원하는 태그를 찾았다면, 이제 그 안의 텍스트나 속성값을 꺼내야 합니다.

  • 텍스트 추출: .get_text() 또는 .text 속성
  • 속성값 추출: ['속성명'] (딕셔너리처럼)
# id가 link1인 <a> 태그에서 텍스트와 href 속성값 추출
link_elsie = soup.select_one('#link1')

# 텍스트
elsie_name = link_elsie.get_text()
print("Name:", elsie_name) # 출력: Elsie

# href 속성값
elsie_url = link_elsie['href']
print("URL:", elsie_url) # 출력: http://example.com/elsie

🧩 최종 조합: Requests로 가져오고 BeautifulSoup으로 파싱하기

이제 두 라이브러리를 합쳐서 실전처럼 사용해 봅시다. 특정 웹페이지의 모든 뉴스 기사 제목을 가져오는 예제입니다.

import requests
from bs4 import BeautifulSoup

# 1. Requests로 웹페이지 가져오기
url = "https://news.example.com"
response = requests.get(url)
response.raise_for_status() # 요청이 실패하면 에러 발생

# 2. BeautifulSoup으로 파싱 준비
soup = BeautifulSoup(response.text, "html.parser")

# 3. CSS 선택자로 모든 기사 제목 찾기
# (실제 사이트의 HTML 구조에 맞게 선택자를 지정해야 합니다)
# 예: 기사 제목이 <a class="news_title"> 안에 있을 경우
news_titles = soup.select("a.news_title")

# 4. 결과 출력
print(f"--- {url} 뉴스 제목 ---")
for title in news_titles:
    print(title.get_text().strip()) # .strip()으로 양옆 공백 제거

 

이처럼 Requests는 웹 세계의 문을 여는 열쇠, BeautifulSoup은 그 안에서 보물을 찾는 지도와 같습니다. 이 두 가지 도구를 자유자재로 사용할 수 있다면 여러분은 이미 훌륭한 데이터 탐험가입니다! 🧭

 

다음 편에서는 조금 더 고급 주제인 동적 웹 페이지 크롤링(Selenium)에 대해 알아보겠습니다. 기대해주세요!