프로그래밍/데이터 분석

[데이터 분석 심화 개념] 웹 자동화 개념 정리 4️⃣ (Beautifulsoup)

ourkofe's story 2024. 8. 23. 18:55

이번 글은 코드잇 강의를 수강하면서 배운 내용을 주로 하여 정리되어 있습니다. (코드잇 스프린트 데이터 애널리스트 트랙 1기 훈련생)


웹에서 데이터 얻기(Beautifulsoup)

 


 

크롬 개발자 도구

크롬 개발자 도구(Chrome Developer Tools)는 웹 개발자들이 웹 페이지를 분석하고 디버깅하는 데 사용하는 도구입니다.

이 도구는 웹 페이지의 구조, 스타일, 네트워크 요청 등을 실시간으로 확인하고 수정할 수 있도록 도와줍니다.

개발자 도구를 사용하면 웹 페이지가 어떻게 구성되어 있는지, 그리고 각 요소가 어떻게 스타일링되고 동작하는지 이해할 수 있습니다.

 

개발자 도구 사용법

  • Windows : 웹 페이지에서 마우스 오른쪽 버튼을 클릭한 후 "검사"를 선택하거나, 키보드에서 F12 키를 눌러 개발자 도구를 열 수 있습니다.
  • Mac : 웹 페이지에서 마우스 오른쪽 버튼을 클릭한 후 "검사"를 선택하거나, 키보드에서 Command + Option + I 키를 눌러 개발자 도구를 열 수 있습니다.

Elements 탭이란?

 

크롬 개발자 도구의 "Elements" 탭은 웹 페이지의 HTML 구조와 CSS 스타일을 실시간으로 확인하고 수정할 수 있는 곳입니다. 웹 페이지의 모든 요소를 검사하고 편집할 수 있어서, 디자인이나 레이아웃을 조정할 때 매우 유용합니다.


Elements 탭의 주요 기능

  1. HTML 구조 보기:
    • Elements 탭에서는 웹 페이지의 HTML을 트리 구조로 보여줍니다. 각 HTML 태그는 하나의 노드로 표시되며, 이 노드를 클릭하면 그 안에 포함된 하위 요소들을 볼 수 있습니다.
    • 이 트리를 통해 페이지의 어떤 부분이 어떤 HTML 코드로 구성되어 있는지 쉽게 확인할 수 있습니다.
  2. CSS 스타일 확인 및 변경:
    • 특정 HTML 요소를 클릭하면, 그 요소에 적용된 CSS 스타일이 화면 오른쪽에 표시됩니다. 이 스타일을 직접 수정할 수도 있는데, 이렇게 수정한 내용은 페이지에 즉시 반영됩니다. 예를 들어, 버튼의 색상을 바꾸거나 글자 크기를 조정하는 등의 작업을 할 수 있습니다.
  3. 실시간 편집:
    • HTML 요소나 CSS 스타일을 바로 수정해 볼 수 있습니다. 페이지의 구조나 디자인을 실험하면서 원하는 결과가 나올 때까지 조정할 수 있습니다. 이렇게 하면 브라우저에서 바로 변경 결과를 확인할 수 있기 때문에 매우 직관적입니다.
  4. 요소 선택:
    • 개발자 도구의 왼쪽 상단에 있는 선택 도구(화살표 아이콘)를 사용하면, 웹 페이지에서 직접 요소를 클릭해 선택할 수 있습니다. 예를 들어, 웹 페이지에서 특정 버튼을 클릭하면, 그 버튼이 HTML 구조에서 어디에 있는지 자동으로 찾아줍니다.

개발자 도구를 사용하는 이유

  • 디버깅: 웹 페이지가 예상대로 동작하지 않을 때, 문제를 찾아 수정할 수 있습니다.
  • 디자인 수정: 페이지의 디자인을 실시간으로 조정하고, CSS 코드를 변경해 볼 수 있습니다.
  • 학습: 웹 페이지가 어떻게 구성되어 있는지 배우고, 다른 웹 사이트의 디자인이나 코드를 분석하는 데 유용합니다.

 

Beautiful soup 라이브러리

