使用python爬取抖音视频列表信息


Posted in Python onJuly 15, 2019

如果看到特别感兴趣的抖音vlogger的视频,想全部dump下来,如何操作呢?下面介绍介绍如何使用python导出特定用户所有视频信息

使用python爬取抖音视频列表信息

抓包分析

Chrome Deveploer Tools Chrome 浏览器开发者工具

在抖音APP端,复制vlogger主页地址, 比如: http://v.douyin.com/kGcU4y/ , 在PC端用chrome浏览器打卡,并模拟手机,这里选择iPhone, 然后把复制的主页地址,放到浏览器进行访问,页面跳转到 https://www.iesdouyin.com/share/user/110677980134

下拉主页, 选择Network=>XHR 选项卡, 看到类似请求

:authority: www.iesdouyin.com
:method: GET
:path: /web/api/v2/aweme/post/?user_id=110677980134&sec_uid=&count=21&max_cursor=1561112910000&aid=1128&_signature=3Xf-nxAQgGfUO4SKisB.Ld13.o&dytk=061ae6e81229e178146aa674327eba89
:scheme: https
accept: application/json
accept-encoding: gzip, deflate, br
accept-language: zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7,zh-TW;q=0.6,da;q=0.5
cookie: tt_webid=6690145457198417412; _ga=GA1.2.605400954.1557670882; _ba=BA0.2-20181226-5199e-GIJXgXk9ajNkyFhmv7Wy; _gid=GA1.2.1914501522.1562857517
referer: https://www.iesdouyin.com/share/user/110677980134
user-agent: Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1
x-requested-with: XMLHttpRequest

返回数据截图

使用python爬取抖音视频列表信息

通过分析ajax请求的URL https://www.iesdouyin.com/web/api/v2/aweme/post/?user_id=110677980134&sec_uid=&count=21&max_cursor=1559299764000&aid=1128&_signature=3Xf-nxAQgGfUO4SKisB.Ld13.o&dytk=061ae6e81229e178146aa674327eba89 得出请求参数主要包含:

字段 类型 说明
user_id int 抖音账号的ID
count int 返回的数据条数,就用默认值21
max_cursor int 请求的游标,每次请求带上上次请求返回的max_cursor
aid int 使用默认值11128
_signature string 每次请求带上的参数签名
dytk string 每次请求带上的一个参数

参数的获取方法:

https://www.iesdouyin.com/share/user/110677980134

(function() {
  $(function(){
    __M.require('douyin_falcon:page/reflow_user/index').init({
      uid: "110677980134",
      dytk: '061ae6e81229e178146aa674327eba89'
    });
  });
})();

通过正则获取到此参数

  • _signature 获取比较复杂,抖音对前端的js代码进行了混淆压缩,不易直接分析出算法过程,不过可以执行签名算法代码,并返回对应的签名结果。
  • 执行js代码的可以使用nodejs或者selenium webdriver,这里推荐使用selenium webdriver , nodejs的js执行环境与浏览器有区别,计算出的签名结果,并不能通过验证,selenium webdriver 可以调用本地浏览器,计算出的签名可以跟浏览器直接访问访问计算出的签名一致。
  • 格式化之后的js代码,点击查看, 执行js方法 _bytedAcrawler.sign("110677980134") 对参数进行签名

代码实现导出主页视频列表

def get_user_video_list_by_uid(user_id, cursor=0):
  url = 'https://www.iesdouyin.com/web/api/v2/aweme/post/?'
  sign, dytk = signature(user_id)
  tk_logger.info("sign:%s,dytk:%s" % (sign, dytk))
  if sign is None or dytk is None:
    tk_logger.log("sign [%s] or dytk [%s] is none" % (sign, dytk))
    return None
  headers = dict_merge(CHROME_HEADER, {
    "Accept": "application/json",
    "X-Requested-With": "XMLHttpRequest",
  })
  params = {
    "user_id": user_id,
    "count": "21",
    "max_cursor": cursor,
    "aid": "1128",
    "_signature": sign,
    "dytk": dytk
  }
  res = requests.get(url, headers=headers, params=params)
  tk_logger.info("request url: %s" % res.url)
  content = res.content.decode("utf8")
  jsn = json.loads(content)
  return jsn

