前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >抖音小姐姐属于你的四种姿势

抖音小姐姐属于你的四种姿势

作者头像
咸鱼学Python
发布2019-10-09 15:03:42
9000
发布2019-10-09 15:03:42
举报
文章被收录于专栏:咸鱼学Python

前言

上周看到一个有趣的项目是使用Python+ADB做一个Python 抖音机器人 Douyin-Bot,自动翻页+颜值识别,自动点赞加关注,效果如下图,可以说是非常秀了。

源码地址: https://github.com/wangshub/Douyin-Bot

而我们今天实现的就是批量下载抖音视频,结合上面的机器人可以说是机器人届的蒂花之秀。

今天我们实现的抖音爬虫主要有下面四点功能:

  • 根据抖音号下载用户发布的全部视频
  • 根据链接自动下载用户点赞的视频
  • 根据链接自动下载某个主题下的全部视频
  • 根据链接自动下载某个音乐下的全部视频 下面会先以第二个功能为例编写代码。

废话说多了,先上一波爬取的结果:

下载视频截图

输出日志截图

实战

引入类库

代码语言:javascript
复制
import requests
import json
import datetime
import re
import sys
import os
from urllib.parse import urlencode
from contextlib import closing
from requests.packages import urllib3
import random

本次代码的主要功能模块如下:

这次的项目主要是根据用户分享的链接自动下载,首先我们通过分享得到下面的链接:

代码语言:javascript
复制
# 这是用户主页的分享链接
https://www.douyin.com/share/user/61806758871/?share_type=link&from=singlemessage
# 这是音乐界面的分享链接
https://www.iesdouyin.com/share/music/6562721743650491139?timestamp=1528546868&utm_source=weixin&utm_campaign=client_share&utm_medium=android&app=aweme&iid=33943329942
# 这是主题界面的分享链接
https://www.iesdouyin.com/share/challenge/1602334725005380?timestamp=1528546923&utm_source=weixin&utm_campaign=client_share&utm_medium=android&app=aweme&iid=33943329942

根据上面的链接我们可以得到以下代码,并且获得唯一的ID标识

代码语言:javascript
复制
# 解析文件里面读取出来的链接
def parse_url(urls):
    musics_id = []
    challenges_id = []
    users_id = []
    for i in range(len(urls)):
        url = urls[i]
        if url:
            # 分析链接是音乐链接
            if re.search('share/music',url):
                music_id = re.findall('share/music/(.*)\?', url)
                # if len(musics_id):
                musics_id.append(music_id[0])
                for music in musics_id:
                    print(music)
                    if music not in os.listdir():
                        os.mkdir(music)
                    download_music_media(music)


            # 分析链接是主题链接
            if re.search('share/challenge', url):
                challenge_id = re.findall('share/challenge/(.*)\?',url)
                challenges_id.append(challenge_id[0])
                for challenge in challenges_id:

                    if challenge not in os.listdir():
                        os.mkdir(challenge)
                    # print(challenge)
                    download_challenge_media(challenge)

            # 分析链接是用户主页,请求下载的是用户喜欢的视频
            if re.search('share/user', url):
                user_id = re.findall('share/user/(.*)/\?',url)
                users_id.append(user_id[0])
                for u_id in users_id:
                    if u_id not in os.listdir():
                        os.mkdir(u_id)
                    # print(challenge)
                    download_ulike_media(u_id)

我们通过浏览器打开上面的链接可以获得以下的Headers信息:

代码语言:javascript
复制
headers = {
            'user-agent':random.choice(hds),
            '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',
            'cache-control': 'max-age=0'
}

我们以第二个获取点赞视频为例,打开我们分享的链接,将开发者模式调整成手机版,点击「喜欢」可以看到请求的链接,如下图:

查看请求链接

获得请求参数 可以看到请求的参数中有一个很奇怪的参数_signature,且每次请求这个参数都不同,通过查阅gayhub上相关项目资料,发现这个参数是链接中的ID号加密获得,所以接下来可以通过调用加密JS对ID加密,就可以构建一个完整的请求。代码如下:

代码语言:javascript
复制
# 构建请求参数
def download_ulike_media(u_id):
    p = os.popen('node fuck-byted-acrawler.js %s' % u_id)
    signature = p.readlines()[0]
    params = {
        'user_id': str(u_id),
        'count': '21',
        'max_cursor': '0',
        'aid': '1128',
        '_signature': signature
    }

可以看到上面调用了node.js来执行加密js,所以我们需要安装NODE.JS,安装文件在公众号后台回复「node」获取。 通过构建请求,我们顺利得到请求的结果,如下图,这个时候我们需要解析请求的数据得到视频的链接。

我们通过查看返回的数据,可以发现正确视频的链接形式如下:

代码语言:javascript
复制
https://www.amemv.com/share/video/xxxxxxxxxxx

在这里我们可以获得视频的id就可以构建完整的视频链接。代码如下:

代码语言:javascript
复制
    # 拼接视频信息
    def get_ulike_url(max_cursor=None, video_count=0):
        video_names = []
        video_urls = []
        url = 'https://www.amemv.com/share/video/'
        if max_cursor:
            params['max_cursor'] = str(max_cursor)
        ulike_url = 'https://www.douyin.com/aweme/v1/aweme/favorite/?' + urlencode(params)
        # print(ulike_url)
        res = requests.get(ulike_url, headers=headers, verify=False)
        ulike_ms = json.loads(res.content.decode('utf-8'))
        favorite_list = str(ulike_ms['aweme_list'])
        v_id = re.findall('https://www.amemv.com/share/video/(.*?)\'',favorite_list)
        for l in v_id:
            share_desc = l + '.mp4'
            s_url = url + l
            video_names.append(share_desc)
            video_urls.append(s_url)
        parse_media_url(video_names, video_urls, u_id)
        if ulike_ms.get('has_more') == 1:
            return get_ulike_url(ulike_ms.get('max_cursor'), video_count)
    video_count = get_ulike_url()
    if video_count == 0:
        print('这个用户没有喜欢的视频')

我们点击我们上面构建的视频链接,看下页面的具体情况是什么样的。

查看网页返回的信息 我们打开上图红框中的链接,可以看到是视频的资源地址。

打开源视频地址 按照上述的思路,我们可以构建以下的代码:

代码语言:javascript
复制
# 下载模块
def _download_video(video_url, path):
    video_content = get_video_url(video_url)
    # print(video_content)
    rec = re.compile(r'class="video-player" src="(.*?)"')
    pattern = re.compile(r'playwm')
    downloadwm_url = rec.search(video_content).group(1)
    # 构建无水印下载链接
    download_url = re.sub(pattern, 'play', downloadwm_url)
    print('正在下载:',download_url, path)
    with closing(requests.get(download_url, headers=headers, stream=True, verify=False)) as response:
        chunk_size = 1024
        if response.status_code == 200:
            with open(path, 'wb') as f:
                for data in response.iter_content(chunk_size=chunk_size):
                    f.write(data)
                # flush() 方法是用来刷新缓冲区的,即将缓冲区中的数据立刻写入文件,同时清空缓冲区,不需要是被动的等待输出缓冲区写入。
                    f.flush()

以上就是下载用户点赞视频的代码,相比于其他功能稍微复杂了点,其他功能通过手机抓包就可以获得请求接口,且没有加密参数。本次的项目代码基本类似,这里就以下载音乐视频的代码为例,讲下抓包部分: 这次使用的抓包工具是Charles,基础的配置可以看下面的文章: 10行代码实现自动参与抽奖助手抽奖(上) 配置好Charles后,打开抖音,通过刷新手机页面,可以看到左边栏的请求链接中有两处链接高亮,Charles截图如下:

Charles截图 点击开响应的数据可以看到每一个链接,我们只要解析每个链接中share_url中包含的videoid,再带入到API中就可以得到真实的视频地址了。

解析图中红框中链接包含的videoid 在测试API时强烈建议可以使用Postman来测试链接的可用性,以减少我们请求的参数数量和测试的复杂度。

测试接口时的部分截图

留心

  • 写给之后的自己 没有用到多线程,下载起来有点慢,只能等到之后完全吃透后再应用上。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-06-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 咸鱼学Python 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 实战
  • 留心
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档