9장 연습 문제 12번

상당히 까다롭던 문제이다. 처음 시작부터 아주 애를 먹었다. 문제는 하나의 url 을 받아서 해당 페이지 및 그 페이지에 연결 되어 있는 확장자가 .html 인 HTML 파일을 디스크에 저장 하는 문제이다.

처음에 이것을 풀기 위해 약간의 테스트를 했었는데, 인코딩 때문에 상당히 애를 먹었다.

한국 대부분의 html 파일들은 utf-8 로 인코딩이 되어 있다. 그러나 파이썬에서는 'mbcs' 로 인코딩하여 출력을 해준다. 이로 인해 페이지 소스와 출력물이 어긋났다.

urllib 모듈을 임포트 하여 print urllib.urlopen('http://bluekyu.textcube.com/').read() 을 하면 소스가 잘 나온다. 하지만 내가 이 문제를 풀기 위해 소스를 한 줄씩 읽기 위해 for line in urllib.urlopen('http://bluekyu.textcube.com/') 으로 하여 print line, 을 했더니 '§' 부분이 '짱' 으로 표시 되는 것이다. ㅡㅡ;;;;

처음에는 읽기에 문제가 있는지 확인 할려고 파이썬 3.1 까지 깔아서 삽질을 했지만 결국 못 알아내고 한국 파이썬 모임에 물어 보니 인코딩 문제라고 했다.

>>> print '\xc2\xaf'.decode('cp949').encode('utf-8')


위 코드에서 \xc2\xaf 는 utf-8 코드로 '§' 을 의미 한다. 그러나 파이썬에서 저 코드를 cp949(mbcs) 로 받아 들이면 유니코드로 '짱' 이라는 의미가 된다.

어쨌든 인코딩 때문에 애를 먹고, 어차피 파일로 저장하므로 인코딩에 신경 쓰지 않고 코딩을 했다.

import os, urllib, urlparse, re

def regu(urlstring) :
    if urlstring[-1] == '/' :
        return urlstring[:-1]
    return urlstring

def url_Add(add_url) :
    global urllist
    if add_url not in urllist :
        urllist.append(add_url)

def makedir(link, flist) :
    if len(flist) > 0 :
        k = flist.pop(0)
        if not (os.path.exists(link + '/' + k)) :
            os.mkdir(link + '/' + k)
        makedir(link + '/' + k, flist)

urllist = [regu(raw_input('Input URL : '))]
os.mkdir('./htmlpage')

for url in urllist :
    flink = url.split(urllist[0])[-1]
    makedir('./htmlpage/', flink.split('.')[0].split('/')[1:])
    if url == urllist[0] :
        f = open('./htmlpage/' + url.split('http://')[-1] + '.html', 'w')
    else :
        f = open('./htmlpage' + flink.split('.')[-2] + '/' + flink.split('/')[-1], 'w')
    for line in urllib.urlopen(url) :
        f.write(line)
        url_2 = re.search(r'href(\s?)=(\s?)"(.*?).html"', line) or re.search(r'href(\s?)=(\s?)"(.*?).htm"', line)
        if url_2 :
            addurl = regu(url_2.group().split('"')[-2])
            if re.search('http:', addurl) :
                if re.search(urllist[0], addurl) :
                    url_Add(addurl)
            else :
                url_Add(urllist[0] + '/' + addurl)
상당히 긴 코드인데, 이거 푸느라 시간이 상당히 많이 걸렸다.

이 문제를 푸는 방법은 html 의 소스에서 <a> 태그를 이용하는 방법이다. 페이지 링크는 <a> 태그에 href 속성에 걸려 있으므로 href 에 걸려 있는 링크를 정규식으로 추출하고 저장했다.

문제를 풀다보니 처음에 입력한 url 의 페이지에 있는 링크 외에도 링크가 연결된 페이지에 존재하는 링크의 페이지도 저장을 했다. 그리고 여기에다가 디렉토리 구조도 같은 구조로 만들었다.


ps. 잘 되는 줄 알았는데, 약간 작동이 잘 안되는 것 같다.

댓글 없음:

댓글 쓰기