BeautifulSoup의 find() 및 find_all(): 2026 가이드

Python에서 BeautifulSoup의 find() 및 find_all() 메서드를 활용하여 클래스, ID, 텍스트, 속성별로 웹 데이터를 효율적으로 추출하는 방법을 익히세요.
4 분 읽기
How To Use BeautifulSoup’s find and find_all blog image

find()find_all()BeautifulSoup을 이용한 웹 스크래핑에 필수적인 메서드로, HTML에서 데이터를 추출하는 데 도움을 줍니다. find() 메서드는 지정된 조건에 맞는 첫 번째 요소를 반환합니다(예: find("div") 는 페이지의 첫 번째 div를 가져옴). 일치하는 요소가 없으면 None을 반환합니다. 반면 find_all()은 일치하는 모든 요소를 찾아 리스트 형태로 반환하므로, 모든 div 태그처럼 여러 요소를 추출하는 데 적합합니다. BeautifulSoup으로 웹 스크래핑을 시작하기 전에 Requests와 BeautifulSoup이 모두 설치되었는지 확인하세요.

의존성 설치

pip install requests
pip install beautifulsoup4

find()

find() 함수를 알아봅시다. 아래 예시에서는 Quotes To Scrape와 Fake Store API를 사용하여 페이지의 요소를 찾을 것입니다. 이 두 사이트는 스크래핑을 위해 제작되었습니다. 변경 사항이 거의 없어 학습에 완벽합니다.

클래스로 찾기

클래스를 사용하여 요소를 찾으려면 class_ 키워드를 사용합니다. 왜 class가 아니라 class_인지 궁금할 수 있습니다. Python에서 class는 사용자 정의 데이터 유형을 생성하는 데 사용되는 키워드입니다. class_의 언더스코어는 이 키워드가 코드와 충돌하는 것을 방지합니다.

아래 예제는 class: quote를 가진 첫 번째 div를 찾습니다.

import requests
from bs4 import BeautifulSoup

response = requests.get("https://quotes.toscrape.com")

soup = BeautifulSoup(response.text, "html.parser")

first_quote = soup.find("div", class_="quote")
print(first_quote.text)

출력 결과는 다음과 같습니다.

“우리가 창조한 세상은 우리의 사고 과정이다. 사고를 바꾸지 않고서는 세상을 바꿀 수 없다.”
앨버트 아인슈타인
(about)


            Tags:
            
change
deep-thoughts
thinking
world

ID로 찾기

스크래핑 시에는 일반적으로 요소의 ID를 사용하여 찾는 경우도 많습니다. 아래 예시에서는 id 인수를 사용하여 페이지의 메뉴를 찾습니다. 여기서 우리는 ID를 사용하여 페이지의 메뉴를 찾습니다.

import requests
from bs4 import BeautifulSoup

response = requests.get("https://fakestoreapi.com")

soup = BeautifulSoup(response.text, "html.parser")

ul = soup.find("ul", id="menu")

print(ul.text)

추출한 메뉴를 터미널에 출력한 결과는 다음과 같습니다.

홈
문서
GitHub
커피 한 잔 사주세요

텍스트로 찾기

텍스트를 사용해 항목을 검색할 수도 있습니다. 이를 위해 문자열 인수를 사용합니다. 아래 예시는 페이지에서 로그인 버튼을 찾습니다.

import requests
from bs4 import BeautifulSoup

response = requests.get("https://quotes.toscrape.com")

soup = BeautifulSoup(response.text, "html.parser")

login_button = soup.find("a", string="Login")
print(login_button.text)

보시다시피, 콘솔에 'Login'이 출력됩니다.

속성별 찾기

속성으로 찾기

더 정확한 검색을 위해 다른 속성을 사용할 수도 있습니다. 이번에도 페이지에서 첫 번째 인용문을 찾습니다. 하지만 text 속성을 가진 span 요소를 찾습니다. 이렇게 하면 저자나 태그 같은 불필요한 정보 없이 첫 번째 인용문만 다시 찾을 수 있습니다.

import requests
from bs4 import BeautifulSoup

response = requests.get("https://quotes.toscrape.com")

soup = BeautifulSoup(response.text, "html.parser")

first_clean_quote = soup.find("span", attrs={"itemprop": "text"})

print(first_clean_quote.text)

첫 번째 인용문의 정리된 버전입니다.

“우리가 창조한 세상은 우리의 사고 과정이다. 우리의 사고를 바꾸지 않고서는 세상을 바꿀 수 없다.”

