본문 바로가기
개인프로젝트 후기/열린강좌 다운로더

서울대학교 열린강좌 다운로더 개발후기

by GiraffeB 2018. 1. 23.

서울대학교 열린강좌 다운로더 개발후기


#1. 제작동기


서울대학교 열린강좌 동영상을 스트리밍해서 보는데 몇가지 불편한 점이 있었음.
1) 네트워크 상황이 열악해지면 아무것도 할 수 없음
- 카페에서 공부하는데 네트워크가 가장 안정적이던 스타벅스에서도 사람이 많거나,
네트워크가 불안정해지는 경우가 있었음.
2) 기본으로 제공하는 플레이어는 볼륨이 매우 부족했음
- 노트북 볼륨을 거의 최대로 하더라도 외부소음대비 소리가 매우 작았음.
- 이어팟으로 들을때는 오픈형이라는 단점
- mc5로 들을때는 내부 저항이 높아 볼륨얻기가 힘들었음

3) 보다가 중단한 영상을 다시 볼 때, 시간이동이 매우 느리고 답답했음.



##1-1 이런 단점들을 해결하기 위해서 몇가시 시도한 것은

1) 팟 플레이어로 링크를 끌어서 보기
- 볼륨 부분은 해결할 수 있었음.
- 그러나 기능적으로 제공하는 시간이동이나 끊김은 네트워크의 한계로 여전히 답답했음
2) 집에서 하기

- 네트워크가 상대적으로 빵빵하나, 내 의지가 끊김.




#2. 준비과정 or 혹은 해결과정

##1. 동영상 주소를 찾아보자.
동영상을 가져오는 건 크롬 개발자도구로 영상 부분을 찍어보면서 조사했다.

플래시를 쓴다는건 알았는데, 다운로드하는 주소를 어떻게 알 수 있나.

1) 플래시 다운로더로 검색해서 이것저것 다운로더들을 보다가 RTMP프로토콜을 사용 중인 것을 확인함.
2) 다운로드 주소를 얻기 위해서 크롬 개발자도구로 소스를 찍어보기 시작함. 검색을 통한 분석 끝에 streamer와 file 파라미터를 합치면 그게 원하는 주소인 것을 확인.
3) rtmpdump라는 툴에 다운로드 주소를 지정해주면 받아지는 것을 확인.
4) 팟플레이어로 돌려보니 원하는 것들이 해결됨.


##2. 여러 강의들을 모두 다운로드하자.
60개 정도되는 강의를 일일이 이렇게 찾아서 받을 수는 없으니, 강의목록의 링크를 가져와보기로 했다.
python의 beautifulsoup라는 도구가 크롤링에 많이 쓰인다고 해서 사용했다.

크롤링에서 난관은 간단히 beautifulSoup튜토리얼을 따라하며 크롬 개발자 도구에서 찍어봤던 그 엘리먼트를 찾는데 없다고 나온다. 찾을 수가 없다는 거다. 뭐가 문제인지 모르고 싸메다가 찾은 것.

1) beautifulsoup만으로는 자바스크립트에서 동적으로 가져오는 부분은 얻을 수 없다. 는 점이었다.

자바스크립트에서 동적으로 가져오는 부분을 얻기 위해선 웹브라우저가 필요했다. 즉 자바스크립트가 작동하는 환경이 필요했다. 이런 도구에 Selenium이 있다고 알게 되었다. 

결과적으로 Selenium과 BeautifulSoup를 이용해서 해당 강의의 모든 페이지 링크를 얻었고, 
이 링크들을 순차적으로 방문하면서 강의명, 동영상 다운로드 주소를 파일로 저장해놓았다.



##3. python 멀티 쓰레드? 프로세싱.
수집한 주소들로 rtmpdump를 사용하니 잘 받아졌다.
그러나 다운로드 속도가 스트리밍으로 강의를 보기엔 적절했으나, 모든 강의를 다 받기엔 너무 느렸다.
그러니 여러개를 동시에 받으면 어떨까, 속도저하가 있나 확인해보았다.

