python3下载抖音视频的完整代码


Posted in Python onJune 05, 2019

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

# -*- coding:utf-8 -*-
from contextlib import closing
import requests, json, re, os, sys, random
from ipaddress import ip_address
from subprocess import Popen, PIPE
import urllib
class DouYin(object):
 def __init__(self, width = 500, height = 300):
 """
 抖音App视频下载
 """
 rip = ip_address('0.0.0.0')
 while rip.is_private:
  rip = ip_address('.'.join(map(str, (random.randint(0, 255) for _ in range(4)))))
 self.headers = {
  'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
  'accept-encoding': 'gzip, deflate, br',
  'accept-language': 'zh-CN,zh;q=0.9',
  'pragma': 'no-cache',
  'cache-control': 'no-cache',
  'upgrade-insecure-requests': '1',
  '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',
  'X-Real-IP': str(rip),
  'X-Forwarded-For': str(rip),
 }
 def get_video_urls(self, user_id, type_flag='f'):
 """
 获得视频播放地址
 Parameters:
  user_id:查询的用户UID
 Returns:
  video_names: 视频名字列表
  video_urls: 视频链接列表
  nickname: 用户昵称
 """
 video_names = []
 video_urls = []
 share_urls = []
 max_cursor = 0
 has_more = 1
 i = 0
 share_user_url = 'https://www.douyin.com/share/user/%s' % user_id
 share_user = requests.get(share_user_url, headers=self.headers)
 while share_user.status_code != 200:
  share_user = requests.get(share_user_url, headers=self.headers)
 _dytk_re = re.compile(r"dytk\s*:\s*'(.+)'")
 dytk = _dytk_re.search(share_user.text).group(1)
 _nickname_re = re.compile(r'<p class="nickname">(.+?)<\/p>')
 nickname = _nickname_re.search(share_user.text).group(1)
 urllib.request.urlretrieve('https://raw.githubusercontent.com/Jack-Cherish/python-spider/master/douyin/fuck-byted-acrawler.js', 'fuck-byted-acrawler.js')
 try:
  Popen(['node', '-v'], stdout=PIPE, stderr=PIPE).communicate()
 except (OSError, IOError) as err:
  print('请先安装 node.js: https://nodejs.org/')
  sys.exit()
 user_url_prefix = 'https://www.douyin.com/aweme/v1/aweme/favorite' if type_flag == 'f' else 'https://www.douyin.com/aweme/v1/aweme/post'
 print('解析视频链接中')
 while has_more != 0:
  process = Popen(['node', 'fuck-byted-acrawler.js', str(user_id)], stdout=PIPE, stderr=PIPE)
  _sign = process.communicate()[0].decode().strip('\n').strip('\r')
  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)
  req = requests.get(user_url, headers=self.headers)
  while req.status_code != 200:
  req = requests.get(user_url, headers=self.headers)
  html = json.loads(req.text)
  try:
  while html['aweme_list'] == []:
   i = i + 1
   sys.stdout.write('已重新链接' + str(i) + '次 (若超过100次,请ctrl+c强制停止再重来)' + '\r')
   sys.stdout.flush()
   process = Popen(['node', 'fuck-byted-acrawler.js', str(user_id)], stdout=PIPE, stderr=PIPE)
   _sign = process.communicate()[0].decode().strip('\n').strip('\r')
   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)
   req = requests.get(user_url, headers=self.headers)
   while req.status_code != 200:
   req = requests.get(user_url, headers=self.headers)
   html = json.loads(req.text)
  except:
  pass
  i = 0
  for each in html['aweme_list']:
  try:
   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'
   uri = each['video']['play_addr']['uri']
   video_url = url % uri
  except:
   continue
  share_desc = each['share_info']['share_desc']
  if os.name == 'nt':
   for c in r'\/:*?"<>|':
   nickname = nickname.replace(c, '').strip().strip('\.')
   share_desc = share_desc.replace(c, '').strip()
  share_id = each['aweme_id']
  if share_desc in ['抖音-原创音乐短视频社区', 'TikTok', '']:
   video_names.append(share_id + '.mp4')
  else:
   video_names.append(share_id + '-' + share_desc + '.mp4')
  share_urls.append(each['share_info']['share_url'])
  video_urls.append(video_url)
  max_cursor = html['max_cursor']
  has_more = html['has_more']
 return video_names, video_urls, share_urls, nickname
 def get_download_url(self, video_url, watermark_flag):
 """
 获得带水印的视频播放地址
 Parameters:
  video_url:带水印的视频播放地址
 Returns:
  download_url: 带水印的视频下载地址
 """
 # 带水印视频
 if watermark_flag == True:
  download_url = video_url.replace('/play/', '/playwm/')
 # 无水印视频
 else:
  download_url = video_url.replace('/playwm/', '/play/')
 return download_url
 def video_downloader(self, video_url, video_name, watermark_flag=False):
 """
 视频下载
 Parameters:
  video_url: 带水印的视频地址
  video_name: 视频名
  watermark_flag: 是否下载带水印的视频
 Returns:
  无
 """
 size = 0
 video_url = self.get_download_url(video_url, watermark_flag=watermark_flag)
 with closing(requests.get(video_url, headers=self.headers, stream=True)) as response:
  chunk_size = 1024
  content_size = int(response.headers['content-length'])
  if response.status_code == 200:
  sys.stdout.write(' [文件大小]:%0.2f MB\n' % (content_size / chunk_size / 1024))
  with open(video_name, 'wb') as file:
   for data in response.iter_content(chunk_size = chunk_size):
   file.write(data)
   size += len(data)
   file.flush()
   sys.stdout.write(' [下载进度]:%.2f%%' % float(size / content_size * 100) + '\r')
   sys.stdout.flush()
 def run(self):
 """
 运行函数
 Parameters:
  None
 Returns:
  None
 """
 self.hello()
 print('搜索api需要登录,暂时使用UID下载\n分享用户页面,用浏览器打开短链接,原始链接中/share/user/后的数字即是UID')
 user_id = input('请输入ID (例如95006183):')
 user_id = user_id if user_id else '95006183'
 watermark_flag = input('是否下载带水印的视频 (0-否(默认), 1-是):')
 watermark_flag = watermark_flag if watermark_flag!='' else '0'
 watermark_flag = bool(int(watermark_flag))
 type_flag = input('f-收藏的(默认), p-上传的:')
 type_flag = type_flag if type_flag!='' else 'f'
 save_dir = input('保存路径 (例如"E:/Download/", 默认"./Download/"):')
 save_dir = save_dir if save_dir else "./Download/"
 video_names, video_urls, share_urls, nickname = self.get_video_urls(user_id, type_flag)
 nickname_dir = os.path.join(save_dir, nickname)
 if not os.path.exists(save_dir):
  os.makedirs(save_dir)
 if nickname not in os.listdir(save_dir):
  os.mkdir(nickname_dir)
 if type_flag == 'f':
  if 'favorite' not in os.listdir(nickname_dir):
  os.mkdir(os.path.join(nickname_dir, 'favorite'))
 print('视频下载中:共有%d个作品!\n' % len(video_urls))
 for num in range(len(video_urls)):
  print(' 解析第%d个视频链接 [%s] 中,请稍后!\n' % (num + 1, share_urls[num]))
  if '\\' in video_names[num]:
  video_name = video_names[num].replace('\\', '')
  elif '/' in video_names[num]:
  video_name = video_names[num].replace('/', '')
  else:
  video_name = video_names[num]
  video_path = os.path.join(nickname_dir, video_name) if type_flag!='f' else os.path.join(nickname_dir, 'favorite', video_name)
  if os.path.isfile(video_path):
  print('视频已存在')
  else:
  self.video_downloader(video_urls[num], video_path, watermark_flag)
  print('\n')
 print('下载完成!')
 def hello(self):
 """
 打印欢迎界面
 Parameters:
  None
 Returns:
  None
 """
 print('*' * 100)
 print('\t\t\t\t抖音App视频下载小助手')
 print('\t\t作者:Jack Cui、steven7851')
 print('*' * 100)
