본문 바로가기
ETC/싸이월드 클럽 동영상 백업 프로그램

싸이월드 클럽 동영상 백업 프로그램

by 손너잘 2019. 11. 5.
싸이월드의 유통기한이 1년남았다.
대학시절 몸담았던 응원단 동아리의 모든 동영상 및 사진자료들이 싸이월드 클럽에 올라가 있었기에 이를 다운받기 위한 노력의 여정...
 
사진이나 글 등 백업 프로그램은 깃허브에 많이 있으나 유독 동영상은 없었다.
하지만 다운로드받아야 할 동영상이 수백개가 되는 본인은 이를 손으로 다운로드 할 자신이 없었다.
 
먼저 동영상을 파싱하기 위해 분석에 들어갔다.
 
                                           아아 다운받아지고 싶어하는 저 동영상을 보라..!
 
소스를 보아하니 iframe으로 플레이어를 보여주는것을 볼 수 있다.
하지만 해당 url을 접속한다고 동영상 재생이 되지는 않는다.
무언가 다른 데이터가 필요하단 뜻인데..... 

 

해당 페이지를 불러올 때 무슨 데이터를 불러오는지 확인하도록 하였다.
데이터를 보던 중 위와같은 파일 2개를 발견했다. 하나는 동영상을 불러오기 위한 정보들을 xml 형식으로 표현한 파일이고 하나는 우리가 원하던 mp4 파일이다.
이거 일이 쉽게 풀릴것으로 예상됐다.
 
빠르게 코딩을 진행했다.  파이썬을 사용했으며 사용한 라이브라리는 셀레니움, 크롬드라이버, browsermobproxy ...
고안한 파싱 방법은 다음과 같다.
 

 

로컬호스트에 프록시를 하나 만들어 서버와 통신하때 생기는 모든 트래픽을 감시한다. 이 트래픽에서 위에서 찾은 mp4 파일만 추출하여 다운로드 하면 끝!
빠르게 코딩하여 리스트를 뽑아 보았지만..
 
 
없다!!!!!
 
있어야 할 xml파일과 mp4 파일에 대한 정보가 나오지 않는다... 어찌 된 일일까 열심히 고민해 보았다. 그 결과..
이놈이 문제였다... 싸이월드 동영상 플레이어는 플래쉬 기반...
네트워크 트래픽에서 볼 수 있는 해당 자료들은 해당 플래쉬가 실행되어야만 전송되는 자료들이었다..
 
플래쉬가 실행되지 않으면 xml, mp4 파일을 확인할 수 없다.
간단하게 플래쉬를 허용하면 되지 뭐 ㅎ 라고 생각했으나 이는 큰 오산이었다.
크롬, 파이어폭스, IE, 팬텀js 까지 다 시도했으나 플래쉬를 아무것도 허용하지 않았다...
허용 하더라도 "클릭하여 허용"하는수준까지만 허용하기에 셀레니움으로는 플래쉬를 재생시키기란 불가능했다... (낮은 버전의 브라우저로는 가능하지만 버전이 올라가면서 보안이슈때문에 플래시를 아얘 자동재생 못하게 해놨다.)
 
여기서 엄청난 쌩고생을 하다가(플래쉬 허용하는 방법을 찾다가 몇시간을 소비했다...) 문득 모바일 페이지가 생각났다. 
모바일 페이지로 이동..
 
 
안녕? ㅋ ㅋㅋ ㅋㅋㅋ ㅋㅋㅋㅋ ㅋㅋㅋㅋ 개꿀 함수 발견!  loadVideoData 함수 한번 구경이나 해보자
 
우와~~~ 저 주소에다가 저 params를 get으로 던져주면 Url을 주는구나!!?!?
 
그래서 던져줬다.
우와! 주소를 주네!!! (뒤에 v_key가 없으면 영상 재생이 안되니까 중간만 좀 지우면 괜찮겠지..?)
 
우와~~ 잘나오네~~~~
 
근데 또 다른 문제가 있다.  싸이월드 서버가 진짜 갈때까지 갔는지 모바일로 들어가면 에러를 심각하게 내뿜는다..
 
 
진짜 무슨.. 10번중에 6번은 이 에러가 나온다..... 어쩔땐 그냥 몇분동안 접속이 안될때도 있다.
이러면 예외처리를 한다고 하더라도 크롤링이.... 좀...
 
역시... 답에 근접했지만 모바일 페이지도 답이 아닌가.....
그래서 그냥 pc페이지 소스 함 뒤져봤다. 비슷한 부분이 있는지..
 
 
그러다 이런 부분을 찾아냈는데,  iframe으로 감싸져 있던 플레이어 부분이다.
주소창에 쳤을 때 ERROR 만 나오길래 포기하고 넘어갔는데 네트워크 활동쪽에서 살펴보니 우리에게 필요한 정보(동영상에 관한) 를 RESPONSE해주고 있다.
단순 GET으로는 ERROR만 뿜는데 실제로는 데이터를 주는 녀석이라.... 어떤 인자를 주면 이놈이 데이터를 뿜을까 열심히 고민해 봤지만 실패하여 포기하던 찰나...

 

"아... 나 프록시 설치했었지...??"  문득 떠올라서 바로 프록시에서 데이터를 긁어봐 보았다.
 
