经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Python3 » 查看文章
python3下载抖音视频的完整代码
来源:jb51  时间:2019/6/5 11:40:41  对本文有异议

python3下载抖音视频的代码如下所示:

  1. # -*- coding:utf-8 -*-
  2. from contextlib import closing
  3. import requests, json, re, os, sys, random
  4. from ipaddress import ip_address
  5. from subprocess import Popen, PIPE
  6. import urllib
  7. class DouYin(object):
  8. def __init__(self, width = 500, height = 300):
  9. """
  10. 抖音App视频下载
  11. """
  12. rip = ip_address('0.0.0.0')
  13. while rip.is_private:
  14. rip = ip_address('.'.join(map(str, (random.randint(0, 255) for _ in range(4)))))
  15. self.headers = {
  16. 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
  17. 'accept-encoding': 'gzip, deflate, br',
  18. 'accept-language': 'zh-CN,zh;q=0.9',
  19. 'pragma': 'no-cache',
  20. 'cache-control': 'no-cache',
  21. 'upgrade-insecure-requests': '1',
  22. 'user-agent': 'Mozilla/5.0 (Linux; U; Android 5.1.1; zh-cn; MI 4S Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.146 Mobile Safari/537.36 XiaoMi/MiuiBrowser/9.1.3',
  23. 'X-Real-IP': str(rip),
  24. 'X-Forwarded-For': str(rip),
  25. }
  26. def get_video_urls(self, user_id, type_flag='f'):
  27. """
  28. 获得视频播放地址
  29. Parameters:
  30. user_id:查询的用户UID
  31. Returns:
  32. video_names: 视频名字列表
  33. video_urls: 视频链接列表
  34. nickname: 用户昵称
  35. """
  36. video_names = []
  37. video_urls = []
  38. share_urls = []
  39. max_cursor = 0
  40. has_more = 1
  41. i = 0
  42. share_user_url = 'https://www.douyin.com/share/user/%s' % user_id
  43. share_user = requests.get(share_user_url, headers=self.headers)
  44. while share_user.status_code != 200:
  45. share_user = requests.get(share_user_url, headers=self.headers)
  46. _dytk_re = re.compile(r"dytk\s*:\s*'(.+)'")
  47. dytk = _dytk_re.search(share_user.text).group(1)
  48. _nickname_re = re.compile(r'<p class="nickname">(.+?)<\/p>')
  49. nickname = _nickname_re.search(share_user.text).group(1)
  50. urllib.request.urlretrieve('https://raw.githubusercontent.com/Jack-Cherish/python-spider/master/douyin/fuck-byted-acrawler.js', 'fuck-byted-acrawler.js')
  51. try:
  52. Popen(['node', '-v'], stdout=PIPE, stderr=PIPE).communicate()
  53. except (OSError, IOError) as err:
  54. print('请先安装 node.js: https://nodejs.org/')
  55. sys.exit()
  56. user_url_prefix = 'https://www.douyin.com/aweme/v1/aweme/favorite' if type_flag == 'f' else 'https://www.douyin.com/aweme/v1/aweme/post'
  57. print('解析视频链接中')
  58. while has_more != 0:
  59. process = Popen(['node', 'fuck-byted-acrawler.js', str(user_id)], stdout=PIPE, stderr=PIPE)
  60. _sign = process.communicate()[0].decode().strip('\n').strip('\r')
  61. user_url = user_url_prefix + '/?user_id=%s&max_cursor=%s&count=21&aid=1128&_signature=%s&dytk=%s' % (user_id, max_cursor, _sign, dytk)
  62. req = requests.get(user_url, headers=self.headers)
  63. while req.status_code != 200:
  64. req = requests.get(user_url, headers=self.headers)
  65. html = json.loads(req.text)
  66. try:
  67. while html['aweme_list'] == []:
  68. i = i + 1
  69. sys.stdout.write('已重新链接' + str(i) + '次 (若超过100次,请ctrl+c强制停止再重来)' + '\r')
  70. sys.stdout.flush()
  71. process = Popen(['node', 'fuck-byted-acrawler.js', str(user_id)], stdout=PIPE, stderr=PIPE)
  72. _sign = process.communicate()[0].decode().strip('\n').strip('\r')
  73. user_url = user_url_prefix + '/?user_id=%s&max_cursor=%s&count=21&aid=1128&_signature=%s&dytk=%s' % (user_id, max_cursor, _sign, dytk)
  74. req = requests.get(user_url, headers=self.headers)
  75. while req.status_code != 200:
  76. req = requests.get(user_url, headers=self.headers)
  77. html = json.loads(req.text)
  78. except:
  79. pass
  80. i = 0
  81. for each in html['aweme_list']:
  82. try:
  83. url = 'https://aweme.snssdk.com/aweme/v1/play/?video_id=%s&line=0&ratio=720p&media_type=4&vr_type=0&test_cdn=None&improve_bitrate=0'
  84. uri = each['video']['play_addr']['uri']
  85. video_url = url % uri
  86. except:
  87. continue
  88. share_desc = each['share_info']['share_desc']
  89. if os.name == 'nt':
  90. for c in r'\/:*?"<>|':
  91. nickname = nickname.replace(c, '').strip().strip('\.')
  92. share_desc = share_desc.replace(c, '').strip()
  93. share_id = each['aweme_id']
  94. if share_desc in ['抖音-原创音乐短视频社区', 'TikTok', '']:
  95. video_names.append(share_id + '.mp4')
  96. else:
  97. video_names.append(share_id + '-' + share_desc + '.mp4')
  98. share_urls.append(each['share_info']['share_url'])
  99. video_urls.append(video_url)
  100. max_cursor = html['max_cursor']
  101. has_more = html['has_more']
  102. return video_names, video_urls, share_urls, nickname
  103. def get_download_url(self, video_url, watermark_flag):
  104. """
  105. 获得带水印的视频播放地址
  106. Parameters:
  107. video_url:带水印的视频播放地址
  108. Returns:
  109. download_url: 带水印的视频下载地址
  110. """
  111. # 带水印视频
  112. if watermark_flag == True:
  113. download_url = video_url.replace('/play/', '/playwm/')
  114. # 无水印视频
  115. else:
  116. download_url = video_url.replace('/playwm/', '/play/')
  117. return download_url
  118. def video_downloader(self, video_url, video_name, watermark_flag=False):
  119. """
  120. 视频下载
  121. Parameters:
  122. video_url: 带水印的视频地址
  123. video_name: 视频名
  124. watermark_flag: 是否下载带水印的视频
  125. Returns:
  126. """
  127. size = 0
  128. video_url = self.get_download_url(video_url, watermark_flag=watermark_flag)
  129. with closing(requests.get(video_url, headers=self.headers, stream=True)) as response:
  130. chunk_size = 1024
  131. content_size = int(response.headers['content-length'])
  132. if response.status_code == 200:
  133. sys.stdout.write(' [文件大小]:%0.2f MB\n' % (content_size / chunk_size / 1024))
  134. with open(video_name, 'wb') as file:
  135. for data in response.iter_content(chunk_size = chunk_size):
  136. file.write(data)
  137. size += len(data)
  138. file.flush()
  139. sys.stdout.write(' [下载进度]:%.2f%%' % float(size / content_size * 100) + '\r')
  140. sys.stdout.flush()
  141. def run(self):
  142. """
  143. 运行函数
  144. Parameters:
  145. None
  146. Returns:
  147. None
  148. """
  149. self.hello()
  150. print('搜索api需要登录,暂时使用UID下载\n分享用户页面,用浏览器打开短链接,原始链接中/share/user/后的数字即是UID')
  151. user_id = input('请输入ID (例如95006183):')
  152. user_id = user_id if user_id else '95006183'
  153. watermark_flag = input('是否下载带水印的视频 (0-否(默认), 1-是):')
  154. watermark_flag = watermark_flag if watermark_flag!='' else '0'
  155. watermark_flag = bool(int(watermark_flag))
  156. type_flag = input('f-收藏的(默认), p-上传的:')
  157. type_flag = type_flag if type_flag!='' else 'f'
  158. save_dir = input('保存路径 (例如"E:/Download/", 默认"./Download/"):')
  159. save_dir = save_dir if save_dir else "./Download/"
  160. video_names, video_urls, share_urls, nickname = self.get_video_urls(user_id, type_flag)
  161. nickname_dir = os.path.join(save_dir, nickname)
  162. if not os.path.exists(save_dir):
  163. os.makedirs(save_dir)
  164. if nickname not in os.listdir(save_dir):
  165. os.mkdir(nickname_dir)
  166. if type_flag == 'f':
  167. if 'favorite' not in os.listdir(nickname_dir):
  168. os.mkdir(os.path.join(nickname_dir, 'favorite'))
  169. print('视频下载中:共有%d个作品!\n' % len(video_urls))
  170. for num in range(len(video_urls)):
  171. print(' 解析第%d个视频链接 [%s] 中,请稍后!\n' % (num + 1, share_urls[num]))
  172. if '\\' in video_names[num]:
  173. video_name = video_names[num].replace('\\', '')
  174. elif '/' in video_names[num]:
  175. video_name = video_names[num].replace('/', '')
  176. else:
  177. video_name = video_names[num]
  178. video_path = os.path.join(nickname_dir, video_name) if type_flag!='f' else os.path.join(nickname_dir, 'favorite', video_name)
  179. if os.path.isfile(video_path):
  180. print('视频已存在')
  181. else:
  182. self.video_downloader(video_urls[num], video_path, watermark_flag)
  183. print('\n')
  184. print('下载完成!')
  185. def hello(self):
  186. """
  187. 打印欢迎界面
  188. Parameters:
  189. None
  190. Returns:
  191. None
  192. """
  193. print('*' * 100)
  194. print('\t\t\t\t抖音App视频下载小助手')
  195. print('\t\t作者:Jack Cui、steven7851')
  196. print('*' * 100)
  197. if __name__ == '__main__':
  198. douyin = DouYin()
  199. douyin.run()

总结

以上所述是小编给大家介绍的python3下载抖音视频的完整代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对w3xue网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号