if __name__ == '__main__':
 douyin = DouYin()
 douyin.run()

总结

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

Python 相关文章推荐
爬山算法简介和Python实现实例
Apr 26 Python
浅谈Python爬取网页的编码处理
Nov 04 Python
Python面向对象class类属性及子类用法分析
Feb 02 Python
Tensorflow 利用tf.contrib.learn建立输入函数的方法
Feb 08 Python
python 获取字符串MD5值方法
May 29 Python
Python中分支语句与循环语句实例详解
Sep 13 Python
python无限生成不重复(字母,数字,字符)组合的方法
Dec 04 Python
Python中的 is 和 == 以及字符串驻留机制详解
Jun 28 Python
为什么说Python可以实现所有的算法
Oct 04 Python
Python 函数绘图及函数图像微分与积分
Nov 20 Python
基于Python获取照片的GPS位置信息
Jan 20 Python
基于django micro搭建网站实现加水印功能
May 22 Python
把JSON数据格式转换为Python的类对象方法详解(两种方法)
Jun 04 #Python
Django集成搜索引擎Elasticserach的方法示例
Jun 04 #Python
python添加菜单图文讲解
Jun 04 #Python
Python3.6+Django2.0以上 xadmin站点的配置和使用教程图解
Jun 04 #Python
Python自动化之数据驱动让你的脚本简洁10倍【推荐】
Jun 04 #Python
pandas DataFrame索引行列的实现
Jun 04 #Python
深入浅析Python中的迭代器
Jun 04 #Python
You might like
模仿OSO的论坛(三)
2006/10/09 PHP
PHP验证码函数代码(简单实用)
2013/09/29 PHP
ThinkPHP3.2.2的插件控制器功能
2015/03/05 PHP
Zend Framework路由器用法实例详解
2016/12/11 PHP
php面试中关于面向对象的相关问题
2019/02/13 PHP
简单实用的反馈表单无刷新提交带验证
2013/11/15 Javascript
jquery操作checkbox实现全选和取消全选
2014/05/02 Javascript
基于JavaScript实现单选框下拉菜单添加文件效果
2016/06/26 Javascript
原生js轮播(仿慕课网)
2017/02/15 Javascript
React-native桥接Android原生开发详解
2018/01/17 Javascript
在 Typescript 中使用可被复用的 Vue Mixin功能
2018/04/17 Javascript
jQuery中的for循环var与let的区别
2018/04/21 jQuery
jQuery实现为动态添加的元素绑定事件实例分析
2018/09/07 jQuery
基于three.js实现的3D粒子动效实例代码
2019/04/09 Javascript
抖音上用记事本编写爱心小程序教程
2019/04/17 Javascript
详解用async/await来处理异步
2019/08/28 Javascript
react quill中图片上传由默认转成base64改成上传到服务器的方法
2019/10/30 Javascript
three.js利用卷积法如何实现物体描边效果
2019/11/27 Javascript
JavaScript oncopy事件用法实例解析
2020/05/13 Javascript
vue data对象重新赋值无效(未更改)的解决方式
2020/07/24 Javascript
小程序实现点击tab切换左右滑动
2020/11/16 Javascript
如何利用Boost.Python实现Python C/C++混合编程详解
2018/11/08 Python
python频繁写入文件时提速的方法
2019/06/26 Python
python中 * 的用法详解
2019/07/10 Python
python实现的config文件读写功能示例
2019/09/24 Python
Pytorch中的VGG实现修改最后一层FC
2020/01/15 Python
国际旅客访问北美最大的汽车租赁提供商:Alamo Rent A Car
2018/06/13 全球购物
Nike香港官网:Nike HK
2019/03/23 全球购物
历史学专业个人的自我评价
2013/10/13 职场文书
应届毕业生个人求职信范文
2014/01/29 职场文书
道路交通安全实施方案
2014/03/12 职场文书
药品营销策划方案
2014/06/15 职场文书
邀请函模板
2015/02/02 职场文书
2015年学校禁毒工作总结
2015/05/27 职场文书
教你用Python+selenium搭建自动化测试环境
2021/06/18 Python
python ConfigParser库的使用及遇到的坑
2022/02/12 Python