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'를 속성으로 가진 항목들에 포함되어 있습니다.

<div class="tit5"> <a href="/movie/bi/mi/basic.nhn?code=17421" title="쇼생크 탈출"> 쇼생크 탈출 </a> </div>

그래서 생성한 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())

결과를 출력해 보면 원하는 데로 제목만 잘 출력이 되었습니다. ^^

결과적으로, 네이버 페이지에 있는 많은 영화 제목들을 단 몇줄로 간단하게 출력해본 예제입니다.

예제는 네이버 페이지이지만, 다양한 사이트에서 원하는 정보를 뽑아낼 때 활용할 수 있겠습니다.

 

 

+ Recent posts