Post List

2017년 7월 23일 일요일

[Python 2.7] 파이썬으로 웹 크롤러 만들기 - (멜론 차트 뽑아오기)

이전 포스트에서 파이썬으로 특정 웹사이트의 html 문서를 받는 걸 구현해봤다. (참고 : 파이썬으로 url 접속하기)
이를 바탕으로 웹 크롤러를 만들어 보려한다.

크롤링이란 웹상에 올라온 데이터들 중 원하는 데이터들만 뽑아서 캐가는 기술이다. 해외에서는 crawling 보다는 scrapping이라는 단어를 많이 선택하는 것 같다. 예전에 머신러닝을 위한 데이터들을 모을 때 크롤링을 시도한 적이 있다. 원하는 데이터의 양이 막대하고 찾고자 하는 데이터가 규칙을 가진다면 크롤링은 매우 유용하다.

지금은 멜론 TOP 100 차트의 해당 곡 이름들을 뽑아와 저장하는 코드를 짜봅시다.( 멜론 TOP 100 링크 : http://www.melon.com/chart/index.htm )


1
2
3
4
5
6
7
8
import urllib2
url = "http://www.melon.com/chart/index.htm"
user_agent = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36'
request = urllib2.Request(url, None, {'User-Agent':user_agent})
data = urllib2.urlopen(request).read()
f=open("a.html","w")
f.write(str(data))
f.close()
cs


위의 코드는 멜론 TOP 100 링크로부터 html 문서를 받아오는 코드이다. 여기서 이전 글과 다른 건 user_agent라는 변수를 새로 쓰고 이를 HTTP header에 넣기 위해 urllib2.Request(url,None,{~~~}) 방식으로 값을 넣은 것이 있다.
http header에서 'User-Agent' 값은 client의 웹브라우저에 대한 정보를 담는 공간인데 아무것도 입력하지 않으면 파이썬에서 자동으로 'Python-urllib/2.7' 을 입력하여 http를 보낸다. 문제는 멜론에서 웹브라우저로 접속하지 않은 client들에게 html문서를 보내지 않는다는 것이다. 그래서 실제 크롬 웹브라우저가 가지는 'User-Agent' 값을 넣어 보낸 것이 위와 같다.

 자 이제 본격적으로 크롤링을 해봅시다. 크롤링을 하기 위해선 링크 부분의 html문 특징을 캐치해야한다.!! 위의 코드로 받아온 html 코드를 들여다 보자.


위에서 처럼 차트 순위에 있는 곡 이름 옆에는 <button type="button" class="btn_icon play" title=" 라는 문자열이 공통적으로 있다는 것을 알 수 있다. 그렇다면 data 변수에 저장된 문자열 중에 위 문자열의 위치를 찾고 '재생' 이라는 단어가 나오기 전까지의 문자열을 저장하면 된다.!!! 이 방법으로 코드를 짜보자.

1
2
3
4
5
6
7
8
9
import re
for iterate in re.finditer('<button type="button" class="btn_icon play" title="',data):
    a = iterate.end()
    b = ''
    i = 0
    while data[a+i] != '-':
        b = b+data[a+i]
        i += 1
 
cs

먼저 맨 윗줄에 re 모듈을 import 하자. 이 녀석이 문자열 내에 특정 문자열을 찾아주는 함수를 제공한다. 파이썬 내에 내장함수로 find() 함수가 있는데 이녀석은 특정 문자열이 여러개 있을 경우 최초 발견한 문자열만 찾아주므로 여기선 적합하지 않다.

for 문을 통해 iterate 변수 안에는 re.finditer() 함수의 반환값이 차례로 들어가게 된다. 발견된 특정 문자열의 시작 위치를 알고 싶으면 iterate.start() 로 알 수 있다. 하지만 여기선 특정 문자열의 마지막 위치를 알아야 하므로 iterate.end()를 사용했다.

이제 이를 활용하여 b 변수에 곡이름을 저장하도록 하자. while 문을 통해 a위치(iterate.end()의 반환값)부터 data 를 하나하나 확인하며 b에 저장한다. 그러다가 '-' 라는 문자가 나오면 저장을 끝낸다. 그렇게 되면 b에는 'Ko Ko Bop 재생 '이 저장된다.

우리가 원하는 목표는 b에 'Ko Ko Bop' 이 저장 되는 것이다. 그러므로 '재생'문자열이 나오는 시작위치를 찾아 내고 그 앞까지만 b에 저장하면 된다. 문제는 파이썬이 기본적으로 문자열을 unicode로 인코딩한다는 것이다. 그러므로 한글을 쓸 때 인코딩 문제로 매우 골치아픈 일이 생길 수 밖에 없다. 이를 해결하기 위해 다음과 같이 코드를 짰다.


1
2
3
str1 = unicode(' 재생','euc-kr').encode('utf-8')
= b.find(str1)
= b[0:c]
cs

str1 변수에 ' 재생'이라는 utf-8로 인코딩한 문자열을 저장한다. 이 문자열을 b에서 find() 함수를 통해 시작위치를 c에 저장하고 substring을 통해 b에 0번째 문자부터 c번째 문자까지 저장한다. 그렇게 되면 b에는 'Ko Ko Bop' 저장된다.

완성된 코드 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# -*- coding: cp949 -*-
import urllib2
import re
url = "http://www.melon.com/chart/index.htm"
user_agent = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36'
request = urllib2.Request(url, None, {'User-Agent':user_agent})
data = urllib2.urlopen(request).read()
= open("chart.txt","w")
str1 = unicode(' 재생','euc-kr').encode('utf-8')
num = 1
for iterate in re.finditer('<button type="button" class="btn_icon play" title="',data):
    a = iterate.end()
    b = ''
    i = 0
    while data[a+i] != '-':
        b = b+data[a+i]
        i += 1
    f.write(str(num)+'.')
    f.write(b[0:b.find(str1)]+'\n')
    num += 1
f.close()
cs

파이썬코드가 저장된 폴더 내 chart.txt 파일에 멜론 차트가 번호순으로 저장된다.
짜자자자작~~!!!!

댓글 없음:

댓글 쓰기