내가 rtmpdump를 4개정도 띄워서 주소를 입력하니 각각의 최대 속도에 큰 영향없이 병렬로 잘 받아지더라.
이것을 프로그래밍하기로 했다.

python에서 멀티쓰레딩으르 찾아보니, GIL이라는 키워드가 나왔다.
일반적인 cpython에서 쓰레드는 한번에 하나만 돌 수 있다고 한다. 그래서 동시에 멀티코어에서 작동시키려면 멀티 프로세싱 방법으로 구현한다고 한다.

그래서 낑낑대며 그렇게 구현했다. 강의목록을 각 프로세스들에게 공유자원으로 넘겨두고 동시에 같은 영상을 받지 않도록 락이 구현된 큐를 이용했다.

사실 글을 정리할때 생각해보니, 순차적으로 하나씩 돌아가는 쓰레드여도 상관이 없는게, rtmpdump라는 프로세스만 여러개 돌아가고 강의다운로드 리스트만 충돌없이 소비하면 되는 거라서 thread여도 전혀 문제 없었겠다 싶다.
이래서 지식을 어설프게 알면 안되는걸까.

그렇게 최대 4개로 동시다운로드 가능하도록 멀티 프로세싱을 구현했다.



#3. 의외의 파일이름 문제( 인코딩 문제 )

사실 만났던 문제 중 제대로 처리하지 못한 부분은
해당 사이트에 적힌 강의명으로 파일이름을 지정하고 저장하는 부분에서 파일이름에서 에러가 발생한 부분이었다.
이제와서 분류해보니
1) windows filesystem에서 file/directory name에 사용하지 못하는 문자들이 있음
2) windows default character encoding인 ms949와 web에서의 utf-8과의 차이점
3) chracter encoding이라는 개념의 부족으로 어디서 문제가 발생하는지 제대로 추적 못함.
이었다.

주먹구구식으로 문제되는 문자들을 바꾸는 처리를 하고나서
나중에 인코딩에 대해서 공부한뒤 코드를 다시 보니 문제되는 부분은 파일 입출력을 할때 인코딩을 지정해 주지 않은 부분이었다.

웹에서는 utf-8로 가져와 놓고 윈도우에서 저장할때는 기본 문자 인코딩으로 열어서 ms949로 열린거였다.
참 알고나면 단순하고도 단순한 문제였다는 점.




#4. github에 올리면서

##1. unittest
코드를 기능단위로 쪼개고 정리하면서 unittest툴을 써봤는데,
나를 위해서 검증하면서 코딩하는 것은 정말 적절하다고 느꼈다.
게다가 남겨두었다고 나중에 다시 코드를 볼때 이해를 돕는 기능도 있는 것 같다.

##2. setup.py
배포라는 개념없이 내 코드를 단순히 올려놓았는데,
다른 분들 소스를 찾아보니, 필요한 라이브러리들을 명시하고 받을 수 있도록 하는 기술부분들이 있더라.
작동을 위해 필요한 라이브러리, 버전등을 명시하는게 나중에 서버에서도 필요할 것 같고
java gradle이 이런 역할을 하는 것 같고.
너무 아무생각 없이 만들지 않았나 생각이 들었다.

물론 있다는 정도만 몇개의 글을 살펴봤지 학습하지는 않았다.




#5. 무엇을 얻었나

내가 필요로 하는 프로그램을 작성해본 또 하나의 경험이었다는 것.
내 생각을 내가 만난 문제들을 주체적으로 해결하는 경험이었다는 것
몇개월전에 만든 코드를 다시보면서 깨끗한 코드가 유지보수에 너무나 중요하나는 것

유닛테스트는 오류나 예외의 검증뿐만 아니라 코드 이해해도 도움이 될 것 같다는 점