학습 기록
Python 공부 기록 #7: BeautifulSoup으로 웹페이지 해부하기
- 목차
인트로: HTML 코드 덩어리를 어떻게 정리하지?
HTML 구조 살짝만 알아보기
BeautifulSoup 기본 사용법
실습: 명언 사이트 크롤링해보기
주의사항: 크롤링하기 전에 알아둘 것
아웃트로: 다음은 Excel 저장이다
- 인트로: HTML 코드 덩어리를 어떻게 정리하지?
지난 포스팅에서 requests.get()으로 웹페이지 데이터를 가져오는 데 성공했습니다.
근데 막상 print(response.text) 해보니까…
#html
제목입니다
내용...
이런 식으로 HTML 코드가 한 덩어리로 쏟아지더라고요.
“여기서 제목만 어떻게 뽑아내지?” 하고 구글링하다가 BeautifulSoup이라는 라이브러리를 알게 됐습니다.
오늘은 이걸로 HTML에서 원하는 데이터만 쏙쏙 빼내는 방법을 정리합니다.
- HTML 구조 살짝만 알아보기
크롤링하려면 HTML이 어떻게 생겼는지 조금은 알아야 합니다. 전문가 수준까진 아니고, 딱 “어디에 제목이 있고, 어디에 링크가 있는지” 정도만 알면 됩니다.
브라우저에서 직접 보기
크롬에서 아무 웹페이지나 열고 F12를 누르면 개발자 도구가 뜹니다.
#html
큰 제목
크롤링할 때 주로 보는 것들
태그/속성
의미
예시
,
제목
뉴스 헤드라인
문단
기사 본문
링크
다음 페이지 URL
class=“이름”
CSS 클래스 (같은 종류 묶음)
id=“이름”
고유 식별자
처음에는 복잡해 보였는데, 브라우저 개발자 도구(F12)로 실제 웹페이지 구조를 몇 번 보니까 감이 왔습니다.
- BeautifulSoup 기본 사용법
BeautifulSoup은 HTML을 파이썬에서 쉽게 다룰 수 있게 해주는 라이브러리입니다. 이름이 좀 특이하죠?
(이상한 나라의 앨리스에 나오는 시 제목에서 따왔다고 합니다)
설치하기
#bash
pip install beautifulsoup4
pip install lxml # 파서(분석기)로 자주 쓰임
lxml은 HTML을 빠르게 분석해 주는 도구라고 하네요. 같이 설치하라고 해서 했습니다.
첫 번째 실습: 제목 뽑아내기
#python
from bs4 import BeautifulSoup
html = “”“
첫 번째 제목
두 번째 제목
본문입니다.
“”“
soup = BeautifulSoup(html, ‘lxml’)
첫 번째 h1 태그 찾기
first = soup.find(‘h1’)
print(first.text)
출력: 첫 번째 제목
모든 h1 태그 찾기
all_h1 = soup.find_all(‘h1’)
for title in all_h1:
print(title.text)
출력:
첫 번째 제목
두 번째 제목
이해한 내용:
soup.find(‘태그’): 첫 번째 거 하나만
soup.find_all(‘태그’): 전부 다 (리스트로 받음)
.text: 태그 안의 텍스트만 꺼내기
생각보다 간단해서 놀랐습니다!
두 번째 실습: class로 구분해서 찾기
실제 웹페이지는 같은 태그가 수십 개라서, class 이름으로 구분해야 합니다.
#python
html = “”“
뉴스 제목 1
내용 1
뉴스 제목 2
내용 2
“”“
soup = BeautifulSoup(html, ‘lxml’)
class가 “title”인 것들만 찾기
titles = soup.find_all(class_=“title”)
for t in titles:
print(t.text)
출력:
뉴스 제목 1
뉴스 제목 2
처음에 class=“title” 이렇게 써서 에러 났는데, 찾아보니 class_로 언더바를 붙여야 한다고 하더라고요.
(파이썬에서 class는 이미 쓰는 단어라서 그렇다고 합니다)
세 번째 실습: 링크(URL) 뽑아내기
#python
html = “”“
“”“
soup = BeautifulSoup(html, ‘lxml’)
links = soup.find_all(‘a’)
for link in links:
print(f“제목: {link.text}”)
print(f“주소: {link.get(‘href’)}”)
print(“—”)
**출력**:
제목: 기사1
주소: https://news.example.com/article1
제목: 기사2
주소: https://news.example.com/article2
.get(‘href’)로 속성값을 가져온다는 걸 알았습니다. 이거 알고 나니까 “다음 페이지” 버튼 주소도 뽑아낼 수 있겠더라고요!
- 실습: 명언 사이트 크롤링해보기
이제 진짜 웹사이트를 크롤링해 봤습니다.
연습용으로 만들어진 사이트가 있다고 해서 거기서 해봤어요.
#python
from bs4 import BeautifulSoup
import requests
url = “http://quotes.toscrape.com/”
response = requests.get(url, timeout=5)
if response.status_code == 200:
soup = BeautifulSoup(response.text, ‘lxml’)
명언과 작가 찾기
quotes = soup.find_all(‘span’, class_=‘text’)
authors = soup.find_all(‘small’, class_=‘author’)
print(f“총 {len(quotes)}개의 명언\n”)
for i in range(len(quotes)):
print(f“{i+1}. {quotes[i].text}“)
print(f“ - {authors[i].text}\n“)
else:
print(“실패했습니다…”)
실행 결과:
총 10개의 명언
- “The world as we have created it is a process…”
- Albert Einstein
- “It is our choices, Harry, that show what we truly are…”
- J.K. Rowling
…
이게 처음 성공했을 때 진짜 신기했어요. 웹페이지에서 데이터를 자동으로 긁어오다니!
삽질했던 부분
처음에 class='text' 이렇게 써서 아무것도 안 나왔는데,
브라우저 F12로 확인해 보니 실제로는 class="text italic"처럼 여러 개가 붙어 있더라고요.
그래서 class_='text'로만 찾으니까 잘 되었습니다.
- 주의사항: 크롤링하기 전에 알아둘 것
크롤링 공부하면서 찾아보니, 무작정 막 긁으면 안 된다고 하더라고요.
① robots.txt라는 게 있다
모든 웹사이트 주소 뒤에 /robots.txt를 붙이면 “크롤링 해도 되는 영역”이 나온다고 합니다.
#python
네이버 robots.txt 확인
print(“https://www.naver.com/robots.txt”)
User-agent: *
Disallow: /private/
Allow: /public/
Disallow로 막혀 있으면 크롤링하면 안 됩니다. 나중에 회사에서 쓸 때 조심해야겠더라고요.
Disallow: 크롤링 금지 영역
Allow: 크롤링 허용 영역
② 사이트 부하 고려하기
#python
import time
for page in range(1, 11):
url = f“https://example.com/page={page}”
response = requests.get(url)
데이터 처리…
time.sleep(2) # 2초 대기 (중요!)
1초에 100번씩 요청하면 서버가 다운될 수 있다고 합니다. 그래서 time.sleep()으로 쉬는 시간을 넣어야 한다고 하네요.
③ API가 있으면 API 사용하기
방법
장점
단점
크롤링
모든 사이트 가능
불안정, 법적 리스크
공식 API
안정적, 합법적
제한적인 데이터
찾아보니 네이버, 카카오 같은 큰 사이트들은 공식 API를 제공한다고 합니다.
크롤링보다 API가 훨씬 안정적이고 합법적이라서, 있으면 무조건 API를 쓰는 게 낫다고 하더라고요.
- 자주 쓰는 패턴 정리
몇 번 해보니까 이런 패턴들이 자주 나왔습니다:
#python
1. 첫 번째 것만
title = soup.find(‘h1’).text
2. 전부 다
all_titles = soup.find_all(‘h2’)
3. class로 찾기
news = soup.find_all(class_=‘news-title’)
4. 속성 가져오기
link = soup.find(‘a’)
url = link.get(‘href’)
5. 공백 제거 (이거 자주 씀)
text = soup.find(‘p’).text.strip()
실제로 크롤링하면 텍스트 앞뒤에 공백이나 줄바꿈(\n)이 많이 껴있어서, .strip()은 거의 필수더라고요.
- 정리하며
오늘은 BeautifulSoup으로 HTML에서 데이터를 추출하는 방법을 정리했습니다.
핵심만 정리:
soup.find(): 첫 번째 거 하나
soup.find_all(): 전부 다
.text: 텍스트만 꺼내기
.get(‘속성’): 링크 같은 속성 가져오기
크롤링 전에 robots.txt 확인하기
time.sleep()으로 서버 부담 줄이기
다음 포스팅에서는:
여러 페이지 자동으로 넘기면서 크롤링
크롤링한 데이터를 Excel로 저장
이 두 가지를 해보겠습니다. 드디어 “업무 자동화”랑 연결되는 느낌이네요!
혹시 설명 중에 틀린 부분이나 더 좋은 방법 있으면 알려주세요! 😊