获取的视频列表信息

使用python爬取抖音视频列表信息

获取视频信息代码片段

def get_video_detail_by_id(video_id):
  url = "https://aweme-hl.snssdk.com/aweme/v1/aweme/detail/?version_code=6.5.0&pass-region=1&pass-route=1&js_sdk_version=1.16.2.7&app_name=aweme&vid=9D5F078E-A1A9-4F64-81C7-F89CA6A3B1DC&app_version=6.5.0&device_id=34712926793&channel=App%20Store&mcc_mnc=46011&aid=1128&screen_width=750&openudid=263bd93f02801d126ca004edccbff8f6e1b19f51&os_api=18∾=WIFI&os_version=12.3.1&device_platform=iphone&build_number=65014&device_type=iPhone9,1&iid=74239983401&idfa=F39B285A-4B4F-4874-9D7E-C728A892BF6D"
  data = {"aweme_id": video_id}
  headers = {
    "sdk-version": "1",
    "x-Tt-Token": "00fc1e7950db67b5f43a312e9265cdfee513ea70c36d918c871f3bb553347f3db50ffca143b8722327b345816a75efca071d",
    "User-Agent": "Aweme 6.5.0 rv:65014 (iPhone; iOS 12.3.1; en_CN) Cronet",
    "Content-Type": "application/x-www-form-urlencoded",
    "Cookie": "tt_webid=6636348554880222728; __tea_sdk__user_unique_id=6636348554880222728; odin_tt=76d9b82d6e6f2ddfc99719a5b5d44a7d703cf977f0f7bddf8537f93920d57cb9ec33162ee47868b760f6b09e69209bb2f90bad220b75678af850a0dfa9f056e2; install_id=74239983401; ttreq=1$dab0516952a4157c0c11d4993533c09d6e45fc94; sid_guard=fc1e7950db67b5f43a312e9265cdfee5%7C1559955316%7C5184000%7CWed%2C+07-Aug-2019+00%3A55%3A16+GMT; uid_tt=0afcb06309f632d872799ec0ac3b2c80; sid_tt=fc1e7950db67b5f43a312e9265cdfee5; sessionid=fc1e7950db67b5f43a312e9265cdfee5",
    "X-Khronos": "1559956401",
    "X-Gorgon": "8300000000002e40eee38cad71d14037bd1385d18bc973f094f5",
  }
  ret = {}
  res = requests.post(url, data=data, headers=headers)
  if res.status_code == 200:
    # tk_logger.info("video detail raw:%s" % res.content.decode("utf8"))
    jsn = json.loads(res.content)
    detail = jsn.get("aweme_detail", {})
    video_info = get_video_info(detail)
    user_info = get_user_info(detail)
    play_addr = get_play_address(detail)
    video_cover = get_video_cover(detail)
    ret["video_info"] = video_info
    ret["user_info"] = user_info
    ret["play_addr"] = play_addr
    ret["video_cover"] = video_cover
  else:
    raise TKException("get video detail failed [%s][%d]" % (url, res.status_code))
  return ret

下载视频代码片段

detail = get_video_detail_by_id(video_id)
def download_video(detail):
  url = detail.get("play_addr", {}).get("url_list", [])
  if len(url) == 0:
    raise TKException("cannot get video url list [%s]" % detail)

  url = url[0]
  folder = DOWNLOAD_DIR + '/' + detail.get('user_info', {}).get("uid", "unknown")
  if not os.path.exists(folder):
    os.mkdir(folder)
  video_id = detail.get('video_info', {}).get('statistics', {}).get('aweme_id')
  # filename = "%s/%s" % (folder, detail.get("video_info", {}).get("desc", video_id) + ".mp4")
  filename = "%s/%s" % (folder, video_id + ".mp4")
  tk_logger.info("download video %s" % url)
  if os.path.isfile(filename):
    file_size = get_remote_file_size(url)
    if file_size == os.path.getsize(filename):
      tk_logger.info("file already downloaded, skip ...")
      return
    else:
      tk_logger.info("download file , file size:%d" % file_size)
  res = requests.get(url, headers=IOS_HEADER)
  if res.status_code == 200:
    with open(filename, "wb") as fp:
      for chunk in res.iter_content(chunk_size=1024):
        fp.write(chunk)
  else:
    raise TKException("download video [%s] failed [%d]" % (url, res.status_code))

