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 27 Python
python实现数组插入新元素的方法
May 22 Python
通过数据库向Django模型添加字段的示例
Jul 21 Python
python多线程socket编程之多客户端接入
Sep 12 Python
Python堆排序原理与实现方法详解
May 11 Python
python 画三维图像 曲面图和散点图的示例
Dec 29 Python
微信小程序python用户认证的实现
Jul 29 Python
Flask框架单例模式实现方法详解
Jul 31 Python
Python Process多进程实现过程
Oct 22 Python
Python绘制全球疫情变化地图的实例代码
Apr 20 Python
Python基于xlrd模块处理合并单元格
Jul 28 Python
python基础详解之if循环语句
Apr 24 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
浅谈PHP接收POST数据方式
2015/06/05 PHP
php发送短信验证码完成注册功能
2015/11/24 PHP
WordPress主题制作中自定义头部的相关PHP函数解析
2016/01/08 PHP
PHP7新功能总结
2019/04/14 PHP
免费空间广告万能消除代码
2006/09/04 Javascript
javascript XMLHttpRequest对象全面剖析
2010/04/24 Javascript
JQuery通过Ajax提交表单并返回结果
2011/07/31 Javascript
IE的有条件注释判定IE版本详解(附实例代码)
2012/01/04 Javascript
jQuery实现Twitter的自动文字补齐特效
2014/11/28 Javascript
jQuery中index()方法用法实例
2014/12/27 Javascript
javascript实现客户端兼容各浏览器创建csv并下载的方法
2015/03/23 Javascript
快速掌握Node.js之Window下配置NodeJs环境
2016/03/21 NodeJs
Seajs是什么及sea.js 由来,特点以及优势
2016/10/13 Javascript
NodeJS 实现手机短信验证模块阿里大于功能
2017/06/19 NodeJs
JS实现小米轮播图
2020/09/21 Javascript
JS实现公告上线滚动效果
2021/01/10 Javascript
Python中使用Inotify监控文件实例
2015/02/14 Python
Python中Django框架利用url来控制登录的方法
2015/07/25 Python
CentOS 6.5中安装Python 3.6.2的方法步骤
2017/12/03 Python
Python使用Matplotlib模块时坐标轴标题中文及各种特殊符号显示方法
2018/05/04 Python
python多进程控制学习小结
2018/10/31 Python
检测python爬虫时是否代理ip伪装成功的方法
2019/07/12 Python
python 写一个文件分发小程序
2020/12/05 Python
HTML5离线缓存在tomcat下部署可实现图片flash等离线浏览
2012/12/13 HTML / CSS
HTML5 Canvas 旋转风车绘制
2017/08/18 HTML / CSS
AmazeUI图片轮播效果的示例代码
2020/08/20 HTML / CSS
伦敦剧院及景点门票:Encore Tickets
2018/07/01 全球购物
BookOutlet加拿大:在网上书店购买廉价折扣图书和小说
2018/10/05 全球购物
瑞典多品牌连锁店:Johnells
2021/01/13 全球购物
知识改变命运演讲稿
2014/05/21 职场文书
应届生自荐信
2014/06/30 职场文书
关于调整工作时间的通知
2015/04/24 职场文书
小学生表扬稿范文
2015/05/05 职场文书
分享:关于学习的励志名言赏析
2019/08/16 职场文书
MySQL8.0.24版本Release Note的一些改进点
2021/04/22 MySQL
python中24小时制转换为12小时制的方法
2021/06/18 Python