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 网络爬虫初级实现代码
Feb 27 Python
Python编码类型转换方法详解
Jul 01 Python
Python内置模块turtle绘图详解
Dec 09 Python
[原创]windows下Anaconda的安装与配置正解(Anaconda入门教程)
Apr 05 Python
在python中只选取列表中某一纵列的方法
Nov 28 Python
Linux下Pycharm、Anaconda环境配置及使用踩坑
Dec 19 Python
详解用Python练习画个美队盾牌
Mar 23 Python
Python如何基于smtplib发不同格式的邮件
Dec 30 Python
基于SpringBoot构造器注入循环依赖及解决方式
Apr 26 Python
Python基于当前时间批量创建文件
May 07 Python
Python字符串对齐方法使用(ljust()、rjust()和center())
Apr 26 Python
Python入门学习之类的相关知识总结
May 25 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作为Shell脚本语言使用
2006/10/09 PHP
谷歌音乐搜索栏的提示功能php修正代码
2011/05/09 PHP
PHP反转字符串函数strrev()函数的用法
2012/02/04 PHP
php explode函数实例代码
2012/02/27 PHP
ThinkPHP模板自定义标签使用方法
2014/06/26 PHP
ThinkPHP分组下自定义标签库实例
2014/11/01 PHP
PHP检测接口Traversable用法详解
2017/12/29 PHP
客户端脚本中常常出现的一些问题和调试技巧
2007/01/09 Javascript
用JavaScript修改CSS属性的代码
2013/05/06 Javascript
微信小程序 基础知识css样式media标签
2017/02/15 Javascript
Js自动截取字符串长度,添加省略号(……)的实现方法
2017/03/06 Javascript
Vue单页应用引用单独的样式文件的两种方式
2018/03/30 Javascript
vue 属性拦截实现双向绑定的实例代码
2018/10/24 Javascript
详解原生JS回到顶部
2019/03/25 Javascript
js字符串处理之绝妙的代码
2019/04/05 Javascript
webpack自动打包和热更新的实现方法
2019/06/24 Javascript
JavaScript中的全局属性与方法深入解析
2020/06/14 Javascript
[01:34]2014DOTA2展望TI 剑指西雅图VG战队专访
2014/06/30 DOTA
[05:39]2014DOTA2西雅图国际邀请赛 淘汰赛7月14日TOPPLAY
2014/07/14 DOTA
[57:31]DOTA2-DPC中国联赛 正赛 SAG vs CDEC BO3 第一场 2月1日
2021/03/11 DOTA
Python环境下安装使用异步任务队列包Celery的基础教程
2016/05/07 Python
selenium+python设置爬虫代理IP的方法
2018/11/29 Python
python把1变成01的步骤总结
2019/02/27 Python
Django 路由控制的实现
2019/07/17 Python
Python多进程编程常用方法解析
2020/03/26 Python
OpenCV利用python来实现图像的直方图均衡化
2020/10/21 Python
CSS3 伪类选择器 nth-child()说明
2010/07/10 HTML / CSS
巴西食品补充剂在线零售商:Músculos na Web
2017/08/07 全球购物
木工主管岗位职责
2013/12/08 职场文书
母亲七十大寿答谢词
2014/01/18 职场文书
小学社会实践活动总结
2014/07/03 职场文书
2016关于学习党章的心得体会
2016/01/15 职场文书
python学习之panda数据分析核心支持库
2021/05/07 Python
详解Python函数print用法
2021/06/18 Python
使用jpa之动态插入与修改(重写save)
2021/11/23 Java/Android
基于redis+lua进行限流的方法
2022/07/23 Redis