아... 잘 받아와 진다. 하지만 문제가 또 하나 있다.
동영상의 url 앞부분에는 정체를 알 수 없는 숫자가 들어가게 되는 그 부분을 알아낼 수 가 없다...
아래 주소의 형식에서 물음표 부분이 그 부분이다.
http://mpmedia?????.video.cyworld.com/mov/mov_id[-3:]/mov_id[:4]/mov_id[4:6]/mov_id[6:8]/mov_id[8:10]/M_mov_id.mp4?v_key=v_key
이 부분을 해결하기 위해 주소를 받아올 방법을 계속 찾아봤다.
그러다 위와 같은 함수를 찾게 되는데.
파라메터를 html5_player.php 라는 곳으로 넘겨주면 뭔가 나올것 같다. 코드를 짜 확인해 봤다.
아.. 뭔가 나왔다 소스를 확인해보니
 
 
url을 찾을 수 있었다....... 코딩을 시작하자.
자. 코딩해라 손너잘.
 
난 파이썬이 싫다. 
왜냐면 내가 못하는 언어이기 때문이다
그래도 좋다
왜냐면 다 만들어져 있는게 있기 때문이다.
 
전체 게시물에서 동영상이 올라가 있는게시물 번호만 뽑아와서 영상 다운받는 형식으로 만들었다.
혼자만 쓰려고 만든거라서 불친절하긴 하지만 필요한 개발자 동지여러분은 잘 쓸 수 있을것이라고 믿는다.
필요한 라이브러리들은 import를 참고하여 설치하길 바란다. Windows 기반으로 만들어져 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import urllib.request
from bs4 import BeautifulSoup
 
def download(url, file_name):
     urllib.request.urlretrieve(url, file_name)
     
_CLUBID = '싸이월드 클럽 이이디'
 
from browsermobproxy import Server
 
server = Server("browsermob-proxy경로/browsermob-proxy.bat")
 
proxy = server.create_proxy()
 
from selenium import webdriver
 
co = webdriver.ChromeOptions()
 
 
co.add_argument('--proxy-server={host}:{port}'.format(host='localhost', port=proxy.port))
co.add_argument('--headless')
co.add_argument('--no-sandbox')
co.add_argument('--disable-dev-shm-usage')
 
co.add_experimental_option("prefs", {
  "download.default_directory": r"./",
  "download.prompt_for_download": False,
  "download.directory_upgrade": True,
  "safebrowsing.enabled": True
})
 
driver = webdriver.Chrome(executable_path="chromedriver경로/chromedriver", chrome_options=co)
 
print('login')
driver.find_element_by_id('uid').send_keys('아이디')
driver.find_element_by_id('upw').send_keys('비밀번호')
 
driver.find_element_by_class_name('btn_login').click()
 
print('login fin')
print('goto')
 
 
#목록 가져오기
print('get list')
list=[]
num = 65
while True :
     print('page', num)
     driver.get('http://club.cyworld.com/club/board/general/AllListNormal.asp?cpage='+str(num)+'&club_id='+_CLUBID+'&board_no=0&board_type=1&list_type=0&show_type=5&headtag_seq=&search_type=&search_keyword=&search_block=1')
     src = driver.page_source
     soup = BeautifulSoup(src, 'html.parser')
     tr = soup.find('tbody').find_all('tr', {'class':''})
 
     if tr[0].find('td', {'class':'no_article'}) is not None :
          break
     
     for t in tr :
          img = t.find('td',{'class':'col_title'}).find('img')
          if img is not None and 'ico_attach_movie' in img['src'] :
               _url = t.find('td',{'class':'col_title'}).find('a')['onclick']
               s = _url.find('item_seq=')
               e = _url.find('&cpage')
               list.append(_url[s+9:e])
     num+=1
 
print(list)
 
for item_seq in list :
     
     proxy.new_har('req',options={'captureHeaders': True,'captureContent':True})
     driver.get('http://club.cyworld.com/Club/Board/General/View.asp?club_id=' + _CLUBID + '&item_seq=' + str(item_seq) + '&cpage=1&notice=yes&search_block=1&Scpage=1&board_type=1&list_type=0&show_type=5&headtag_seq=&club_auth=0')
     proxy.har  # returns a HAR
 
     for ent in proxy.har['log']['entries']:
          _url = ent['request']['url']
          if 'video_player_v2.asp' in _url:
              _response = ent['response']
              _content = _response['content']['text']
              break
     
     mov_id_s = _content.find('mov_id')
     mov_id_e = _content[mov_id_s:].find('";')
     v_key_s = _content.find('v_key')
     v_key_e = _content[v_key_s:].find('";')
     
     mov_id = _content[mov_id_s+10:mov_id_e+mov_id_s]
     v_key = _content[v_key_s+9:v_key_e+v_key_s]
     
     
     param = "mov_id="+mov_id+"&v_key="+v_key+"&vs_id=club&width=480&height=384&div_id=divPlayer&player_id=player&pixelRatio=1"
     movie_meta_url = "http://dbi.video.cyworld.com/player2/html5_player.php?" + param
     
     
     src = driver.page_source
     s = src.find('http://mpmedia')
     e = src[s:].find('" type')
     movie_url = src[s:s+e]
     
     print(movie_url)
     download(movie_url, str(item_seq)+'.mp4')
 
print("fin")
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white">cs
 

댓글