여러 기준을 사용한 검색

앞서 보셨듯이, attr 인자는 단일 값 대신 딕셔너리를 받습니다. 이를 통해 더 나은 필터링을 위해 여러 기준을 전달할 수 있습니다. 여기서는 classitemprop 속성을 사용하여 페이지의 첫 번째 저자를 찾습니다.

import requests
from bs4 import BeautifulSoup

response = requests.get("https://quotes.toscrape.com")

soup = BeautifulSoup(response.text, "html.parser")

first_author = soup.find("small", attrs={"class": "author", "itemprop": "author"})
print(first_author.text)

이 코드를 실행하면 Albert Einstein이 출력됩니다.

Albert Einstein

find_all()

이제 find_all()을 사용하여 동일한 예제를 살펴보겠습니다. 다시 한번 Quotes to Scrape와 Fake Store API를 사용할 것입니다. 이 예제들은 거의 동일하지만 한 가지 주요 차이점이 있습니다. find() 는 단일 요소를 반환합니다. find_all()은 페이지 요소들의 리스트를 반환합니다.

클래스로 찾기

클래스를 사용하여 요소를 찾으려면 class_ 키워드 인수를 사용합니다. 아래 코드는 find_all() 을 사용하여 CSS 클래스를 기반으로 각 인용문을 추출합니다.

import requests
from bs4 import BeautifulSoup

response = requests.get("https://quotes.toscrape.com")

soup = BeautifulSoup(response.text, "html.parser")

quotes = soup.find_all("div", class_="quote")

for quote in quotes:
    print("-------------")
    print(quote.text)

첫 페이지의 명언을 추출하여 출력하면 다음과 같습니다.

-------------

“우리가 창조한 세상은 우리의 사고 과정이다. 사고를 바꾸지 않고서는 세상을 바꿀 수 없다.”
앨버트 아인슈타인
(주제)

            태그:
            
변화
깊은 생각
사고
세계


-------------

“해리, 우리의 진정한 모습을 드러내는 것은 능력보다 선택이다.”
J.K. 롤링
(주제)

            태그:
            
능력
선택

-------------

“삶을 사는 방법은 두 가지뿐이다. 하나는 아무것도 기적처럼 여기지 않는 삶이고, 다른 하나는 모든 것을 기적처럼 여기는 삶이다.”
앨버트 아인슈타인
(인용)

            태그:
            
영감
삶
살다
기적
기적들

-------------

“좋은 소설에서 즐거움을 느끼지 못하는 사람은, 신사든 숙녀든, 참을 수 없을 만큼 어리석은 사람일 것이다.”
제인 오스틴
(인용)


            태그:
            
문맹
책
고전
유머


-------------

“불완전함은 아름다움이고, 광기는 천재성이다. 그리고 완전히 우스꽝스러운 편이 완전히 지루한 편보다 낫다.”
- 마릴린 먼로
(인용)


            태그:
            
자기다움
영감


-------------

"성공한 사람이 되려 하지 마라. 차라리 가치 있는 사람이 되라."
앨버트 아인슈타인
(인용)

            태그:
            
성인기
성공
가치


-------------

“있는 그대로의 모습으로 미움받는 것이, 없는 모습으로 사랑받는 것보다 낫다.”
앙드레 지드
(인용)

            태그:
            
삶
사랑


-------------

“나는 실패한 것이 아니다. 단지 1만 가지 안 되는 방법을 발견했을 뿐이다.”
토머스 에디슨
(인용)


            태그:
            
에디슨
실패
영감
의역


-------------

"여자는 티백과 같다. 뜨거운 물에 담기기 전까지는 그 강도를 알 수 없다."
엘리너 루스벨트
(인용)


            태그:
            
잘못된 인용-엘리너 루스벨트


-------------

"햇빛 없는 하루는, 알다시피, 밤과 같아."
- 스티브 마틴
(인용)

            태그:
            
유머
당연한
비유

ID로 찾기

find() 사용 시 논의했던 것처럼, id는 페이지에서 데이터를 추출할 때 흔히 사용하는 또 다른 방법입니다. id를 이용해 데이터를 추출하려면 id 인자를 사용합니다… 앞서 했던 방식과 동일합니다.

그런 다음 id가 menu인 모든 ul 항목을 찾습니다. menu는 하나뿐이므로 실제로는 하나만 찾을 것입니다.

import requests
from bs4 import BeautifulSoup