Beautiful Soup은 파이썬에서 HTML 및 XML 파일을 파싱(parsing)하는 데 사용되는 매우 인기 있는 라이브러리입니다. 웹 스크래핑(web scraping) 작업에서 자주 사용되며, 웹 페이지에서 데이터를 추출하는 과정을 쉽게 도와줍니다.


 

Beautiful Soup의 주요 기능

  1. HTML/XML 파싱: Beautiful Soup은 HTML과 XML 문서를 파싱하여 태그, 속성, 텍스트 등을 쉽게 다룰 수 있도록 도와줍니다.
  2. 태그 탐색 및 검색: 특정 태그나 속성, 텍스트를 기준으로 원하는 요소를 검색하고 탐색할 수 있습니다.
  3. 트리 구조 탐색: HTML 문서는 트리 구조로 되어 있으며, Beautiful Soup은 부모-자식 관계, 형제 관계 등을 통해 트리를 쉽게 탐색할 수 있습니다.
  4. 데이터 수정: 파싱한 HTML 문서에서 데이터를 추출할 뿐만 아니라, 특정 요소를 수정하거나 삭제할 수도 있습니다.

Beautiful Soup 설치

 

Beautiful Soup은 pip을 사용하여 설치할 수 있습니다.

pip install beautifulsoup4

추가적으로, HTML 파싱을 위해 lxml 또는 html.parser를 사용할 수 있습니다.

lxml을 사용하려면 아래와 같이 추가 패키지를 설치해야 합니다.

pip install lxml

 

Beautiful Soup 기본 사용법

 

밑의 예시는 BeautifulSoup라이브러리를 불러와 간단한 웹 페이지를 파싱하고 데이터를 추출하는 내용을 설명하고 있습니다.

from bs4 import BeautifulSoup

# 예제 HTML
html_doc = """
<html>
<head><title>The Dormouse's story</title></head>
<body>
<h1>This is a heading</h1>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
</body>
</html>
"""

# Beautiful Soup 객체 생성
soup = BeautifulSoup(html_doc, 'html.parser')

# HTML의 title 태그 가져오기
print(soup.title)
# 혹은 title이라는 태그가 있다면 밑 방법으로도 title 태그를 가져올 수 있음
print(soup.select('title'))

# title 태그의 텍스트 가져오기
print(soup.title.string)

# 첫 번째 p 태그 가져오기
print(soup.p)

# 모든 a 태그 가져오기
for link in soup.find_all('a'):
    print(link.get('href'))

# 특정 id를 가진 태그 가져오기
print(soup.find(id="link2").string)

 


주요 메소드 및 속성

  • soup.title: <title> 태그를 반환합니다.
  • soup.title.string: <title> 태그 내의 텍스트를 반환합니다.
  • soup.find_all(name, attrs, recursive, string, limit, **kwargs): 주어진 조건에 맞는 모든 태그를 리스트로 반환합니다.
  • soup.find(name, attrs, recursive, string, **kwargs): 주어진 조건에 맞는 첫 번째 태그를 반환합니다.
  • soup.get_text(): 문서 내의 모든 텍스트를 하나의 문자열로 반환합니다.
  • soup.get('속성명'): 특정 태그의 속성 값을 가져옵니다.

원하는 태그 선택하기 : 태그 선택 방법 

  • 태그 이름으로 선택하기

특정 태그 이름을 사용하여 해당 태그를 선택할 수 있습니다. soup.find()는 첫 번째로 발견된 태그를 반환하고, soup.find_all()은 모든 해당 태그를 리스트로 반환합니다.

# 첫 번째 <p> 태그 선택
first_p_tag = soup.find('p')

# 모든 <a> 태그 선택
all_a_tags = soup.find_all('a')

  • 속성을 사용해 선택하기

태그의 속성(예: id, class, name, href 등)을 기준으로 특정 태그를 선택할 수 있습니다.

# id가 'link1'인 태그 선택
tag_with_id = soup.find(id='link1')

# class가 'sister'인 모든 <a> 태그 선택
tags_with_class = soup.find_all('a', class_='sister')

# 특정 속성을 가진 태그 선택
tag_with_attrs = soup.find('a', attrs={'href': '<http://example.com/elsie>'})

 


  • CSS 선택자를 사용해 선택하기

