정보공간_1

[6기 부산 정희록] Beautiful Soup #2 본문

IT 놀이터/Elite Member Tech & Talk

[6기 부산 정희록] Beautiful Soup #2

알 수 없는 사용자 2014. 9. 10. 15:33

Beautiful Soup #2

이번 시간에는 Beautiful Soup를 이용해서 간단하게 쇼핑몰의 내용을 가져와보도록 하겠습니다. 쉽게 설명드리면 쇼핑몰의 사이트를 웹 클라이언트를 통해 접속하고 접속된 웹클라이언트를 통해 HTML FILE을 파싱하여 우리가 원하는 내용을 가져오는 단계까지만 진행해보도록 하겠습니다.


직접 수동으로 익스플로러나 크롬으로 해당 웹페이지를 접속하여 HTML파일을 구할수도 있겠지만 매번 하기에는 상당히 손이 많이가는 작업입니다. 파이썬에서 기본으로 제공하는 urllib를 사용해도 되지만 제가 추천드리는 방법은 Mechanize를 사용하여 웹 클라이언트를 사용하는 것을 추천드립니다.

mechanize도 마찬가지로 urllib2를 통해 웹 클라이언트기능을 수행하지만 래핑되어 있어서 훨씬 개발자가 사용하기 간편하게 설계되어 있습니다.

