많은 내용들이 키=값 형태로 나열되어 있는 것을 확인할 수 있습니다. 일단 동영상을 다운로드 받는다는 목적에만 집중하겠습니다. 잡다한 키는 넘어가고 ''url_encoded_fmt_stream_map'' 이라는 키와 값에만 주목하도록 하겠습니다.
==== 스트림 맵 분석하기 ====
여기서는 ''url_encoded_fmt_stream_map''의 값을 일컬어 '스트림 맵'이라고 부르겠습니다. 스트림 맵의 생짜 값(raw value)은 상당히 긴 문자열인데, 바로 여기에 우리가 원하는 동영상의 실제 주소가 숨겨져 있습니다. 이 문자열은 CSV 형태로 되어 있고, 각 필드의 값은 urlencode가 되어 있습니다. 일단 콤마(,)를 기준으로 문자열 분리를 해야 올바르게 하나의 의미를 가진 덩어리를 나눌 수 있습니다. 우선 당장 프로그래밍을 들이대지 말고 텍스트 편집기를 이용해 차근차근 손으로 해 보도록 하겠습니다.
스트림 맵을 텍스트 편집기로 붙여 넣습니다. 그리고 콤마 문자 하나를 검색합니다. 처음 발견된 콤마를 기준으로 공백을 입력해 값을 위, 아래 두 덩어리로 떼어 냅니다. 추출해 낸 윗부분 덩어리의 처음은 ''itag=XX%%\u0026%%sig=XXX...'' 와 같이 시작하는 것을 확인할 수 있습니다. \u0026은 유니코드 문자임이 분명합니다.
print unichr(0x26)
위 코드를 실행하면 '&' 문자가 출력됩니다. 그러므로 텍스트 편집기에서 \u0026을 찾아 '&'로 변경합니다. 변경할 때 '&' 기호 뒤에 개행 문자까지 넣으면 시각적으로 더 보기 좋겠죠. 그러면 다음과 같이 분리됩니다.
itag=...&
sig=...&
url=...&
fallback_host=...&
quality=...&
type=...,
이제 거의 다 왔습니다. url 부분이 보이죠? 바로 저기가 실제 동영상의 주소입니다. 나머지 분리하지 않은 덩어리도 같은 방식으로 나누어지므로 일일이 나누어 확인해 봅니다. 값을 다 살펴보면 아시겠지만, 서버가 다양한 포맷과 해상도로 인코딩해 놓은 것을 정리한 목록이 이 스트림 맵입니다. 결국 순수하게 HTML 코드 및 자바스크립트만 분석하면 동영상 주소를 찾아낼 수 있는 것이네요. 물론 이 방법이 언제까지 통하리란 보장은 없습니다만, 그렇다고 동영상의 주소를 숨바꼭질하는 것처럼 꽁꽁 숨겨두지는 않을 겁니다.
마지막으로 첫번째 덩어리의 url 부분의 문자열을 한 번 [[http://meyerweb.com/eric/tools/dencoder/|urldecode]]하면 웹브라우저에도 입력 가능한 url 주소가 됩니다. 단, 이 주소를 바로 넣으면 '403 forbidden' 에러가 납니다. 반드시 ''sig''라는 키의 값을 붙여 넣어야 합니다. 주소로 적을 때는 왠일인지 키 이름은 ''sig''에서 ''signature''로 변경됩니다. 이렇게 signature까지 붙여 넣은 주소를 사용하면 동영상에 직접 접근이 가능합니다. 그러므로 이 주소만 있으면 HTTP 스트림 재생을 지원하는 다른 재생기에서도 재생이 가능하며, 우리의 최종 목적인 동영상 다운로드도 가능합니다. 이제 프로그램을 작성하기 위한 모든 준비가 끝났습니다.
===== 코드로 작성 =====
그러면 지금까지 한 내용을 파이썬 코드로 옮겨 보겠습니다. 완전 프로토타입의 코드이므로 쓰기 편하게 만드려면 고쳐야 할 부분이 많습니다. 그러나 일단 복잡한 기능은 배제하여 작동을 확인하는 수준으로 최대한 간결하게 작성해 보겠습니다.
# -*- coding: utf-8 -*-
import urllib
import urllib2
import re
import codecs
import sys
def get_html(url):
# url을 열어 html 문서를 받아옵니다.
# 문서는 utf-8 인코딩입니다.
resp = urllib2.urlopen(url)
html = resp.read().decode('utf-8')
# 인코딩된 문서를 미리 저장하고, 저장된 문서를 이용합니다.
# 일일이 네트워크를 이용해 문서를 받고 싶지 않을 때 사용합니다.
# 적절히 주석으로 조절하세요.
with codecs.open('sample.html', 'w', 'utf-8') as f:
f.write(html)
#with codecs.open('sample.html', 'r', 'utf-8') as f:
# html = f.read()
return html
def extract_format_info(v_value):
# v_value는 동영상의 아이디입니다.
URL_BASE = 'http://www.youtube.com/watch?v='
url = URL_BASE + v_value
html = get_html(url)
# playerConfig의 모든 값을 가져옵니다.
t = re.search(r'yt.playerConfig = {(.+)};', html)
# print t.groups()[0]
# print
# 그 중 스트림 맵 부분만 추출해냅니다.
r = re.search(r'"url_encoded_fmt_stream_map": "(.+?)"', t.groups()[0].strip())
# 스트림맵은 CSV이므로 콤마로 분리합니다.
rawstrings = r.groups()[0].strip().split(',')
items = []
for rawstring in rawstrings:
item = {}
# \uXXXX 부분을 실제 문자열로 변경합니다.
uniesc = rawstring.decode('unicode-escape')
# 실제 문자열로 변경된 부분 중 '&'기호가 있습니다.
# 이것은 재차 키=값 문자열을 분리하는 역할을 합니다.
for oneitem in uniesc.split('&'):
# 키와 값을 분리, 딕셔너리로 저장합니다.
key, val = oneitem.split('=')
item[key] = urllib.unquote(val.strip())
items.append(item)
# 값들을 프린트
#for item in items:
# for it in item.items():
# print it[0]+': '+it[1]
# print
return items
if __name__ == '__main__':
items = extract_format_info(sys.argv[1])
# 동영상을 실제로 받아 봅니다. url과 sig 필드의 값이 필요합니다.
# 영상의 첫번째 항목을 열어 저장합니다.
url = '%s&signature=%s' % (items[0]['url'], items[0]['sig'])
# 쿠키 등의 장치가 필요 없습니다. 단순히 열면 됩니다.
resp = urllib2.urlopen(url)
# 수신 상태를 확인
print resp.info()
# 동영상의 인코딩 상태를 파악하여 다운로드 받는 것이 아니므로
# 동영상 파일의 확장자는 적절히 변경하세요.
f = open('result.flv', 'wb')
f.write(resp.read())
f.close()
resp.close()
소스의 동영상 아이디만 적절히 바꾸면 파일이 다운로드 될 것입니다. 초라한 형태지만 제대로 동작함을 확인할 수 있습니다. 유튜브의 동영상 URL이 ''http://www.youtube.com/watch?v=a1cTyDOuop0''라면
youtube_dn_proto.py a1cTyDOuop0
이렇게 입력하면 됩니다.
===== 마치며 =====
지금까지 간단하게 유튜브 동영상을 다운로드 받는 방법에 대해 조사하고 과정을 기록하였습니다. 다운로드를 할 수 있는 툴은 엄청나게 많지만 그 방법에 대해서 자세하게 소개한 문서가 없어 직접 해 보았습니다. 단순한 궁금증에서 시작했는데 은근히 재밌네요 :-) 기본적인 원리는 HTML 코드 파싱 --> 원하는 정보 추출 --> 다운로드로 별반 다른 것이 없습니다. 여타 프로그램들은 꽤 다양한 옵션들을 제공하고 쓰기도 편리하기도 할 겁니다. 그러나 기본적인 큰 틀은 제가 제시한 방법과 크게 다르지는 않을 것입니다.
마지막으로 파이썬 기반으로 작성된 유튜브와 같은 스트리밍 동영상의 다운로드 CLI 프로그램인 [[http://rg3.github.com/youtube-dl/|youtube-dl]]을 소개하고 문서를 마칩니다. 원클릭으로 실행되는 여타 다른 프로그램들 보다는 조금 불편하긴 합니다만, 유튜브 뿐만 아니라 다른 사이트의 동영상도 다운로드 가능하고, 여러 가지 옵션들이 잘 정리되어 있으며, 무엇보다 소스가 공개되어 있으므로 파이썬 공부를 위해서는 한 번 살펴볼만한 프로그램입니다.