CSS 선택자를 이용하면 더욱 정교하게 태그를 선택할 수 있습니다. select() 메서드를 사용하면 CSS 선택자와 유사하게 태그를 선택할 수 있습니다.

# 모든 <a> 태그 중 class가 'sister'인 것 선택
css_selected_tags = soup.select('a.sister')

# id가 'link1'인 태그 선택
css_selected_tag = soup.select_one('#link1')

  • 계층 구조를 따라 선택하기

HTML 문서는 계층 구조를 이루고 있으므로, 특정 태그의 부모, 자식, 형제 태그를 선택할 수 있습니다.

# <p> 태그 안의 <b> 태그 선택
parent_tag = soup.find('p')
b_tag = parent_tag.find('b')

# 첫 번째 <a> 태그의 다음 형제 태그 선택
first_a_tag = soup.find('a')
next_sibling = first_a_tag.find_next_sibling('a')

  • 텍스트 내용을 기준으로 선택하기

태그의 텍스트 내용 자체를 기준으로 태그를 선택할 수 있습니다. 이 때 string, text 파라미터를 사용합니다.

# 텍스트가 'Elsie'인 태그 선택
tag_with_text = soup.find('a', string='Elsie')

# 특정 텍스트 패턴을 포함하는 태그 선택 (정규 표현식 사용 가능)
import re
tag_with_regex = soup.find('a', string=re.compile(r'El'))

예제: 뉴스 기사 제목 및 링크 추출

 

밑은 웹 페이지에서 뉴스 기사 제목과 링크를 추출하는 예시입니다.

from bs4 import BeautifulSoup
import requests

# 웹 페이지 가져오기
url = "<http://example.com/news>"
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')

# 뉴스 기사 제목과 링크 추출
articles = soup.find_all('h2', class_='title')

for article in articles:
    title = article.get_text()
    link = article.find('a')['href']
    print(f"Title: {title}")
    print(f"Link: {link}")

find 와 find_all 메소드

Beautiful Soup에는 필요한 태그를 선택하는 방법이 크게 .select() 메소드를 활용하는 방법과.find() 메소드를 활용하는 방법 두가지가 있습니다.

두 방법 모두 다 기능이 비슷하기 때문에 둘 중 하나만 알아도 무방하기 때문에 이번 목차에서는 find 와 find_all 메소드에 대해 설명하도록 하겠습니다.

find와 find_all 메소드는 웹 스크래핑에서 HTML 문서를 탐색하는 데 사용되는 Python의 BeautifulSoup 라이브러리의 중요한 메소드입니다.

 

find() 메소드는 select_one()과 비슷하고, find_all()메소드는 select()와 비슷합니다.

find()는 매칭되는 태그를 (최대) 하나만 가져오는데 쓰이고 find_all()은 매칭되는 태그를 모두 가져오는데 쓰이고 있습니다.(리턴값의 형식도 똑같다.)

find()는 태그 자체나 None을 리턴하고 find_all()은 리스트를 리턴합니다.


BeautifulSoup 기본 설정

 

먼저 BeautifulSoup을 사용하려면 HTML 문서를 파싱해야 합니다. 이를 위해 BeautifulSoup 객체를 생성합니다.

from bs4 import BeautifulSoup

html_content = """<html><body><h1>Title</h1><p class='content'>First paragraph.</p><p class='content'>Second paragraph.</p></body></html>"""

soup = BeautifulSoup(html_content, 'html.parser')

 

find 메소드

 

find 메소드는 HTML에서 첫 번째로 일치하는 태그를 반환합니다. 특정 태그, 클래스, ID 등을 기준으로 검색할 수 있습니다.

 

  • 태그로 찾기:
first_paragraph = soup.find('p')
print(first_paragraph)

위 코드는 첫 번째 <p> 태그를 반환합니다.

  • 클래스로 찾기:
first_content = soup.find('p', class_='content')
print(first_content)

위 코드는 클래스가 content인 첫 번째 <p> 태그를 반환합니다.

  • ID로 찾기:
first_title = soup.find('h1')
print(first_title)

위 코드는 첫 번째 <h1> 태그를 반환합니다.


find_all 메소드

 

