์น ์คํฌ๋ํ
BeautifulSoup์ ์ฌ์ฉํ์ฌ ์น ํ์ด์ง์์ ์ํ๋ ๋ฐ์ดํฐ๋ฅผ ์ถ์ถํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋ด ์๋ค.
์น ์คํฌ๋ํ์ด๋?โ
์น ์คํฌ๋ํ์ ์น ํ์ด์ง์์ ์๋์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์์งํ๋ ๊ธฐ์ ์ ๋๋ค. ๋ด์ค ๊ธฐ์ฌ, ์ํ ๊ฐ๊ฒฉ, ๋ ์จ ์ ๋ณด ๋ฑ ์น์ ์๋ ๋ค์ํ ๋ฐ์ดํฐ๋ฅผ ํ๋ก๊ทธ๋๋ฐ์ ์ผ๋ก ์ถ์ถํ ์ ์์ต๋๋ค.
์ฃผ์ ์ฉ๋โ
- ๊ฐ๊ฒฉ ๋น๊ต ๋ฐ ๋ชจ๋ํฐ๋ง
- ๋ด์ค ๋ฐ ์ฝํ ์ธ ์์ง
- ๋ฐ์ดํฐ ๋ถ์ ๋ฐ ์ฐ๊ตฌ
- ๊ฒ์ ์์ง ์ธ๋ฑ์ฑ
- ์์ฅ ์กฐ์ฌ ๋ฐ ๊ฒฝ์์ฌ ๋ถ์
์ฃผ์์ฌํญโ
- robots.txt ํ์ธ: ์น์ฌ์ดํธ์ ํฌ๋กค๋ง ์ ์ฑ ์ค์
- ์ด์ฉ ์ฝ๊ด ๊ฒํ : ๋ฒ์ ๋ฌธ์ ๋ฐฉ์ง
- ์๋ฒ ๋ถํ ๊ณ ๋ ค: ์์ฒญ ๊ฐ๊ฒฉ ์กฐ์
- ๊ฐ์ธ์ ๋ณด ๋ณดํธ: ๋ฏผ๊ฐํ ์ ๋ณด ์์ง ๊ธ์ง
์ค์นํ๊ธฐโ
# BeautifulSoup 4
pip install beautifulsoup4
# HTML ํ์ (lxml์ด ๋ ๋น ๋ฆ)
pip install lxml
# ๋๋ html5lib (๋ ๊ด๋ํ ํ์ฑ)
pip install html5lib
# requests (HTTP ์์ฒญ์ฉ)
pip install requests
๊ธฐ๋ณธ ์ฌ์ฉ๋ฒโ
HTML ๊ฐ์ ธ์ค๊ธฐ์ ํ์ฑโ
import requests
from bs4 import BeautifulSoup
# ์น ํ์ด์ง ๊ฐ์ ธ์ค๊ธฐ
url = 'https://example.com'
response = requests.get(url)
html = response.text
# BeautifulSoup ๊ฐ์ฒด ์์ฑ
soup = BeautifulSoup(html, 'lxml')
# ์ ์ฒด HTML ์ถ๋ ฅ (๋ณด๊ธฐ ์ข๊ฒ)
print(soup.prettify())
# ์ ๋ชฉ ๊ฐ์ ธ์ค๊ธฐ
title = soup.title
print(title.string) # ์ ๋ชฉ ํ
์คํธ
# ๋ชจ๋ ํ
์คํธ ๊ฐ์ ธ์ค๊ธฐ
text = soup.get_text()
print(text)
ํ์ ์ข ๋ฅโ
# lxml (๋น ๋ฅด๊ณ ์ ์ฐํจ, ๊ถ์ฅ)
soup = BeautifulSoup(html, 'lxml')
# html.parser (๋ด์ฅ, ์ถ๊ฐ ์ค์น ๋ถํ์)
soup = BeautifulSoup(html, 'html.parser')
# html5lib (๊ฐ์ฅ ๊ด๋ํจ, ๋๋ฆผ)
soup = BeautifulSoup(html, 'html5lib')
# XML ํ์ฑ
soup = BeautifulSoup(xml, 'xml')
ํ๊ทธ ์ ํํ๊ธฐโ
๊ธฐ๋ณธ ์ ํ ๋ฐฉ๋ฒโ
from bs4 import BeautifulSoup
html = '''
<html>
<head><title>My Page</title></head>
<body>
<h1 id="main-title">Welcome</h1>
<div class="content">
<p class="intro">First paragraph</p>
<p class="text">Second paragraph</p>
<a href="/page1">Link 1</a>
<a href="/page2">Link 2</a>
</div>
</body>
</html>
'''
soup = BeautifulSoup(html, 'lxml')
# ์ฒซ ๋ฒ์งธ ํ๊ทธ ์ฐพ๊ธฐ
h1 = soup.find('h1')
print(h1.string) # Welcome
# ๋ชจ๋ ํ๊ทธ ์ฐพ๊ธฐ
paragraphs = soup.find_all('p')
for p in paragraphs:
print(p.string)
# ID๋ก ์ฐพ๊ธฐ
main_title = soup.find(id='main-title')
print(main_title.string)
# ํด๋์ค๋ก ์ฐพ๊ธฐ
intro = soup.find(class_='intro')
print(intro.string)
# ์ฌ๋ฌ ์กฐ๊ฑด
link = soup.find('a', href='/page1')
print(link.string)
CSS ์ ํ์ ์ฌ์ฉโ
# CSS ์ ํ์๋ก ์ฐพ๊ธฐ (๋ ์ง๊ด์ )
h1 = soup.select_one('h1#main-title')
print(h1.string)
# ํด๋์ค ์ ํ
intro = soup.select_one('.intro')
paragraphs = soup.select('.content p')
# ์์ ์ ํ์
content_links = soup.select('div.content > a')
# ์์ฑ ์ ํ์
external_links = soup.select('a[href^="http"]')
# ์ฌ๋ฌ ๊ฐ ์ ํ
items = soup.select('.item')
for item in items:
print(item.text)
๋ฐ์ดํฐ ์ถ์ถํ๊ธฐโ
ํ ์คํธ ์ถ์ถโ
# ํ๊ทธ์ ํ
์คํธ
text = tag.string # ์ง์ ์์ ํ
์คํธ๋ง
text = tag.get_text() # ๋ชจ๋ ํ์ ํ
์คํธ
text = tag.text # get_text()์ ๋์ผ
# ๊ณต๋ฐฑ ์ฒ๋ฆฌ
text = tag.get_text(strip=True) # ์๋ค ๊ณต๋ฐฑ ์ ๊ฑฐ
# ๊ตฌ๋ถ์ ์ง์
text = tag.get_text(separator=' | ') # ํ๊ทธ ์ฌ์ด์ ๊ตฌ๋ถ์
# ์์
html = '<div> <p>Hello</p> <p>World</p> </div>'
soup = BeautifulSoup(html, 'lxml')
div = soup.find('div')
print(div.get_text()) # " Hello World "
print(div.get_text(strip=True)) # "HelloWorld"
print(div.get_text(separator=' | ', strip=True)) # "Hello | World"
์์ฑ ์ถ์ถโ
# ์์ฑ ๊ฐ์ ธ์ค๊ธฐ
link = soup.find('a')
# ๋์
๋๋ฆฌ ๋ฐฉ์
href = link['href']
title = link.get('title', 'No title') # ๊ธฐ๋ณธ๊ฐ ์ค์
# ๋ชจ๋ ์์ฑ
attrs = link.attrs
print(attrs) # {'href': '/page1', 'class': ['link'], 'id': 'first'}
# ์ฌ๋ฌ ๊ฐ์ ๊ฐ์ง ์์ฑ (class, rel ๋ฑ)
classes = link.get('class') # ๋ฆฌ์คํธ ๋ฐํ
print(classes) # ['link', 'external']
# ์์ : ๋ชจ๋ ์ด๋ฏธ์ง URL ์ถ์ถ
images = soup.find_all('img')
for img in images:
src = img.get('src')
alt = img.get('alt', 'No description')
print(f"Image: {src} - {alt}")
ํ์ ๋ฐ ์ํโ
# ๋ถ๋ชจ ํ์
tag = soup.find('p')
parent = tag.parent
print(parent.name)
# ๋ชจ๋ ๋ถ๋ชจ
for parent in tag.parents:
print(parent.name)
# ํ์ ํ์
next_sibling = tag.next_sibling # ๋ค์ ํ์ (ํ
์คํธ ํฌํจ)
next_tag = tag.find_next_sibling() # ๋ค์ ํ๊ทธ
prev_tag = tag.find_previous_sibling() # ์ด์ ํ๊ทธ
# ๋ชจ๋ ํ์
for sibling in tag.next_siblings:
print(sibling)
# ์์ ํ์
children = tag.children # ์ง์ ์์ (์ดํฐ๋ ์ดํฐ)
descendants = tag.descendants # ๋ชจ๋ ํ์ ์์
# ์์ : ํ
์ด๋ธ ํ์
table = soup.find('table')
for row in table.find_all('tr'):
cells = row.find_all(['td', 'th'])
data = [cell.get_text(strip=True) for cell in cells]
print(data)