본문 바로가기
Python

Python으로 웹 크롤링 시작하기 - BeautifulSoup 완전 입문

by ramzee 2025. 3. 29.

0. 이 글은 누구를 위한 글인가요?

  • 인터넷에서 표, 제목, 가격 등 정보를 자동으로 수집하고 싶어요!
  • BeautifulSoup? 뭔지 모르겠어요. 처음부터 알려주세요.
  • Python으로 뉴스 제목이나 날씨 정보를 가져오고 싶어요.

가장 쉬운 예제로 웹에서 데이터를 추출하는 법을 알려드립니다.


1. 웹 크롤링이란?

  • 웹사이트의 HTML 구조를 분석해 원하는 데이터를 자동 수집하는 작업입니다.
  • BeautifulSoup + requests 조합으로 가장 많이 사용됩니다.
  • 뉴스 제목, 쇼핑몰 가격, 리뷰 등 다양한 정보 수집 가능!

2. 필요한 도구 설치

pip install requests beautifulsoup4
라이브러리 설명
requests 웹사이트 HTML 요청/다운로드
beautifulsoup4 HTML 파싱 및 원하는 태그 찾기

3. 예제 웹페이지: 네이버 뉴스 메인


4. HTML 구조 파악 방법

  1. 크롬 브라우저에서 네이버 뉴스 접속
  2. 뉴스 제목에 마우스 올린 후 오른쪽 클릭 → 검사
  3. <a> 태그 또는 <div class="cjs_t"> 등 구조 확인

5. 기본 코드 - 모든 텍스트 수집

import requests
from bs4 import BeautifulSoup

url = "https://news.naver.com/"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')

a_tags = soup.find_all('a')
for tag in a_tags:
    title = tag.get_text().strip()
    if title:
        print(title)
출력 예시
네이버
뉴스
스포츠
연예
경제
오늘의 주요 뉴스
...

→ 너무 많아서 특정 영역만 필터링할 필요가 있어요.


6. 뉴스 헤드라인만 추출하기 (div + class 기반)

# 모든 뉴스 블록 찾기
news_blocks = soup.find_all('div', class_='comp_news_feed')

# 결과 담을 리스트
news_titles = []

# 각 뉴스 블록에서 제목 추출
for block in news_blocks:
    # 메인 뉴스 제목
    main_title_tag = block.find('strong', class_='cnf_news_title')
    if main_title_tag:
        main_title = main_title_tag.get_text(strip=True)
        news_titles.append(main_title)
    
    # 하위 뉴스 제목들
    sub_title_tags = block.find_all('a', class_='cnf_news')
    for tag in sub_title_tags:
        sub_title = tag.get_text(strip=True)
        news_titles.append(sub_title)

# 출력
for idx, title in enumerate(news_titles, 1):
    print(f"{idx}. {title}")
출력 예시
1. 선관위가 편향? 尹후보 향한 비방·허위사실 삭제 가장 많았다
2. 계엄 100일, "尹의 정치적 자해"라던 조선일보 어떻게 변했나
3. 고전IP, 어디까지 바꿔도 될까…'백설공주' 실사판이 던진 질문
4. 귀여운 멸종위기종? 그 뒤엔 생태계 붕괴 있다
5. '정치 격랑'의 3월 마지막주, 의대생 복귀 데드라인
6. NASA, 여성·유색인종 달착륙 계획 철회
7. '잡아 먹거나, 잡아 먹히거나'…사냥꾼 거미, 사냥감 거미
8. 법 시행 날개 단 '재생의료'…'제2의 인보사 사태' 막아야
9. 중대본 "동시 산불로 산림 3,286㏊ 소실"…10명 사상
10. 美 그랜드캐니언 여행 한국인 여성 3명, 실종 10일째

7. 크롤링한 뉴스 → 표로 정리하기 (DataFrame)

import pandas as pd

# 뉴스 저장 리스트
news_list = []

# 블록 순회하며 제목 + 링크 추출
for block in news_blocks:
    
    # 메인 뉴스
    main_tag = block.find('a', class_='cnf_news_area')
    main_title_tag = block.find('strong', class_='cnf_news_title')
    if main_tag and main_title_tag:
        main_title = main_title_tag.get_text(strip=True)
        main_link = main_tag['href']
        news_list.append({'제목': main_title, '링크': main_link})
    
    # 하위 뉴스들
    sub_tags = block.find_all('a', class_='cnf_news')
    for tag in sub_tags:
        sub_title = tag.get_text(strip=True)
        sub_link = tag['href']
        news_list.append({'제목': sub_title, '링크': sub_link})

# DataFrame으로 정리
df = pd.DataFrame(news_list)
print(df.head())
출력 예시
제목	링크
0	선관위가 편향? 尹후보 향한 비방·허위사실 삭제 가장 많았다	https://n.news.naver.com/article/006/0000129114
1	계엄 100일, "尹의 정치적 자해"라던 조선일보 어떻게 변했나	https://n.news.naver.com/article/006/0000129112
2	고전IP, 어디까지 바꿔도 될까…'백설공주' 실사판이 던진 질문	https://n.news.naver.com/article/006/0000129113
3	귀여운 멸종위기종? 그 뒤엔 생태계 붕괴 있다	https://n.news.naver.com/article/006/0000129111
4	'정치 격랑'의 3월 마지막주, 의대생 복귀 데드라인	https://n.news.naver.com/article/584/0000031514

8. 결과 저장 (CSV)

df.to_csv('네이버_뉴스_헤드라인.csv', index=False, encoding='utf-8-sig')

→ Excel에서도 한글 안 깨지고 열 수 있어요!


9. 마무리 요약

단계 내용
웹 요청 requests.get(url)
HTML 파싱 BeautifulSoup(html, 'html.parser')
태그 찾기 find(), find_all()
텍스트 추출 get_text(strip=True)
데이터 저장 to_csv()