find_all 메소드는 HTML에서 모든 일치하는 태그를 리스트 형태로 반환합니다. find와 마찬가지로 특정 태그, 클래스, ID 등을 기준으로 검색할 수 있습니다.

 

  • 태그로 찾기:
all_paragraphs = soup.find_all('p')
print(all_paragraphs)

위 코드는 모든 <p> 태그를 리스트로 반환합니다.

  • 클래스로 찾기:
all_content = soup.find_all('p', class_='content')
print(all_content)

위 코드는 클래스가 content인 모든 <p> 태그를 리스트로 반환합니다.

  • 여러 태그로 찾기:
all_links_and_paragraphs = soup.find_all(['p', 'a'])
print(all_links_and_paragraphs)

위 코드는 <p> 태그와 <a> 태그를 모두 리스트로 반환합니다.

  • 모든 태그 가져오기:
all_tags = soup.find_all(True)
print(all_tags)

위 코드는 HTML 문서의 모든 태그를 리스트로 반환합니다.


속성 사용

 

태그를 찾을 때 특정 속성을 기준으로 필터링할 수도 있습니다. 이때 속성 이름과 속성 값을 함께 지정해 줍니다.

filtered_paragraphs = soup.find_all('p', id="some-id", class_="some-class")
print(filtered_paragraphs)

위 코드는 id가 "some-id"이고, class가 "some-class"인 모든 <p> 태그를 리스트로 반환합니다.

 

속성만을 이용해 태그를 필터링할 수도 있습니다. 이 경우 태그 이름을 생략하고 속성만 지정하면 됩니다.

filtered_tags = soup.find_all(id="some-id", class_="some-class")
print(filtered_tags)

위 코드는 id가 "some-id"이고, class가 "some-class"인 모든 태그를 리스트로 반환합니다.

 

또한, 특정 속성이 존재하는지 여부로 필터링할 수도 있습니다. 속성 값 대신 True 또는 False를 사용하면 됩니다.

filtered_paragraphs = soup.find_all('p', id=True, class_=False)
print(filtered_paragraphs)

위 코드는 id 속성은 있지만 class 속성은 없는 모든 <p> 태그를 반환합니다.


중첩 태그 탐색

 

find와 find_all 메소드는 중첩 태그에 대한 문법을 별도로 제공하지 않지만, 태그 내에 중첩된 태그를 찾기 위해 메소드 체이닝을 사용할 수 있습니다.

div_tag = soup.find('div', class_='some-class')
nested_paragraphs = div_tag.find_all('p')
print(nested_paragraphs)

위 코드는 클래스가 "some-class"인 <div> 태그 내부의 모든 <p> 태그를 반환합니다.

 

또는 CSS 선택자를 사용하여 중첩된 태그를 한 번에 선택할 수도 있습니다.

nested_paragraphs = soup.select('div.some-class p')
print(nested_paragraphs)

위 코드는 클래스가 "some-class"인 <div> 태그 내부의 모든 <p> 태그를 CSS 선택자를 사용해 한 번에 반환합니다.


차이점

  • find: 첫 번째 일치하는 요소를 반환합니다.
  • find_all: 모든 일치하는 요소를 리스트로 반환합니다.

이 두 메소드는 웹 페이지에서 원하는 정보를 효율적으로 추출하는 데 유용합니다. 작은 차이점이 있지만, 올바르게 사용하면 필요한 데이터를 효과적으로 얻을 수 있습니다.


위에서 설명한 내용을 바탕으로, 웹 개발자나 데이터 분석가들이 웹 페이지의 구조를 이해하고, 원하는 데이터를 효율적으로 추출할 수 있는 방법을 배울 수 있습니다. 크롬 개발자 도구를 통해 웹 페이지의 HTML과 CSS 구조를 분석하고, Beautiful Soup 라이브러리를 활용해 필요한 정보를 손쉽게 스크래핑할 수 있습니다. 이러한 기술들은 웹 크롤링과 데이터 분석에 필수적이며, 이를 통해 다양한 데이터를 수집하고 분석하는 데 있어 강력한 도구로 활용될 수 있습니다.
감사합니다!


출처 및 참고자료 : 코드잇 사이트 강의 '웹 자동화' https://www.codeit.kr/topics/web-automation

728x90