response = requests.get("https://fakestoreapi.com")

soup = BeautifulSoup(response.text, "html.parser")

uls = soup.find_all("ul", id="menu")

for ul in uls:
    print("-------------")
    print(ul.text)

페이지에 메뉴가 하나뿐이므로, 출력 결과는 find()를 사용했을 때와 정확히 동일합니다.

-------------

홈
문서
GitHub
커피 한 잔 사주세요

텍스트로 찾기

이제 텍스트를 이용해 페이지에서 항목을 추출해 보겠습니다. 문자열 인수를 사용할 것입니다. 아래 예시에서는 'Login' 문자열을 포함하는 모든 a 요소를 찾습니다. 다시 한번, 단 하나만 존재합니다.

import requests
from bs4 import BeautifulSoup

response = requests.get("https://quotes.toscrape.com")

soup = BeautifulSoup(response.text, "html.parser")

login_buttons = soup.find_all("a", string="Login")

for button in login_buttons:
    print("-------------")
    print(button)

출력 결과는 다음과 같아야 합니다.

-------------
<a href="/login">Login</a>

속성으로 찾기

실제 웹 스크래핑을 진행할 때는 페이지에서 항목을 추출하기 위해 다른 속성을 사용해야 하는 경우가 많습니다. 첫 번째 예제의 출력이 얼마나 지저분했는지 기억하시나요? 다음 코드 조각에서는 itemprop 속성을 사용하여 이번에는 인용문만 추출해 보겠습니다.

import requests
from bs4 import BeautifulSoup

response = requests.get("https://quotes.toscrape.com")

soup = BeautifulSoup(response.text, "html.parser")

clean_quotes = soup.find_all("span", attrs={"itemprop": "text"})

for quote in clean_quotes:
    print("-------------")
    print(quote.text)

출력이 얼마나 깔끔한지 보세요!

-------------
“우리가 창조한 세상은 우리의 사고 과정이다. 사고를 바꾸지 않고서는 세상을 바꿀 수 없다.”
-------------
“해리, 우리의 진정한 모습을 드러내는 것은 능력보다 선택이다.”
-------------
“인생을 사는 방법은 단 두 가지뿐이다. 하나는 아무것도 기적처럼 여기지 않는 삶이고, 다른 하나는 모든 것을 기적처럼 여기는 삶이다.”
-------------
“좋은 소설에서 즐거움을 느끼지 못하는 사람은, 신사든 숙녀든, 참을 수 없을 만큼 어리석은 사람일 것이다.”
-------------
“불완전함은 아름다움이고, 광기는 천재성이다. 완전히 우스꽝스러운 사람이 완전히 지루한 사람보다 낫다.”
-------------
“성공한 사람이 되려 하지 마라. 차라리 가치 있는 사람이 되라.”
-------------
“있는 그대로의 모습으로 미움받는 것이, 없는 모습으로 사랑받는 것보다 낫다.”
-------------
“나는 실패한 것이 아니다. 단지 효과가 없는 방법 1만 가지를 발견했을 뿐이다.”
-------------
“여자는 티백과 같다. 뜨거운 물에 담그기 전까지는 그 강도를 알 수 없다.”
-------------
“햇빛 없는 날은, 알다시피, 밤과 같다.”

여러 기준을 사용한 찾기

이번에는 attrs 인자를 더 복잡하게 활용해 보겠습니다. 여기서 우리는 class가 author이고 itemprop가 author인 모든 작은 요소들을 찾습니다. 두 속성을 모두 attrs 사전으로 전달하여 이를 수행합니다.

import requests
from bs4 import BeautifulSoup

response = requests.get("https://quotes.toscrape.com")

soup = BeautifulSoup(response.text, "html.parser")

authors = soup.find_all("small", attrs={"class": "author", "itemprop": "author"})

for author in authors:
    print("-------------")
    print(author.text)

콘솔에 표시된 저자 목록입니다.

-------------
Albert Einstein
-------------
J.K. Rowling
-------------
Albert Einstein
-------------
Jane Austen
-------------
Marilyn Monroe
-------------
Albert Einstein
-------------
André Gide
-------------
Thomas A. Edison
-------------
Eleanor Roosevelt
-------------
Steve Martin

고급 기법

다음은 좀 더 고급 기법들입니다. 아래 예제에서는 find_all() 을 사용하지만, find()를 사용할 때도 동일한 방식으로 적용 가능합니다. 단, 단일 요소를 원하는지, 아니면 요소들의 리스트를 원하는지 기억하세요.

