BeautifulSoup 은 HTML 및 XML 파일에서 원하는 데이터를 손쉽게 Parsing 할 수 있는 Python 라이브러리 입니다.
오늘은 Beautiful Soup 라이브러리를 활용하여 HTML 코드 안에서 원하는 Data 를 뽑아내는 예제를 다뤄보려고 합니다.
1. Beautiful Soup 설치하기
Beautiful Soup 라이브러리는 Python 에서 기본적으로 제공하는 라이브러리에 해당하지 않기 때문에 별도의 설치가 필요합니다.
Windows 에서는 cmd 창에서 간단하게 pip 명령으로 설치할 수 있습니다.
- pip install beautifulsoup4
pip 는 Python 설치 디렉토리의 Scripts 폴더 밑에 있기 때문에, 해당 위치로 이동하여 명령어를 실행해 주어야 합니다.
설치가 완료되면 Python 설치 디렉토리 밑의 Lib/site-packages/ 위치에 bs4 디렉토리가 생성된 것을 확인 할 수 있습니다.
2. HTML 에서 원하는 정보 추출하기 예제
먼저 BeautifulSoup 라이브러리 사용을 위해 bs4 를 import 합니다.
from bs4 import BeautifulSoup
예제에 사용될 HTML 문서는 다음과 같습니다.
html_doc = """ <html><head><title>The Dormouse's story</title></head> <body> <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> """
문서를 Parsing 하기 위해서 BeautifulSoup 생성자에 해당 문서를 인자로 전달 해주어야 합니다.
아래와 같이 문자 열을 전달할 수도 있고, file handle 을 전달 할 수도 있습니다.
from bs4 import BeautifulSoup with open("index.html") as fp: soup = BeautifulSoup(fp) soup = BeautifulSoup("<html>data</html>")
위의 html_doc 문자열을 전달하여 BeautifulSoup 객체를 생성 합니다.
그렇게 생성한 soup 객체를 통해 HTML Parsing 을 위해 제공되는 BeautifulSoup 라이브러리의 여러가지 API 들을 사용해 보겠습니다.
if __name__ == "__main__": soup = BeautifulSoup(html_doc, 'html.parser') print('1. ', soup.title) print('2. ', soup.title.name) print('3. ', soup.title.string) print('4. ', soup.title.parent.name) print('5. ', soup.p) print('6. ', soup.p['class']) print('7. ', soup.a) print('8. ', soup.find_all('a')) print('9. ', soup.find(id="link3"))
1번 부터 9번까지 파싱 결과를 살펴보겠습니다.
원하는 tag 를 가지고 오고 싶을 때 1번과 5번 경우처럼 간단하게 soup.(원하는tag 명) 을 사용할 수 있습니다.
특정 tag 로 감싸진 내용만 가져오고 싶다면 3번과 같이 soup.title.string 을 사용하면 됩니다.
.(tag 명)의 경우 해당 태그를 포함하여 그 태그가 끝날 까지의 문장을 가지고 오고, .name, .string, .parent.name 등을 통해 더 자세한 정보들을 얻어 올 수 있습니다.
6번의 경우 soup.p['class'] 라고 하면 tag 가 p 인 것들 중 속성이 class 인 부분을 파싱 합니다.
7번과 8번의 다른점은 soup.a 의 경우 html 중 tag 가 a 인 첫번째 항목을 뽑아내지만, find_all 을 이용하면 tag 가 a 인 것들을 모두 리스트의 형태로 뽑아 낼 수 있습니다.
3. 네이버 영화 랭킹 페이지에서 영화 목록 가져오기
이번에는 자주 들어가는 Naver 포탈 사이트에서 제공하는 영화 목록을 가져와 보도록 하겠습니다.
먼저 Parsing 할 주소는 http://movie.naver.com/movie/sdb/rank/rmovie.nhn?sel=pnt&date=20180117 입니다.
페이지에 들어가 보면 평점이 가장 높은 영화부터 쭉 리스팅이 되어있습니다. 많은 정보들 중에 영화의 제목만 파싱해 오도록 하겠습니다.
먼저 BeautifulSoup 을 하나 생성하고, 인자로 네이버 영화 랭킹 페이지를 전달 합니다.
soup = BeautifulSoup(urllib.request.urlopen('http://movie.naver.com/movie/sdb/rank/rmovie.nhn?sel=pnt&date=20161120').read(), 'html.parser')
해당 페이지가 어떤 tag 들로 어떻게 구성되어있는지 보고싶다면,
print(soup.prettify())
를 이용할 수도 있지만, Chrome 에서 제공하는 개발자도구를 이용하면 더 편리합니다. (도구더보기 -> 개발자도구)
html 코드로 보면 아래와 같이 영화 제목은 'div' tag 의 'tit5'를 속성으로 가진 항목들에 포함되어 있습니다.
그래서 생성한 BeautifulSoup 객체의 find_all 함수를 이용해서 영화 제목이 담긴 div tag 를 가진 항목을 list 로 뽑아 내었습니다.
if __name__ == "__main__": soup = BeautifulSoup(urllib.request.urlopen('http://movie.naver.com/movie/sdb/rank/rmovie.nhn?sel=pnt&date=20161120').read(), 'html.parser') res = soup.find_all('div', 'tit5') print(res)
위 코드에서 res 를 출력해보면, 의도했던대로 모든 div tag 항목이 저장되어 있는 것을 확인 할 수 있습니다.
위와 같이 1차적으로 Parsing 이 되었고, 완벽하게 영화 제목만 가져오기 위해 다시한번 파싱을 해줍니다.
동일 Tag 로 잘 분리가 되어있다면, get_text() 를 이용해 해당 tag 에서 text 정보면 가져올 수 있습니다.
그래서 최종적으로 완성된 코드는 아래와 같이 간단합니다.
if __name__ == "__main__": soup = BeautifulSoup(urllib.request.urlopen('http://movie.naver.com/movie/sdb/rank/rmovie.nhn?sel=pnt&date=20161120').read(), 'html.parser') res = soup.find_all('div', 'tit5') for n in res: print(n.get_text())
결과를 출력해 보면 원하는 데로 제목만 잘 출력이 되었습니다. ^^
결과적으로, 네이버 페이지에 있는 많은 영화 제목들을 단 몇줄로 간단하게 출력해본 예제입니다.
예제는 네이버 페이지이지만, 다양한 사이트에서 원하는 정보를 뽑아낼 때 활용할 수 있겠습니다.