Python 및 BeautifulSoup로 웹 스크래핑 수준 향상
Ethan Miller
Product Engineer · Leapcell

포괄적인 HTML 처리 튜토리얼: 파싱부터 데이터 추출까지
I. 소개
웹 페이지의 기본 언어인 HTML(Hypertext Markup Language)은 웹 데이터 처리 및 웹 개발과 같은 분야에서 널리 사용됩니다. 개발자가 웹 구조를 최적화하든 데이터 분석가가 웹 페이지에서 정보를 추출하든 HTML 처리는 필수적입니다. 이 튜토리얼에서는 HTML 구문 분석, 수정 및 데이터 추출과 같은 핵심 작업에 중점을 두어 독자가 HTML 처리를 위한 포괄적인 방법과 기술을 익히도록 돕습니다.
II. HTML 기본 사항 검토
2.1 기본 HTML 구조
표준 HTML 문서는 <!DOCTYPE html>
선언으로 시작하여 두 개의 주요 섹션(<head>
및 <body>
)을 포함하는 <html>
루트 요소를 포함합니다. <head>
섹션에는 일반적으로 제목, 문자 인코딩, CSS 스타일시트 링크와 같은 페이지에 대한 메타 정보가 포함되어 있습니다. <body>
섹션에는 텍스트, 이미지, 링크, 양식 및 기타 요소를 포함하여 페이지의 보이는 내용이 들어 있습니다.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>My Page</title> </head> <body> <h1>Hello, World!</h1> <p>This is a simple HTML page.</p> </body> </html>
2.2 HTML 요소 및 속성
HTML은 단락의 경우 <p>
, 링크의 경우 <a>
와 같은 태그로 표시되는 다양한 요소로 구성됩니다. 요소에는 추가 정보를 정의하는 속성이 포함될 수 있습니다. 예를 들어 <a href="https://example.com">
의 href
속성은 링크의 대상 주소를 지정합니다. 속성은 일반적으로 "이름-값" 쌍으로 되어 있으며 속성 값은 따옴표로 묶어야 합니다.
III. HTML 파싱
3.1 파싱 도구 및 라이브러리
다양한 개발 환경에서 여러 도구와 라이브러리가 HTML을 파싱할 수 있습니다.
- 브라우저: 브라우저에는 HTML 코드를 시각적 페이지로 렌더링하는 강력한 HTML 파싱 엔진이 내장되어 있습니다. 브라우저 개발자 도구(예: Chrome DevTools)를 통해 파싱된 DOM(Document Object Model) 구조를 보고 요소 스타일과 속성을 분석할 수 있습니다.
- Python 라이브러리:
- BeautifulSoup: Python에서 가장 일반적으로 사용되는 HTML 파싱 라이브러리 중 하나로, HTML 및 XML 문서를 쉽게 파싱하고 파싱 트리를 탐색, 검색 및 수정하기 위한 간단한 API를 제공합니다.
- lxml: libxml2 및 libxslt 라이브러리를 기반으로 구축된 Python 라이브러리로, 빠르게 파싱하고 HTML 및 XML 파싱을 모두 지원하며 XPath 표현식과 함께 사용하여 효율적인 데이터 추출을 지원합니다.
- html5lib: 이 라이브러리는 최신 브라우저와 매우 유사한 방식으로 HTML을 파싱하므로 불규칙한 HTML 코드를 처리하는 데 적합합니다.
- JavaScript: 브라우저 환경에서 JavaScript는
getElementById
및getElementsByTagName
과 같은document
객체에서 제공하는 메서드를 사용하여 DOM을 직접 조작하여 HTML을 파싱하고 작동할 수 있습니다. Node.js 환경에서jsdom
과 같은 라이브러리는 HTML을 파싱하기 위해 브라우저 환경을 시뮬레이션할 수 있습니다.
3.2 Python으로 HTML 파싱
3.2.1 BeautifulSoup 파싱 예제
먼저 BeautifulSoup 라이브러리를 설치합니다.
pip install beautifulsoup4
다음은 BeautifulSoup으로 HTML을 파싱하기 위한 기본 코드입니다.
from bs4 import BeautifulSoup html_doc = """ <html> <head><title>Sample Page</title></head> <body> <p class="intro">This is an introductory paragraph.</p> <p class="content">Here is some content.</p> </body> </html> """ soup = BeautifulSoup(html_doc, 'html.parser') # Python 내장 파서 사용 # 다른 파서(예: lxml)도 사용할 수 있습니다: soup = BeautifulSoup(html_doc, 'lxml') print(soup.title.string) # 출력: Sample Page
3.2.2 lxml 파싱 예제
lxml 라이브러리를 설치합니다.
pip install lxml
lxml을 사용하여 HTML을 파싱하고 XPath를 통해 데이터를 추출합니다.
from lxml import etree html = """ <html> <body> <div class="box"> <p>First paragraph</p> <p>Second paragraph</p> </div> </body> </html> """ tree = etree.HTML(html) paragraphs = tree.xpath('//div[@class="box"]/p/text()') print(paragraphs) # 출력: ['First paragraph', 'Second paragraph']
IV. HTML 문서 트리 탐색 및 검색
4.1 HTML 문서 트리 탐색
BeautifulSoup을 예로 들어 보겠습니다. 파싱 후 HTML 문서는 여러 가지 방법으로 탐색할 수 있는 문서 트리를 형성합니다.
- 자식 요소 액세스: 태그 이름으로 자식 요소에 직접 액세스할 수 있습니다. 예를 들어
soup.body.p
는<body>
요소 아래의 첫 번째<p>
요소에 액세스합니다.contents
속성을 사용하여 자식 요소 목록을 가져올 수도 있고children
속성을 사용하여 자식 요소를 생성기로 반복할 수도 있습니다. - 부모 요소 액세스:
parent
속성을 사용하여 현재 요소의 직접 부모를 가져오고parents
속성을 사용하여 모든 상위 요소를 재귀적으로 순회합니다. - 형제 요소 액세스:
next_sibling
및previous_sibling
속성은 각각 다음 형제 요소와 이전 형제 요소를 가져옵니다.next_siblings
및previous_siblings
속성은 모든 후속 및 이전 형제를 반복합니다.
4.2 HTML 문서 트리 검색
find_all()
메서드: BeautifulSoup의find_all()
메서드는 지정된 기준과 일치하는 모든 요소를 검색하며 태그 이름, 속성 등으로 필터링할 수 있습니다. 예를 들어 모든<p>
태그를 찾으려면soup.find_all('p')
를 사용합니다.content
클래스가 있는 모든 요소를 찾으려면soup.find_all(class_='content')
를 사용합니다.find()
메서드:find()
메서드는 기준과 일치하는 첫 번째 요소를 반환합니다. 예를 들어soup.find('a')
는 문서에서 첫 번째<a>
요소를 반환합니다.- CSS 선택기: CSS 선택기 구문과 함께
select()
메서드를 사용하여 보다 유연한 요소 검색을 수행합니다. 예를 들어box
클래스가 있는 모든<div>
요소를 선택하려면soup.select('div.box')
를 사용하고 id가main
인 요소 아래의 모든<li>
요소를 선택하려면soup.select('#main li')
를 사용합니다.
V. HTML 수정
5.1 요소 속성 수정
Python 라이브러리와 JavaScript 모두 HTML 요소 속성을 쉽게 수정할 수 있습니다.
-
Python(BeautifulSoup):
from bs4 import BeautifulSoup html = """ <html> <body> <a href="https://old-url.com">Old Link</a> </body> </html> """ soup = BeautifulSoup(html, 'html.parser') link = soup.find('a') link['href'] = 'https://new-url.com' # href 속성 수정 print(soup.prettify())
-
JavaScript:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> <img id="myImage" src="old-image.jpg" alt="Old Image"> <script> const image = document.getElementById('myImage'); image.src = 'new-image.jpg'; // src 속성 수정 </script> </body> </html>
5.2 요소 추가 및 제거
-
Python(BeautifulSoup):
-
요소 추가:
from bs4 import BeautifulSoup html = """ <html> <body> <ul id="myList"></ul> </body> </html> """ soup = BeautifulSoup(html, 'html.parser') ul = soup.find('ul') new_li = soup.new_tag('li') new_li.string = 'New Item' ul.append(new_li) # 새 요소 추가
-
요소 제거:
from bs4 import BeautifulSoup html = """ <html> <body> <p id="removeMe">This paragraph will be removed.</p> </body> </html> """ soup = BeautifulSoup(html, 'html.parser') p = soup.find('p', id='removeMe') p.decompose() # 요소 제거
-
-
JavaScript:
-
요소 추가:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> <div id="parentDiv"></div> <script> const parentDiv = document.getElementById('parentDiv'); const newParagraph = document.createElement('p'); newParagraph.textContent = 'This is a new paragraph.'; parentDiv.appendChild(newParagraph); // 새 요소 추가 </script> </body> </html>
-
요소 제거:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> <p id="removeParagraph">This paragraph will be removed.</p> <script> const paragraph = document.getElementById('removeParagraph'); paragraph.remove(); // 요소 제거 </script> </body> </html>
-
VI. HTML 데이터 추출
6.1 텍스트 콘텐츠 추출
-
Python(BeautifulSoup):
string
속성 또는get_text()
메서드를 사용하여 요소 내의 텍스트 콘텐츠를 가져옵니다. 예를 들어:from bs4 import BeautifulSoup html = """ <html> <body> <p class="text">Extract this text.</p> </body> </html> """ soup = BeautifulSoup(html, 'html.parser') text = soup.find('p', class_='text').string print(text) # 출력: Extract this text.
-
JavaScript:
textContent
또는innerText
속성을 사용하여 텍스트 콘텐츠를 가져옵니다. 예를 들어const element = document.getElementById('myElement'); const text = element.textContent;
와 같습니다.
6.2 속성 값 추출
Python과 JavaScript 모두 HTML 요소 속성 값을 쉽게 추출할 수 있습니다. 예를 들어 <a>
태그의 href
속성 값을 추출하려면 다음을 수행합니다.
- Python(BeautifulSoup):
href = soup.find('a')['href']
- JavaScript:
const link = document.querySelector('a'); const href = link.getAttribute('href');
6.3 복잡한 데이터 추출
실제 애플리케이션에서는 제품 목록이 있는 웹 페이지에서 제품 이름, 가격 및 링크를 추출하는 것과 같이 복잡한 HTML 구조에서 데이터를 추출해야 하는 경우가 많습니다. 이 경우 루프와 조건을 위의 탐색 및 검색 메서드와 결합하여 필요한 데이터를 순회하고 추출합니다.
from bs4 import BeautifulSoup import requests url = "https://example.com/products" response = requests.get(url) soup = BeautifulSoup(response.text, 'html.parser') products = [] for product_div in soup.find_all('div', class_='product'): name = product_div.find('h2', class_='product-name').string price = product_div.find('span', class_='product-price').string link = product_div.find('a')['href'] products.append({'name': name, 'price': price, 'link': link}) print(products)
VII. 불규칙한 HTML 처리
실제로 HTML 코드에는 닫히지 않은 태그 또는 누락된 속성 따옴표와 같은 불규칙한 형식이 있는 경우가 많습니다. 다양한 파서가 불규칙한 HTML을 다르게 처리합니다.
- html5lib: 이 파서는 브라우저와 유사하게 작동하며 잘못된 구조를 수정하려고 시도하여 불규칙한 HTML을 더 잘 처리할 수 있습니다.
- lxml: lxml 파서는 비교적 엄격하지만 어느 정도의 내결함성이 있습니다. 심하게 불규칙한 HTML을 처리할 때는 먼저 전처리하거나
recover=True
매개변수를 사용하여lxml.etree.HTMLParser
를 사용하여 복구 모드를 활성화해야 할 수 있습니다. - BeautifulSoup: 선택한 파서의 특성에 따라 불규칙한 HTML을 처리합니다. 복잡한 불규칙한 문서의 경우 html5lib 파서를 우선적으로 사용하는 것이 좋습니다.
VIII. 성능 최적화 및 모범 사례
8.1 올바른 파서 선택
특정 요구 사항에 따라 파서를 선택합니다.
- lxml: HTML이 비교적 표준화된 경우 속도에 이상적입니다.
- html5lib: 불규칙한 HTML 처리에 더 적합합니다.
- html.parser(Python 내장): 단순성과 적당한 성능 요구 사항으로 기본 요구 사항을 충족합니다.
8.2 중복 파싱 감소
여러 HTML 문서를 처리하거나 동일한 문서에서 여러 번 작업할 때는 중복 파싱을 피하십시오. 파싱된 결과를 캐시하거나 단일 파싱 패스에서 관련된 모든 작업을 완료하십시오.
8.3 검색 방법 적절히 사용
요소를 검색할 때는 불필요한 순회를 줄이기 위해 더 정확한 필터링 조건을 사용하십시오. 예를 들어 CSS 선택기 또는 XPath 표현식은 대상 요소를 보다 효율적으로 찾을 수 있습니다.
IX. 결론
이 튜토리얼을 통해 기본 구조, 파싱 방법, 문서 트리 탐색, 수정 작업, 데이터 추출 및 불규칙한 HTML 처리 기술을 포함하여 HTML 처리의 모든 측면을 포괄적으로 배웠습니다. 실제로 특정 시나리오에 따라 적절한 도구와 방법을 선택하는 동시에 성능 최적화와 모범 사례에 집중하면 HTML 처리 작업을 보다 효율적으로 완료하는 데 도움이 됩니다. 웹 개발이든 데이터 수집이든 HTML 처리 기술을 익히면 작업이 크게 촉진됩니다.
이 튜토리얼에서는 HTML 처리의 주요 측면을 다룹니다. 학습 중에 특정 사용 사례가 있거나 특정 섹션을 더 자세히 알고 싶다면 언제든지 저희와 소통하십시오.
Leapcell: 최고의 서버리스 웹 호스팅
마지막으로 Python 서비스를 배포하기 위한 최고의 플랫폼인 **Leapcell**을 추천합니다.
🚀 좋아하는 언어로 빌드
JavaScript, Python, Go 또는 Rust로 손쉽게 개발하십시오.
🌍 무료로 무제한 프로젝트 배포
사용한 만큼만 지불하십시오. 요청도 없고 요금도 없습니다.
⚡ 종량제, 숨겨진 비용 없음
유휴 요금 없이 원활한 확장성만 제공합니다.
🔹 트위터에서 팔로우하세요: @LeapcellHQ