tubeNick - Download youtube videos


/ Published in: Python
Save to your folder(s)

Tool to download youtube videos with STDIN (PIPE) support for playlist parsers like umph or youParse

(PYTHON3+)


Copy this code and paste it in your HTML
  1. #!/usr/bin/python3
  2.  
  3. # Name: tubeNick.py
  4. # Version: 1.5
  5. # Author: pantuts
  6. # Description: Download videos from youtube.
  7. # Use python3 and later.
  8. # Agreement: You can use, modify, or redistribute this tool under
  9. # the terms of GNU General Public License (GPLv3). This tool is for educational purposes only.
  10. # Any damage you make will not affect the author.
  11. # Send bugs to above email.
  12. # Usage: python3 tubeNick.py youtubeURLhere
  13. # Download: https://sourceforge.net/projects/tubenickdownloa/
  14.  
  15. import re
  16. import urllib.request
  17. import urllib.error
  18. import sys
  19. import time
  20.  
  21. COLON = '%253A'
  22. BACKSLASH = '%252F'
  23. QMARK = '%253F'
  24. EQUALS = '%253D'
  25. AMPERSAND = '%2526'
  26. PERCENT = '%2525'
  27.  
  28. MATCHED_LINK = []
  29. SIGNATURE = []
  30. COMPLETE_LINK = []
  31. VIDEO_TYPE = []
  32. VIDEO_RES = []
  33. FINAL_LINK = []
  34.  
  35. sTUBE = ''
  36. final_title = ''
  37. final_url = ''
  38. url = ''
  39. final_f_format = 0
  40. arg_queryf = ''
  41. arg_format = ''
  42. arg_f_format = []
  43.  
  44. ########################################################################
  45.  
  46. def main():
  47.  
  48. global url
  49. global arg_format
  50. global arg_queryf
  51.  
  52. if len(sys.argv) < 2 or len(sys.argv) > 4: return usage()
  53. elif len(sys.argv) == 2:
  54. if sys.argv[-1] == '-h': return usage()
  55. else:
  56. if sys.argv[-1] == '-': url = list(sys.stdin.readlines())
  57. else: url = sys.argv[-1]
  58. elif len(sys.argv) == 3:
  59. for args in sys.argv:
  60. if '-h' in args or '-f' in args: print('\nCommand ERROR...'); exit(1)
  61. if sys.argv[1] == '-q': sys.argv[1] = '-q'; arg_queryf = sys.argv[1]
  62. else: return usage()
  63. if sys.argv[-1] == '-': url = list(sys.stdin.readlines())
  64. else: url = sys.argv[-1]
  65. elif len(sys.argv) == 4:
  66. for args in sys.argv:
  67. if '-h' in args or '-q' in args: print('\nCommand ERROR...'); exit(1)
  68. if sys.argv[1] == '-f': sys.argv[1] = '-f';
  69. else: return usage()
  70. arg_format = sys.argv[2]
  71. if sys.argv[-1] == '-': url = list(sys.stdin.readlines())
  72. else: url = sys.argv[-1]
  73. else: return usage()
  74.  
  75. if sys.argv[-1] == '-':
  76.  
  77. i = 0
  78. while i < len(url):
  79. check_url(url[i].split('\\')[0])
  80. i = i + 1
  81. else:
  82. check_url(url)
  83.  
  84. ########################################################################
  85.  
  86. def usage():
  87.  
  88. print('\nUSAGE: python3 tubeNick.py -q [-f format] [URL or [-] STDIN]')
  89. print('Optional arguments:')
  90. print('\t-q \t\tQuery video formats. Use of -f will be invalid.')
  91. print('\t-f format\tSupply queried format. Highest video if blank.')
  92. print('\t-h \t\tPrint this.')
  93. print()
  94.  
  95. ########################################################################
  96.  
  97. def check_url(url):
  98.  
  99. global final_url
  100.  
  101. tmp_url = 'http://www.youtube.com/get_video_info?video_id='
  102. invalid = '~`!@#$%^&*()_=+{[}]|\\:;"\'<,>.?/'
  103. tmp_id = ''
  104. final_id = ''
  105. eq = 0
  106. last_id = 0
  107.  
  108. split_url = url.split('/')
  109. tmp_id = split_url[-1]
  110.  
  111. if 'v' not in url: print('[-] URLError: Invalid link.'); exit(1)
  112. if len(url) < 20: print('[-] URLError: Invalid link.'); exit(1)
  113. if 'youtube.com' not in url and url != '-': print('[-] URLError: Youtube URLs only.'); exit(1)
  114.  
  115. if 'watch?v=' in tmp_id:
  116. eq = tmp_id.index('=') + 1
  117. if '&' in tmp_id:
  118. tmp_split = tmp_id.split('&')[0]
  119. final_id = tmp_split[eq:]
  120. else: final_id = tmp_id[eq:]
  121.  
  122. # the video id for requesting get_video_info
  123. final_url = tmp_url + final_id
  124.  
  125. if final_url:
  126. con = 'Connecting...\n'
  127. i = 0
  128. while i < len(con):
  129. sys.stdout.write(con[i])
  130. sys.stdout.flush()
  131. time.sleep(0.01)
  132. i = i + 1
  133.  
  134. connection(final_url)
  135.  
  136. ########################################################################
  137.  
  138. def connection(final_url):
  139.  
  140. global sTUBE
  141.  
  142. try:
  143. req = urllib.request.Request(final_url)
  144. req.add_header('User-Agent', 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:16.0) Gecko/20100101 Firefox/16.0')
  145. yTUBE = urllib.request.urlopen(req)
  146. sTUBE = str(yTUBE.read())
  147.  
  148. except urllib.request.URLerror as e: print(e.reason); exit(1)
  149.  
  150. if sTUBE:
  151. rep_page(sTUBE)
  152.  
  153. ########################################################################
  154.  
  155. def rep_page(sTUBE):
  156.  
  157. REP_STR = [COLON, BACKSLASH, QMARK, EQUALS, AMPERSAND, PERCENT]
  158. if REP_STR[0] in sTUBE:
  159. sTUBE = sTUBE.replace('%253A', ':')
  160. if REP_STR[1] in sTUBE:
  161. sTUBE = sTUBE.replace('%252F', '/')
  162. if REP_STR[2] in sTUBE:
  163. sTUBE = sTUBE.replace('%253F', '?')
  164. if REP_STR[3] in sTUBE:
  165. sTUBE = sTUBE.replace('%253D', '=')
  166. if REP_STR[4] in sTUBE:
  167. sTUBE = sTUBE.replace('%2526', '&')
  168. if REP_STR[5] in sTUBE:
  169. sTUBE = sTUBE.replace('%2525', '%')
  170.  
  171. crawl_youtube(sTUBE)
  172.  
  173. ########################################################################
  174.  
  175. def crawl_youtube(sTUBE):
  176.  
  177. global VIDEO_TITLE
  178. global MATCHED_LINK
  179. global SIGNATURE
  180. global COMPLETE_LINK
  181. global VIDEO_TYPE
  182. global VIDEO_RES
  183. global final_title
  184. global final_f_format
  185. global arg_f_format
  186.  
  187. # get title
  188. vid_title = re.search(r'title=\w.+', sTUBE)
  189. if vid_title:
  190. the_title = vid_title.group()
  191. if '&' in the_title:
  192. tmp_title = the_title.index('&')
  193. else: tmp_title = len(the_title) - 1
  194. f_title = the_title[6:tmp_title]
  195. final_title = f_title.replace('+', ' ')
  196. for per_num in ['%21','%22','%23','%24','%25','%26','%27','%28','%29',\
  197. '%2D','%5F','%3D','%2B','%5B','%7B','%7D','%5D','%7C','%5C',\
  198. '%3A','%3B','%2C','%3C','%3E','%2E','%3F','%2F']:
  199. if per_num in final_title:
  200. final_title = final_title.replace(per_num, '')
  201. else: print('[-] ERROR: Can\'t find video title. Title set to default.'); final_title = 'DownloadYTube'
  202.  
  203. # get links
  204. match = re.findall(r'http://\w.+?cp.+?video.+?quality.+?3D\w.+?%', sTUBE)
  205. if match:
  206. for mat in match:
  207.  
  208. MATCHED_LINK.append(mat)
  209.  
  210. # get signature
  211. find_sig = re.search(r'sig+\S.+quality', mat)
  212. if find_sig:
  213. c_sig = find_sig.group()
  214. final_sig = c_sig[6:-10]
  215. SIGNATURE.append(final_sig)
  216. #print(final_sig)
  217.  
  218. # for link / get last characters [id]
  219. if 'id=' in mat:
  220. y_index = mat.index('id=')
  221. id_last = y_index + 19
  222. li = mat[:id_last]
  223. COMPLETE_LINK.append(li)
  224.  
  225. # get video type
  226. if 'video/' in mat:
  227. vid_start = mat.index('video/')
  228. vid_end = vid_start + 11
  229. vid_type = mat[vid_start:vid_end]
  230. for vid_cod in ['flv', 'webm', 'mp4', '3gp']:
  231. if vid_cod in vid_type:
  232. VIDEO_TYPE.append(vid_cod)
  233.  
  234. else: print('[-] URLError'); exit(1)
  235.  
  236. # get formats/resolution
  237. fmt = re.search(r'fmt_list=\S.+?\&', sTUBE)
  238. if fmt:
  239. frmt = fmt.group().split('%2F')
  240. for v_format in frmt:
  241. if 'x' in v_format:
  242. VIDEO_RES.append(v_format)
  243. else: print('Can\'t find video formats. '); exit(1)
  244.  
  245. # append and combine video type and resolution
  246. j = 0
  247. while j < len(COMPLETE_LINK):
  248. arg_f_format.append(VIDEO_TYPE[j] + '_' + VIDEO_RES[j])
  249. j = j + 1
  250.  
  251. # if argument is [ -q ]
  252. if arg_queryf:
  253. i = 0
  254. print(final_title)
  255. while i < len(COMPLETE_LINK):
  256. print('[+] ' + VIDEO_TYPE[i] + '_' + VIDEO_RES[i])
  257. time.sleep(0.04)
  258. i = i + 1
  259. flush()
  260.  
  261. else:
  262.  
  263. # if argument is [ -f ] and the default format
  264. if arg_format is not None and arg_format in arg_f_format:
  265. final_f_format = arg_f_format.index(arg_format)
  266. elif arg_format not in arg_f_format and len(sys.argv) != 2:
  267. print('\n' + arg_format + ' not in video formats.')
  268. exit(1)
  269. else:
  270. final_f_format = 0
  271.  
  272. final_download_link()
  273.  
  274. ########################################################################
  275.  
  276. def final_download_link():
  277.  
  278. global FINAL_LINK
  279.  
  280. i = 0
  281. while i < len(COMPLETE_LINK):
  282. FINAL_LINK.append(COMPLETE_LINK[i] + '&signature=' + SIGNATURE[i])
  283. i = i + 1
  284.  
  285. download()
  286.  
  287. ########################################################################
  288.  
  289. def download():
  290.  
  291. req = urllib.request.Request(FINAL_LINK[final_f_format])
  292. req.add_header('User-Agent', 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:16.0) Gecko/20100101 Firefox/16.0')
  293. try:
  294. tmp_req = urllib.request.urlopen(req)
  295. tmp_size = tmp_req.getheader('Content-Length')
  296. size = int(tmp_size)
  297.  
  298. print('Downloading...')
  299.  
  300. # for reporthook in urlretrieve, 3 arguments needed
  301. def download_progress(counter, bsize, size):
  302. prog_percent = (counter * bsize * 100) / size
  303. sys.stdout.write('\r' + final_title.replace(' ', '') + '.' + VIDEO_TYPE[final_f_format] + \
  304. ' .......................... %2.f%%' % int(prog_percent))
  305. sys.stdout.flush()
  306.  
  307. urllib.request.urlretrieve(FINAL_LINK[final_f_format], (final_title.replace(' ', '') + \
  308. '.' + VIDEO_TYPE[final_f_format]), reporthook=download_progress)
  309. print('\nDone.')
  310. flush()
  311.  
  312. except urllib.error.HTTPError as e: print('Error downloading : ' + e.reason); exit(1)
  313.  
  314. ########################################################################
  315.  
  316. def flush():
  317.  
  318. del MATCHED_LINK[:]
  319. del SIGNATURE[:]
  320. del COMPLETE_LINK[:]
  321. del VIDEO_TYPE[:]
  322. del VIDEO_RES[:]
  323. del FINAL_LINK[:]
  324.  
  325. sTUBE = ''
  326. final_title = ''
  327. final_url = ''
  328. url = ''
  329. final_f_format = 0
  330. arg_queryf = ''
  331. arg_format = ''
  332. del arg_f_format[:]
  333.  
  334. ########################################################################
  335.  
  336. if __name__ =='__main__':
  337. main()

URL: https://sourceforge.net/projects/tubenickdownloa/

Report this snippet


Comments

RSS Icon Subscribe to comments

You need to login to post a comment.