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

🌐 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)에 대해 알아보겠습니다. 기대해주세요!
'일반IT' 카테고리의 다른 글
| 💻 시간 절약의 핵심! 주요 정보통신기반시설 취약점 자동 진단 스크립트 총정리 (4) | 2025.08.17 |
|---|---|
| 클라우드시큐리티랩 소개 (3) | 2025.08.17 |
| 🐍 파이썬 웹 크롤러/스캐너, 뼈대부터 제대로 설계하기 (3) | 2025.08.16 |
| 🗺️ 해커의 공격 지도, 웹 모의해킹은 어떤 절차로 진행될까? (2) | 2025.08.16 |
| 🛡️ "우리 웹사이트는 안전해요"… 정말 그럴까요? 웹 모의해킹이 필수인 이유 (2) | 2025.08.16 |