下载视频

使用python爬取抖音视频列表信息

总结

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

Python 相关文章推荐
介绍Python中内置的itertools模块
Apr 29 Python
浅谈Python NLP入门教程
Dec 25 Python
Python实现的朴素贝叶斯分类器示例
Jan 06 Python
Django框架实现逆向解析url的方法
Jul 04 Python
python代码过长的换行方法
Jul 19 Python
Python OpenCV实现视频分帧
Jun 01 Python
python multiprocessing模块用法及原理介绍
Aug 20 Python
Django admin禁用编辑链接和添加删除操作详解
Nov 15 Python
Pycharm调试程序技巧小结
Aug 08 Python
python 对象真假值的实例(哪些视为False)
Dec 11 Python
Jupyter Notebook 安装配置与使用详解
Jan 06 Python
Python函数中apply、map、applymap的区别
Nov 27 Python
python过滤中英文标点符号的实例代码
Jul 15 #Python
基于python3 pyQt5 QtDesignner实现窗口化猜数字游戏功能
Jul 15 #Python
python 判断字符串中是否含有汉字或非汉字的实例
Jul 15 #Python
如何利用Python模拟GitHub登录详解
Jul 15 #Python
python中将两组数据放在一起按照某一固定顺序shuffle的实例
Jul 15 #Python
postman模拟访问具有Session的post请求方法
Jul 15 #Python
Django的models模型的具体使用
Jul 15 #Python
You might like
php实例分享之html转为rtf格式
2014/06/02 PHP
PHP实现的带超时功能get_headers函数
2015/02/10 PHP
PHP用反撇号执行外部命令
2015/04/14 PHP
Laravel实现ORM带条件搜索分页
2019/10/24 PHP
Thinkphp 框架扩展之行为扩展原理与实现方法分析
2020/04/23 PHP
javascript学习基础笔记之DOM对象操作
2011/11/03 Javascript
基于javascipt-dom编程 table对象的使用
2013/04/22 Javascript
jQuery获得document和window对象宽度和高度的方法
2015/03/25 Javascript
对JavaScript的全文搜索实现相关度评分的功能的方法
2015/06/24 Javascript
jquery实现叠层3D文字特效代码分享
2015/08/21 Javascript
Javascript原型链的原理详解
2016/01/05 Javascript
JavaScript实现带播放列表的音乐播放器实例分享
2016/03/07 Javascript
JavaScript关于提高网站性能的几点建议(一)
2016/07/24 Javascript
零基础之Node.js搭建API服务器的详解
2019/03/08 Javascript
vue组件中watch props根据v-if动态判断并挂载DOM的问题
2019/05/12 Javascript
layui内置模块layim发送图片添加加载动画的方法
2019/09/23 Javascript
python中字符串前面加r的作用
2015/06/04 Python
详解Python网络爬虫功能的基本写法
2016/01/28 Python
django1.8使用表单上传文件的实现方法
2016/11/04 Python
解决Mac下首次安装pycharm无project interpreter的问题
2018/10/29 Python
python2.7实现邮件发送功能
2018/12/12 Python
详解django+django-celery+celery的整合实战
2019/03/19 Python
详解Python self 参数
2019/08/30 Python
在Python中使用filter去除列表中值为假及空字符串的例子
2019/11/18 Python
python实现堆排序的实例讲解
2020/02/21 Python
Python基于yield遍历多个可迭代对象
2020/03/12 Python
Python工程师必考的6个经典面试题
2020/06/28 Python
Python函数__new__及__init__作用及区别解析
2020/08/31 Python
美国在线购买和出售礼品卡网站:EJ Gift Cards
2019/06/09 全球购物
产品促销活动策划书
2014/01/15 职场文书
五好党支部事迹材料
2014/02/06 职场文书
借款协议书
2014/04/12 职场文书
申请吧主发表的感言
2015/08/03 职场文书
传单、海报早OUT了,另类传单营销方案送给你!
2019/07/15 职场文书
详解缓存穿透击穿雪崩解决方案
2021/05/28 Redis
CSS基础详解
2021/10/16 HTML / CSS