앞서 설명드린 내용(Beautiful Soup #1)에서  Beautiful Soup를 활용하기 위한 Document가 있어야 되는데 이 Document는 자신의 로컬컴퓨터에 있거나 웹사이트의 주소에서 다운을 받아야 합니다. 이런 일련의 작업을 Python 코드상에서 하기 위한 웹 클라이언트 혹은 간단한 웹브라우징을 하기위한 mechanize를 통해 URL 접속을 한후 Document를 접근할수 있습니다.



mechanize에 대한 간단한 Reference에 대한 설명을 드리면 mechanize.Browser 와 mechanize.UserAgentBase는 urllib2 인터페이스를 구현한것입니다. http뿐만 아니라 어떠한 URL도 열수 있으며 cookie나 redirection 그리고 robots.txt도 다룰수 있습니다. HTML form을 쉽게 파일링 할수 있으며 link parsing과 link follwong도 편리하게 할수 있으며 Browser가 제공하는 history 기능(.back() 과 .reload())도 활용이 가능합니다. head와 body를 쉽게 분리할수 있습니다. 특히 robots.txt를 다룰 수 있기 때문에 사이트마다 크롤링하지 못하도록 막은 사이트도 쉽게 크롤링이 가능하기 때문에 강력한 라이브러리입니다.

본격적인 파싱에 들어가기 전에 간단하게 mechanize에 대한 예제를 보여드리겠습니다.

그림에는 생략되어 있지만 mechanize 모듈을 임포트를 하고나면 mechanize를 사용할수 있는데, mechanize를 통해 URL을 open을 해야합니다. 현재는 http://www.shopmall.com/ 이라는 사이트를 mechanize가 접속을 하게되고, 접속된 사이트에서 링크의 텍스트부분이 'cheese\s*shop' 인것중에서 2번째 링크를 선택하여 링크를 따라간후의 결과를 response1 에 저장합니다. 여기서 \s 라는 파이썬 정규식이 들어가는데 간단하게 설명드리자면 WhiteSpace(화이트 스페이스)를 포함하는 문자입니다. 
즉 cheese *shop = cheese   *shop = cheese\t*shop = cheese\n*shop 모두 cheese\s*shop 정규식으로 표현이 가능하다는 얘기입니다. 화이트 스페이스인 {스페이스, 탭, 엔터, 라인피드...}등을 하나로 표현하기 위한 정규식을 사용하였고, nr=1 이라는 2번째 파라메터는 기본옵션이 nr=0 인데 찾은 링크들중에서 몇번째 index인지를 나타내는 파라메터 입니다. default는 0이라서 mechanize가 링크를 찾은 항목들중에서 nr값에 따라서 링크를 선택하게 됩니다. 

다음 예제를 보면 mechanize의 강력함을 좀더 알수 있습니다.

웹을 조금이라도 해보셨으면 직관적으로 무슨 Action을 취하는지 쉽게 알수 있을텐데요.. 코드흐름대로 간단하게 설명드리자면..
1. 이름이 "order"인 폼을 선택
2. 폼중에 "cheese" 라는 카테고리에 "mozzarella"와 "caerphilly" 항목을 매핑. (체크박스 정도로 생각하시면 됩니다.!)
3. submit을 통해 폼 전송
4. submit 하기전의 화면으로 돌아감.
5. back() 한후의 데이터를 들고온다.(치즈항목에서 "mozzarella"와 "caerphilly" 항목이 선택된상태)
6. browser를 재로드(refresh)

웹에서 기본적으로 이루어지는 폼선택및 폼전송, 폼의 데이터 채우기등의 예제입니다. 직관적인 함수이름및 간편한 interface이므로 추가적인 설명은 필요없을듯하여 넘어가겠습니다.



자 다음은 브라우저의 링크들중에서 링크의 경로가 python.org인 링크들을 한번씩 탐색해보는 간단한 예제입니다.


이상으로 간단하게 mechanize의 활용에 대해서 설명해 드렸고, 이 포스트의 주제인 Beautiful Soup에 대해서 계속 설명해드리겠습니다. 넘어가기전에 한가지 짚고넘어가야 할 점은 mechanize는 Python 2.7까지만 지원을 하고 3.x 버전에서는 아직까지는 지원을 하지 않고 있습니다. Python 3.x 버전을 사용하고 계시는 분들은 mechanize 대신  selenium 모듈을 설치하셔서 비슷하게 사용하시면 됩니다. 

일단 예제로 제가살고 있는 지역의 아울렛 매장의 이벤트 정보를 한번 가져와보겠습니다.

일단 이벤트 정보 페이지의 화면입니다. 간단하게 이미지와 텍스트로 구성되어 있고, 이미지를 누르면 해당 이벤트에 대한 디테일한 정보 페이지로 넘어가는 구조로 되어 있습니다. 각 이미지에 대한 html 구조를 알기 위해 요소검사를 해보았습니다.


마찬가지로 html도 간단한 구조로 되어 있습니다. 그림으로 간략하게 구조를 표현하면 다음과 같습니다.

 div -> ul -> li -> a -> span -> img 이런식의 계층구조로 되어 있는데 저희가 원하는건 일단은 img 파일입니다. 여기서 우리가 원하는 이미지 태그를 가져오기 위해서 지난시간에 했던 Beautiful Soup를 사용해 보겠습니다.

저희가 필요한건 사실 img 태그 그 자체이기 때문에 Beautiful Soup의 find_all 메서드를 통해서 가져올수도 있습니다. find_all 메서드를 통해 태그가 img 인 태그만 가져오면 간단하게 가져올수는 있겠지만 html 파일에서 우리가 원한 img 뿐만 아니라 해당 url의 모든 img를 가져오기 때문에 가져온 img중에 직접 파싱을 하는 방법도 있습니다. 그럼 한번 img 파일만 가져와보겠습니다.

 br 객체는 mechanize를 통해서 가져온 객체이며 BS를 통해 가져온 soup 객체는 Beautiful Soup를 통해 가져온 객체입니다.
Beautiful Soup를 통해 태그가 img 인 태그들만 가져와서 그 리스트들을 모두 출력해본 결과입니다.


물론 저희가 원하는 이미지도 중간에 있기는 하지만 너무나도 많은 img 태그가 존재하고 속성도 거의 대부분 비슷합니다. 하나의 alt 속성과 src 속성을 가지고 있어서 원하는 img 태그만 가져오기는 쉽지않은 일입니다. 하지만 우리는 그전에 우리가 원하는 img 태그의 계층적인 구조를 파악했기 때문에 다른 방법으로 원하는 img 태그를 한번 가져와보겠습니다.


Lst 리스트를 만드는 부분만 달라졌지만 우리가 원하는 결과를 출력할수 있습니다. 그리고 3번째 라인을 보시면 br.set_handle_robots(False) 라는 부분이 있는데 우리가 크롤링하는 과정에서 사이트들마다 robots.txt 를 통해 웹데이터 수집에 대한 설정을 바꿔놓거나 접근을 못하게 하는 사이트들이 있는데 이 설정을 과감하게 무시하여 웹클라이언트(mechanize)를 해당 사이트에 접근가능하게 해주는 설정입니다. 이 설정을 해놓지 않으면 robots.txt 를 통해 웹데이터 수집을 금지해놓은 사이트에서는 html 파일을 불러오지 못하거나 error에 관련된 접근권한 요청을 하는 html 파일을 불러오게 되는 경우가 있으므로 주의하여 사용해야 됩니다.

바뀐 find 부분을 보시면 div 태그 중에서 class 속성이 list_a4_new 라는 속성을 가진 div 태그를 가져온 후에 그 태그 밑의 img 태그들만 가져오게 수정하였습니다. 따라서 출력 결과는 ~


이런식으로 우리가 원하는 태그만 가져올수 있습니다.. 
mechanize 에 대한 설명이 길어져 다음포스트에 Beautiful Soup에 대한 내용을 추가하여 Beautiful Soup에 대한 내용을 마무리 짓도록 하겠습니다.