IT is Smart
텍스트마이닝의 첫단계, 웹크롤링 본문
텍스트 마이닝이란
탄광에서 광물을 캐어내 듯이 사람들이 자연스럽게 만들어낸 문장에서 의미있는 정보를 찾아내는 작업을 말합니다.
광물이 많이 포함되어 있는 지역에서 원석들을 캐어내어야 정제를 하더라도 필요한 광물을 더 많이 얻어낼 수 있겠죠. 텍스트 마이닝도 마찬가지입니다. 필요한 정보가 있는 곳(웹사이트)를 찾아서 그 중에서도 내가 얻어내고자 하는 정보가 포함되어 있는 문서(웹페이지)를 수집하는 것이 가장 먼저 해야 할 일입니다.
파이썬을 이용해서 손쉽게 인터넷 상의 정보를 수집하는 기본적인 방법을 알아보겠습니다.
urllib와 BeautifulSoap4를 활용해서 아주 심플하게 예제를 만들어보겠습니다.
urllib는 인터넷에서 웹 상의 문서, 이미지 등 다양한 정보를 가져오는 작업을 쉽게 할 수 있도록 해주는 파이썬 표준 라이브러리입니다. 파이썬만 설치하면 별도의 추가설치가 필요없이 바로 사용할 수 있다는 말입니다.
urllib를 이용해서 수집한 정보는 html태크와 단순텍스트가 구분없이 뒤섞여 있는 상태입니다. 이것을 분리하기 위해서 파서(Parser)라는 것이 필요한데 파이썬에 기본 내장되어 있는 html.parser를 직접 사용해도 되지만, 파싱작업을 좀더 편리하게 해주는 BeautifulSoap이라는 유명한 3rd-party 라이브러리를 사용해서 좀더 쉽게 해결해보겠습니다.
BeautifulSoap은 아래에서 다운로드 받아서 설치할 수 있습니다.
https://www.crummy.com/software/BeautifulSoup/
PyCharm에서 파이썬 파일을 새로 하나 생성합니다. 저는 webcrawler.py 이라고 이름을 지었습니다.
한개의 파일만으로 구현할 것이기 때문이 자유롭게 이름을 지으면 됩니다.
소스코드는 다음과 같이 작성해봤습니다.
from urllib.request import urlopen from bs4 import BeautifulSoup url = 'http://news.naver.com' response = urlopen(url) plain_text = response.read() soup = BeautifulSoup(plain_text, 'html.parser') print(soup)
이렇게 총7라인을 작성해서 실행하면 네이버뉴스 첫페이지에 해당하는 html소스코드를 모두 가져오게 됩니다.
from urllib.request import urlopen from bs4 import BeautifulSoup
은 urllib와 BeautifulSoap4를 사용하겠다고 선언하는 부분입니다.
url = 'http://news.naver.com'
은 얻어내려고 하는 정보가 있는 URL을 변수에 저장해두는 부분입니다.
response = urlopen(url)
은 urllib.request 모듈의 urlopen 함수를 사용해서 앞에서 지정한 url주소로 HTTP Request를 보내는 명령이고,
해당 url의 서버가 정상적으로 응답할 경우 그 HTTP Response를 response라는 변수에 저장하게 됩니다.
이때 HTTP Response는 bytes stream으로 print(response)
로 출력해 보더라도 아래와 같이 보이게 됩니다.
<http.client.HTTPResponse object at 0x00000254E7C95780>
그래서, bytes stream 개체를 문자형으로 변환(decoding)해 줘야 합니다.
plain_text = response.read()
이 명령이 그 작업을 처리해 줍니다.
decoding할 때는 그 문자값이 처음 encoding된 charset으로 다시 decoding해줘야 하는데, 파이썬 프로그램은 자동으로 이 부분을 알아서 처리해줍니다. 만약, 실제 encoding된 charset과 decoding하는 charset이 다른 경우 error가 발생하는데 이 경우는 정확한 encoding charset을 확인해서 강제로 decoding해줘야 합니다.
decoding하는 방법은 다음과 같습니다.
plain_text = response.read().decode('euc-kr')
잘못된 charset으로 decoding하는 경우 다음과 같은 error을 만나게 됩니다.
Traceback (most recent call last):
File "C:/Python/workplace/urlgather/webcrawler.py", line 7, in <module>
plain_text = response.read().decode('utf-8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb3 in position 306: invalid start byte
정상적으로 decoding된 후에 print(plain_text)
로 출력해보면 html문서의 완전한 소스를 볼 수 있게 됩니다.
html소스까지 얻어냈지만 아직은 html태그와 정보 텍스트가 분리되지 않은 상태입니다.
soup = BeautifulSoup(plain_text, 'html.parser')
이 명령을 통해 html태그와 정보 텍스트를 분리할 수 있게 모든 준비가 되었습니다.
print(soup)
으로 출력해보니 print(plain_text)
으로 출력해 본 결과와 크게 달라보이지 않습니다. 뭐가 달라진걸까요?
이제부터 정보를 뽑아내보겠습니다.
print(soup.find('a'))
이렇게 실행해보겠습니다.
<a href="#lnb" tabindex="1"><span>메인 메뉴로 바로가기</span></a>
달랑 한 줄이 출력되었습니다. 소스에서 찾아보니 가장 첫번째 a태그 였네요.
이번에는 다음과 같이 실행해보겠습니다.
print(soup.find_all('a'))
여러 라인의 태그가 쏟아져 나왔습니다.
맞습니다.
find()
은 찾고자 하는 대상을 가장 먼저 나오는 것만 찾아줍니다.
find_all()
은 찾고자 하는 대상 전부를 찾아줬습니다. 추가로 알려드리면 find_all()
은 결과를 자동으로 배열에 넣어서 돌려줍니다.
그래서 다음과 같이 코딩을 해주면 좀더 정리된 모습으로 보여줍니다.
lists = soup.find_all('a') for list in lists: print(list)
이제 <a> 태그가 한줄에 하나씩 정렬이 되서 출력되어 나오지요?
하지만 아직 좀 아쉽습니다. 메뉴내용도 나오고 의미없는 javascript도 리스트되어 나오네요.
얻고 싶은 것은 뉴스 헤드라인과 링크주소인데 말이죠.
이 부분부터는 html소스분석을 해서 범위를 좁혀나가야 합니다.
크롬 브라우저의 개발자도구를 이용하는 방법도 있습니다만, 여기서는 분석과정은 넘어가고 바로 결과를 보겠습니다.
html분석을 통해서
'이시각 주요뉴스' 부분은 class='newsnow_tx_inner'인 div태그에 포함된다는 것을 찾았습니다.
각 뉴스는 <a>태그로 링크되어 있고 뉴스의 헤드라인은 <strong>태그로 구성되어 있었습니다.
코드를 좀더 손을 봤습니다.
lists = soup.find_all('div', class_='newsnow_tx_inner') for list in lists: print(list.find('a'))
실행을 해보니 다음과 같이 결과가 출력되었습니다.
필요없는 태그 정보를 좀더 제거하면 될 것 같습니다.
lists = soup.find_all('div', class_='newsnow_tx_inner') for list in lists: print(list.find('a').find('strong').text + " " + list.find('a').get('href'))
코드를 좀더 수정한 후 다시 실행해 봤습니다
와우, 드디어 뉴스 헤드라인과 URL정보를 분리해냈습니다.
실제 크롤링 작업에 필요한 코드는 9라인에 불과했습니다. 상당히 효과적인 도구임을 확인했습니다.
웹크롤링의 개념을 이해하기 위해 생략한 부분이 많습니다만, 기본기를 다지고 부족한 부분에 대한 스터디를 좀더 한다면 더욱 강력한 작업을 할 수 있을 것입니다.
파이썬의 파일 I/O 처리를 추가한다면 크롤링 결과를 txt파일로 생성할 수도 있고,
database 연결을 통해 정보를 축적해서 활용하는 작업도 얼마든지 가능합니다.
가능성은 활짝 열려 있습니다. 적극적인 자세만 있다면 못할 것이 없을 것 같네요. 다음에는 좀더 심화된 작업을 공유해 보겠습니다.
'Programming > Text Mining' 카테고리의 다른 글
웹크롤링 시 HTTP Error 403 Forbidden 해결하기, Solve HTTP Error 403 Forbidden problem (0) | 2016.09.17 |
---|---|
List of HTTP header fields (0) | 2016.09.11 |
BeautifulSoup4 예제 (0) | 2016.09.01 |