학습 기록

Python 공부 기록 #7: BeautifulSoup으로 웹페이지 해부하기

  1. 목차

인트로: HTML 코드 덩어리를 어떻게 정리하지?

HTML 구조 살짝만 알아보기

BeautifulSoup 기본 사용법

실습: 명언 사이트 크롤링해보기

주의사항: 크롤링하기 전에 알아둘 것

아웃트로: 다음은 Excel 저장이다

  1. 인트로: HTML 코드 덩어리를 어떻게 정리하지?

지난 포스팅에서 requests.get()으로 웹페이지 데이터를 가져오는 데 성공했습니다.

근데 막상 print(response.text) 해보니까…

#html

뉴스

제목입니다

내용...

이런 식으로 HTML 코드가 한 덩어리로 쏟아지더라고요.

“여기서 제목만 어떻게 뽑아내지?” 하고 구글링하다가 BeautifulSoup이라는 라이브러리를 알게 됐습니다.

오늘은 이걸로 HTML에서 원하는 데이터만 쏙쏙 빼내는 방법을 정리합니다.

  1. HTML 구조 살짝만 알아보기

크롤링하려면 HTML이 어떻게 생겼는지 조금은 알아야 합니다. 전문가 수준까진 아니고, 딱 “어디에 제목이 있고, 어디에 링크가 있는지” 정도만 알면 됩니다.

브라우저에서 직접 보기

크롬에서 아무 웹페이지나 열고 F12를 누르면 개발자 도구가 뜹니다.

#html

큰 제목

뉴스 제목

뉴스 내용입니다.

링크

크롤링할 때 주로 보는 것들

태그/속성

의미

예시

,

제목

뉴스 헤드라인

문단

기사 본문

링크

다음 페이지 URL

class=“이름”

CSS 클래스 (같은 종류 묶음)

id=“이름”

고유 식별자

처음에는 복잡해 보였는데, 브라우저 개발자 도구(F12)로 실제 웹페이지 구조를 몇 번 보니까 감이 왔습니다.

  1. 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 = “”“

기사1

기사2

“”“

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’)로 속성값을 가져온다는 걸 알았습니다. 이거 알고 나니까 “다음 페이지” 버튼 주소도 뽑아낼 수 있겠더라고요!

  1. 실습: 명언 사이트 크롤링해보기

이제 진짜 웹사이트를 크롤링해 봤습니다.

연습용으로 만들어진 사이트가 있다고 해서 거기서 해봤어요.

#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개의 명언

  1. “The world as we have created it is a process…”
  • Albert Einstein
  1. “It is our choices, Harry, that show what we truly are…”
  • J.K. Rowling

이게 처음 성공했을 때 진짜 신기했어요. 웹페이지에서 데이터를 자동으로 긁어오다니!

삽질했던 부분

처음에 class='text' 이렇게 써서 아무것도 안 나왔는데,

브라우저 F12로 확인해 보니 실제로는 class="text italic"처럼 여러 개가 붙어 있더라고요.

그래서 class_='text'로만 찾으니까 잘 되었습니다.

  1. 주의사항: 크롤링하기 전에 알아둘 것

크롤링 공부하면서 찾아보니, 무작정 막 긁으면 안 된다고 하더라고요.

① 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를 쓰는 게 낫다고 하더라고요.

  1. 자주 쓰는 패턴 정리

몇 번 해보니까 이런 패턴들이 자주 나왔습니다:

#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()은 거의 필수더라고요.

  1. 정리하며

오늘은 BeautifulSoup으로 HTML에서 데이터를 추출하는 방법을 정리했습니다.

핵심만 정리:

soup.find(): 첫 번째 거 하나

soup.find_all(): 전부 다

.text: 텍스트만 꺼내기

.get(‘속성’): 링크 같은 속성 가져오기

크롤링 전에 robots.txt 확인하기

time.sleep()으로 서버 부담 줄이기

다음 포스팅에서는:

여러 페이지 자동으로 넘기면서 크롤링

크롤링한 데이터를 Excel로 저장

이 두 가지를 해보겠습니다. 드디어 “업무 자동화”랑 연결되는 느낌이네요!

혹시 설명 중에 틀린 부분이나 더 좋은 방법 있으면 알려주세요! 😊