본문 바로가기

Python/Basic

[파이썬] BeautifulSoup

BeautifulSoup

BeautifulSoup는 Python의 라이브러리 중 하나로, 웹 페이지에서 데이터를 추출하고 이를 파싱하여 사용자가 필요로 하는 정보를 손쉽게 찾을 수 있도록 도와주는 도구입니다. 이를 통해 웹 스크래핑 (웹 페이지에서 데이터를 수집하는 프로세스) 및 데이터 마이닝 (데이터에서 유용한 정보를 추출하는 프로세스) 작업을 간편하게 수행할 수 있습니다.

 

이 BeautifulSoup은 사용하기 쉬운 API를 제공하며, HTML 태그 및 속성을 탐색하고 원하는 요소를 찾을 수 있는 다양한 메서드를 제공하기에, 많이 사용되는 라이브러리입니다.

 

BeautifulSoup의 사용법

1.HTML 또는 XML 데이터를 BeautifulSoup 객체로 파싱합니다.

2.파싱된 객체를 사용하여 원하는 요소를 탐색하고 찾습니다.

  • find(), find_all(), select(), select_one()과 같은 메서드를 사용합니다.

3. 찾은 요소에서 원하는 데이터를 추출하여 활용합니다.

  • 웹 페이지에서 특정 텍스트, 링크, 이미지 등을 수집하거나 분석할 수 있습니다.

 


예시코드

# BeautifulSoup : HTML 및 XML 파일에서 데이터를 가져오는 Python 라이브러리
# 문서 내의 element(tag, 요소) 및 attribute(속성) 찾기 함수 : find(), find_all(), select_one, select

#BeautifulSoup의 find, select 연습
from bs4 import BeautifulSoup
#-----------------------------------------------------------------------------------------
htmlData='''
<html>
    <body>
        <h1>제목 태그</h1>
        <p>문단 1</p>
        <p>문단 2</p>        
    </body>
</html>
'''

print(type(htmlData)) # <class 'str'> -> python에서 string 파일은 쓸수가 없다.

soup = BeautifulSoup(htmlData, 'html.parser') #BeautifulSoup 객체가 생성이 된다.->BeautifulSoup 모듈 지원 명령 사용 가능
print(type(soup))

h1=soup.html.body.h1
print("h1 : ",h1.text,' ',h1.string)

p1=soup.html.body.p
print('p1 : ',p1.text)

p2=p1.next_sibling.next_sibling
print('p2 : ',p2.text)

#-----------------------------------------------------------------------------------------
print('\n find() : 반환값 단수개 사용 ------')
htmlData2='''
<html>
    <body>
        <h1 id="title">제목 태그</h1>
        <p>문단 1</p>
        <p id="my" class="our">문단 2</p>        
    </body>
</html>
'''

soup2 = BeautifulSoup(htmlData2, 'html.parser') 
print(soup2.p,' ',soup2.p.string)
print(soup2.find('p').string)
print(soup2.find('p',id='my').string)
print(soup2.find(id='title').string)
print(soup2.find(id='my').string)
print(soup2.find(class_ ='our').string)
print(soup2.find(attrs ={'class':'our'}).string)
print(soup2.find(attrs ={'id':'my'}).string) #id를 받으면 단수로 받아온다. 위의 것들은 복수이지만 find를 썼기에 복수로 받아오지 않는다.

#-----------------------------------------------------------------------------------------
print('\n find_all(), findAll() : 반환값이 복수 사용 ------')
htmlData3='''
<html>
    <body>
        <h1 id="title">제목 태그</h1>
        <p>문단 1</p>
        <p id="my" class="our">문단 2</p>        
        <div>
            <a href="https://www.naver.com">네이버</a><br/> 
            <a href="https://www.daum.com">다음</a><br/> 
        </div>
    </body>
</html>
'''

soup3 = BeautifulSoup(htmlData3, 'lxml') 
print(soup3.find_all("a"))
print(soup3.find_all(["a","p"]))
print(soup3.findAll(["a"]))
print()
links=soup3.findAll(["a"])
print(links)
print()

for i in links:
    href = i.attrs['href']
    text=i.string
    print(href, ' ', text)
    
#-----------------------------------------------------------------------------------------
print('\n정규 표현식 사용')
import re
links2 = soup3.find_all(href=re.compile(r'^https'))
for j in links2:
    print(j.attrs['href'])


print('\n select_one,select : css의 셀렉터를 사용 ------')
htmlData4='''
<html>
    <body>
        <div id="hello">
            <a href="https://www.naver.com">네이버</a><br/>
            <span> 
                <a href="https://www.daum.com">다음</a><br/> 
            </span>
            <b>
                <ul class="world">
                    <li>안녕</li>
                    <li>반갑다</li>
                </ul>
            </b>
        </div>
        <div id="hi" class="good"> 
            두번쨰 div 태그
        <div>
    </body>
</html>
'''

print('\n 단수 선택')
soup4 = BeautifulSoup(htmlData4, 'lxml')
kbs=soup4.select_one("div#hello >a") #id가 hello인 a태그
print('kbs : ',kbs,' ',kbs.string) # 태그 내의 정보 뽑아내기
kbs2=soup4.select_one("div.good") #class가 good인 a태그
print('\nkbs2 : ',kbs2,' ',kbs2.string) # 태그 내의 정보 뽑아내기

print('\n 복수 선택')
mbc=soup4.select("div#hello ul.world>li") #div 태그 중 id가 hello, 그런데 hello 내에는 ul이 포함되어있다. 그리고 '.'을 사용하면 자손 태그를 얻는다. '>' :이거는 직계로, 요소냐 속성이냐 구분
print('mbc : ',mbc)
for a in mbc:
    print(a.string,' ')

print()
msg=list()
for a in mbc:
    msg.append(a.string)
    
import pandas as pd
df=pd.DataFrame(msg,columns=['자료'])
print(df)
print(df.to_json())

 

print("\n 벅스 뮤직 상이트에서 곡 제목 읽기 - find 사용")
from urllib.request import urlopen

url= urlopen("https://music.bugs.co.kr/chart") # urlopen을 사용하여 벅스 뮤직 차트 페이지의 HTML가져오기
soup=BeautifulSoup(url.read(),'html.parser') # BeautifulSoup을 사용하여 HTML을 파싱
musics= soup.find_all('td',class_="check")
# find_all을 사용하여 모든 td 태그 중 class가 "check"인 요소들을 찾기

for i,music in enumerate(musics):
    print('{}위 : {}'.format(i+1,music.input['title']))
#찾은 각각의 요소에 대해 반복문을 실행하여 enumerate를 사용하여 순위와 곡 제목을 출력

Python을 사용하여 웹 페이지에서 벅스 뮤직 차트의 곡 제목을 가져오는 코드