정규 표현식

정규 표현식은 문자열 일치에 매우 강력한 도구입니다. 이 코드 예시에서는 정규 표현식과 article 문자열을 결합하여 대소문자를 구분하지 않고 einstein을 포함하는 모든 요소를 찾습니다.

import requests
import re
from bs4 import BeautifulSoup

response = requests.get("https://quotes.toscrape.com")

soup = BeautifulSoup(response.text, "html.parser")

pattern = re.compile(r"einstein", re.IGNORECASE)

tags = soup.find_all(string=pattern)

print(f"아인슈타인 명언 총 개수: {len(tags)}")

페이지에서 3개의 명언을 찾았습니다.

총 아인슈타인 인용문: 3

사용자 정의 함수

이제 아인슈타인의 실제 명언을 모두 반환하는 사용자 정의 함수를 작성해 보겠습니다. 아래 예제에서는 정규식을 확장합니다. 부모 메서드를 사용하여 명언이 포함된 카드를 탐색하고 찾습니다. 다음으로 모든 스팬을 찾습니다. 카드의 첫 번째 스팬이 실제 명언을 포함합니다. 그 내용을 콘솔에 출력합니다.

import requests
import re
from bs4 import BeautifulSoup

def find_einstein_quotes(http_response):
    soup = BeautifulSoup(http_response.text, "html.parser")

    # 모든 아인슈타인 태그 찾기
    pattern = re.compile(r"einstein", re.IGNORECASE)
    tags = soup.find_all(string=pattern)

    for tag in tags:
        # 인용문 카드까지 부모 요소를 따라 이동
        full_card = tag.parent.parent.parent

        # 스팬 요소 찾기
        spans = full_card.find_all("span")

        # 첫 번째 스팬 출력 (실제 인용문 포함)
        print(spans[0].text)


if __name__ == "__main__":
    response = requests.get("https://quotes.toscrape.com")
    find_einstein_quotes(response)

다음은 출력 결과입니다.

“우리가 창조한 세상은 우리의 사고 과정이다. 사고를 바꾸지 않고서는 세상을 바꿀 수 없다.”
“인생을 사는 방법은 두 가지뿐이다. 하나는 아무것도 기적처럼 여기지 않는 삶이고, 다른 하나는 모든 것을 기적처럼 여기는 삶이다.”
“성공한 사람이 되려 하지 마라. 가치 있는 사람이 되라.”

보너스: CSS 선택자를 이용한 찾기

BeautifulSoup의 select 메서드는 find_all()과 거의 동일하게 작동하지만, 좀 더 유연합니다. 이 메서드는 CSS 선택자를 인수로 받습니다. 선택자를 작성할 수 있다면, 해당 요소를 찾을 수 있습니다. 이 코드에서는 여러 속성을 다시 활용해 모든 저자를 찾습니다. 하지만 이들을 단일 선택자로 전달할 수도 있습니다.

import requests
from bs4 import BeautifulSoup

response = requests.get("https://quotes.toscrape.com")

soup = BeautifulSoup(response.text, "html.parser")

authors = soup.select("small[class='author'][itemprop='author']")

for author in authors:
    print("-------------")
    print(author.text)

다음은 출력 결과입니다.

-------------
Albert Einstein
-------------
J.K. Rowling
-------------
Albert Einstein
-------------
Jane Austen
-------------
Marilyn Monroe
-------------
Albert Einstein
-------------
André Gide
-------------
Thomas A. Edison
-------------
Eleanor Roosevelt
-------------
Steve Martin

결론

이제 BeautifulSoup의find()find_all()메서드의 거의 모든 측면을 알게 되었습니다. 이 모든 메서드를 완벽히 숙달할 필요는 없습니다. 다양한 find 메서드 덕분에 자신에게 편한 방법을 선택할 수 있습니다. 가장 중요한 것은, 이들을 활용해 어떤 웹 페이지에서든 데이터를 추출할 수 있다는 점입니다. 실제 운영 환경에서는 특히 높은 성공률로 빠르고 안정적인 결과를 얻기 위해, 저희의주거용 프록시나내장형 프록시 관리 시스템과 CAPTCHA 해결 기능을 갖춘스크래핑 브라우저를고려해 보시기 바랍니다.

지금 바로 가입하여 무료 체험을 시작하고, 여러분의 요구에 딱 맞는 제품을 찾아보세요.