欢迎访问欧博网址!

首页快讯正文

烟台百姓网:Python爬虫---爬取抖音短视频

admin2020-05-0415

目录
  • 前言
  • 抖音爬虫制作
    • 选定网页
    • 剖析网页
    • 提取id组织网址
    • 拼接数据包链接
    • 获取视频地址
    • 下载视频
  • 所有代码
  • 实现效果
  • 待解决的问题

前言

最近一直想要写一个抖音爬虫来批量下载抖音的短视频,然则经由几天的试探我发现了一个很严重的问题......抖音着实是难爬!从一最先的网页剖析中就有着许多的坑,然则这几天的试探也不是一无所获,我鼓捣出来了一个问题版的抖音爬虫(操作较为庞大),以是我也想通过这篇博客来记录下我剖析网页的历程,也想讨教一下途经大佬们,迎接列位大佬指出问题!

抖音爬虫制作

选定网页

想要爬取抖音上面的视频,就要先找到可以刷小视频的地址,于是我就最先在网上寻找网页版的抖音。经由一番寻找,发现抖音根本就没有网页版的这个板块,打开的网页大多都是如下图所示提醒你下载app的网页:

想要爬取小视频的内容,没有网页地址可不行。于是我又想到了另一种寻找网页的方式:

首先我打开了手机抖音,选定了一个喜欢的抖音号,使用复制链接的方式来实验是否可以在网页中打开:

将链接粘贴到记事本中,发现它是长这个样子的

https://v.douyin.com/wGf4e1/

将这个网址在浏览器中打开,发现这个网址可以正常显示

向下滑动,也可以看到这个账号公布的视频
烟台百姓网:Python爬虫---爬取抖音短视频 第1张

ok,到现在为止,我已经选定了将这个页面作为我获取数据的起始页面

选定起始页之后,我的下一步想法是要去获取这些小视频的单独的网页地址,于是我又点击了下面的这些小视频。这里恶心的地方泛起了,无论我点击哪一个小视频,弹出来的都是强迫你下载app的界面

于是我又想实验上面获取到网页的操作来获取视频的地址,再次打开手机上的抖音,在这个漫威的账号下随便打开一个视频,点击右下角的分享,复制它的链接:
烟台百姓网:Python爬虫---爬取抖音短视频 第2张

这个链接地址长这个样子:

#黑寡妇 北美最终预告!漆黑过往揭晓,2020即将强势开启漫威影戏宇宙第四阶段!
 https://v.douyin.com/wGqCNG/ 复制此链接,打开【抖音短视频】,直接旁观视频!

我再把这段地址复制到浏览器中打开:
烟台百姓网:Python爬虫---爬取抖音短视频 第3张

打开简直实是视频页,点击播放按钮也可以播放视频,以是这就是我们需要记着的第二个页面。

剖析网页

现在又泛起了一个对照贫苦的事情,在浏览器中输入网址事后,跳转到了视频的播放页,然则此时的播放页地址经由了重定向天生了异常长的一串地址,乍一看毫无纪律可讲

这是重定向之后的网址:
烟台百姓网:Python爬虫---爬取抖音短视频 第4张

正常来说请求第一种链接https://v.douyin.com/wGqCNG/和第二种重定向之后的链接都可以获取到信息,然则我发现第一种链接地址是找不到纪律的,以是我预测第二种网址的纪律会加倍的好找,先把链接地址复制到记事本中:

https://www.iesdouyin.com/share/video/6802189485015633160/?region=CN&mid=6802184753988471559&u_code=388k48lba520&titleType=title&utm_source=copy_link&utm_campaign=client_share&utm_medium=android
&app=aweme

看了这么长一串的链接,链接包罗的内容也是异常多的,对剖析纪律有着很大的滋扰,于是我试着精简一下这个链接(删掉链接内里的一些内容,看看是否还能找到页面)经由了一次又一次的实验,我所获得的最简朴的网址如下:

https://www.iesdouyin.com/share/video/6802189485015633160/?mid=6802184753988471559

这个网址依旧可以打开视频页,若是在删掉一点器械,出来的就是抖音的宣传页,以是这个网址就是我所需要的最简朴网址
烟台百姓网:Python爬虫---爬取抖音短视频 第5张

就一个网址当然是剖析不出纪律的,于是我又用同样的方式来获得两个新网址:

https://www.iesdouyin.com/share/video/6818885848784702728/?region=CN&mid=6818885858780203783&u_code=388k48lba520&titleType=title&utm_source=copy_link&utm_campaign=client_share
&utm_medium=android&app=aweme

https://www.iesdouyin.com/share/video/6820605884050181379/?region=CN&mid=6820605916115864328&u_code=388k48lba520&titleType=title&utm_source=copy_link&utm_campaign=client_share
&utm_medium=android&app=aweme

精简网址之后,将三个网址放在一起考察:

https://www.iesdouyin.com/share/video/6802189485015633160/?mid=6802184753988471559

https://www.iesdouyin.com/share/video/6818885848784702728/?mid=6818885858780203783

https://www.iesdouyin.com/share/video/6820605884050181379/?mid=6820605916115864328

不难发现,这三个网址的区别就在于数字的差别

接下来预测:这串数字会不会是每个视频的Id值?

随后我打开漫威影业抖音号,右击检查,按下ctrl+f搜索内容,在搜索框内划分搜索https://www.iesdouyin.com/share/video/6802189485015633160/?mid=6802184753988471559链接中的68021894850156331606802189485015633160两个值
烟台百姓网:Python爬虫---爬取抖音短视频 第6张

第一个值顺遂找到,就是我们所预测的id值,然则搜索第二个值却得不到任何的返回
烟台百姓网:Python爬虫---爬取抖音短视频 第7张

这就叫我异常苦恼了,我最先想其他的设施来获取到这个值,我实验了抓包和其他的一些方式,然则都没有找到这个值的相关信息。

我经由了一番思索,突然间冒出了一个想法:这个值是不是随机天生的?

然后我做了一个小小的实验,我将这个值改成了随便的一个数

https://www.iesdouyin.com/share/video/6802189485015633160/?mid=18987

然而神奇的是,这个网址请求出了数据(去掉这个mid键不出数据,将mid随机赋值却可以获得数据emmm)
烟台百姓网:Python爬虫---爬取抖音短视频 第8张

提取id组织网址

经由刚刚的剖析,我发现我们想要提取的数据就只有一个id值,然后再用Id值替换掉网址中的数字就可以获得响应的视频页面了

id是这段代码的最主要的部门,经由前面曲折又难题的网页剖析之后,我以为提取id只需要从网页中用表达式提取数据就可以了,然则我没想到的是这一步也是对照难题的

我先是在主页右击了检查,然后仔细的考察了elements内里的元素,我发现id就储存在elements之中
烟台百姓网:Python爬虫---爬取抖音短视频 第9张

接着我就想设施获得这个页面中的id信息,我实验了直接请求,发现输出的数据中没有Id信息; 我又加上了请求头,依旧没有id值输出(这个页面的元素是动态加载的,虽然不能一次获取所有Id,然则也不至于一个没有) ;然后我想到了selenium自动化测试模块,使用webdriver打开网址打印源码,可是输出照样没变

我查了百度的一些方式,也做了一些实验,发现这个页面所做的反爬确实很难破解。于是我就只能换一条路去实验

在谷歌开发者工具中,点击network选项卡,刷新界面 随着我刷新的操作,在XHR选项卡下泛起了一个名字很新鲜的数据包
烟台百姓网:Python爬虫---爬取抖音短视频 第10张

点击他的preview选项卡,点出他的下拉菜单,这内里存储的正是小视频的Id信息。然则需要注重的是,这个包内里只存储了0-20序列的共21条信息
烟台百姓网:Python爬虫---爬取抖音短视频 第11张

然则从这个主页中我可以知道,它一共公布了64个短视频,以是我推断他另有三个数据包没有加载出来 ---->我转动下拉条,考察有没有数据包
烟台百姓网:Python爬虫---爬取抖音短视频 第12张

转动到最后,验证了我的料想,这个页面有四个数据包且为动态加载

好了,我们已经剖析出来了这个网页的组织,先不要管一共有几个数据包,先以一个数据包为例提取id信息:

复制网页链接作为他的请求网址
烟台百姓网:Python爬虫---爬取抖音短视频 第13张

将user-agaent加到请求头中(这个网页必须要加请求头,否则获取不到数据)
烟台百姓网:Python爬虫---爬取抖音短视频 第14张
请求获得数据:

import requests
import json

class Douyin:
    def page_num(self,max_cursor):
        #网址后面的随机参数(我着实剖析不出纪律)
        random_field = 'RVb7WBAZG.rGG9zDDDoezEVW-0&dytk=a61cb3ce173fbfa0465051b2a6a9027e'
        #网址的主体
        url = 'https://www.iesdouyin.com/web/api/v2/aweme/post/?sec_uid=MS4wLjABAAAAF5ZfVgdRbJ3OPGJPMFHnDp2sdJaemZo3Aw6piEtkdOA&count=21&max_cursor=0&aid=1128&_signature=' + random_field
        #请求头
        headers = {
            'user-agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36',
        }
        response = requests.get(url,headers=headers).text
        #转换成json数据
        resp = json.loads(response)
        #遍历
        for data in resp["aweme_list"]:
            # id值
            video_id = data['aweme_id']
            # 视频简介
            video_title = data['desc']
            # 组织视频网址
            video_url = 'https://www.iesdouyin.com/share/video/{}/?mid=1'
            # 填充内容
            video_douyin = video_url.format(video_id)
            print(video_id)
            print(video_title)
            print(video_douyin)

if __name__ == '__main__':
     douyin = Douyin()
     douyin.page_num()

print一下i相关信息:
烟台百姓网:Python爬虫---爬取抖音短视频 第15张

当前乍一看似乎这个代码没有问题,然则在执行四五次之后,会泛起请求不到数据或返回False的情形,一最先我以为是ip被限制的缘故原由,然则加上了ip池之后也是一样的效果,厥后我才发现:请求不到数据是因为之前请求的url被禁用了,要在抖音详情页刷新一下,再把新的数据包的网址复制过来才气重新获得数据(我也不知道这是什么类型的反爬,希望知道的老哥可以告诉我一下)

*我之以是把这个网址分成两部门来写,是因为当网址请求不到数据的时刻,改变的是末尾的_signature=random_field字段,在请求不到数据的时刻只需重新复制一下这个字段就可以了,会简化一点点代码
烟台百姓网:Python爬虫---爬取抖音短视频 第16张

拼接数据包链接

上面提取Id的时刻讲到,我们先拿一个数据包做例子,然则我们要爬的这个用户的所有视频,以是就要将它所有的数据包地址都接见一遍

想要获得这些数据包的地址,就需要剖析他们的网址组织,我把这四个数据包的网址所有复制到记事本中,逐个剖析他们组织纪律
烟台百姓网:Python爬虫---爬取抖音短视频 第17张

不难看出,这四个数据包的区别就在于max_cursor后面的值的差别,而这个值正好就包包罗在它前一个数据包之中,这就说明我们可以早年一个数据包中提取到下一个数据包的max_curso值,从而组织出下一个数据包的链接地址
烟台百姓网:Python爬虫---爬取抖音短视频 第18张

可是第四个数据包也包罗着max_cursor的值,我们该在何时住手组织下一个数据包呢?

我把最后一个数据包的max_cursor值复制下来并替换到组织的数据包链接中,发现可以跳转到一个新的网址,这个网址中也有max_cursor的值,然则这个值为0
烟台百姓网:Python爬虫---爬取抖音短视频 第19张

也可以多找几个网址测试,最后的效果指向都是0,以是我们可以通过if语句来判断这个值为0的时刻就终止循环
组织网址代码:

import requests
import json

class Douyin:
    def page_num(self,max_cursor):
        #网址后面的随机参数(我着实剖析不出纪律)
        random_field = 'pN099BAV-oInkBpv2D3.M6TdPe&dytk=a61cb3ce173fbfa0465051b2a6a9027e'
        #网址的主体
        url = 'https://www.iesdouyin.com/web/api/v2/aweme/post/?sec_uid=MS4wLjABAAAAF5ZfVgdRbJ3OPGJPMFHnDp2sdJaemZo3Aw6piEtkdOA&count=21&max_cursor=' + str(max_cursor) + '&aid=1128&_signature=' + random_field
        #请求头
        headers = {
            'user-agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36',
        }
        response = requests.get(url,headers=headers).text
        #转换成json数据
        resp = json.loads(response)
        #提取到max_cursor
        max_cursor = resp['max_cursor']
        #判断住手组织网址的条件
        if max_cursor==0:
            return 1
        else:
            print(url)
            douyin.page_num(max_cursor)

if __name__ == '__main__':
     douyin = Douyin()
     douyin.page_num(max_cursor=0)

输出组织后的网址:
烟台百姓网:Python爬虫---爬取抖音短视频 第20张

获取视频地址

现在我们已经可以乐成的进入获取到视频页面了,庞大的网页剖析基本已经竣事了,后续操作就变得简朴了
先打开小视频的页面,右击检查,查看元素
烟台百姓网:Python爬虫---爬取抖音短视频 第21张

经由检查发现,这个源代码中并没有视频地址,点击了一下播放按键,视频的地址才会加载出来
烟台百姓网:Python爬虫---爬取抖音短视频 第22张

这个网址中只包罗了一个小视频
烟台百姓网:Python爬虫---爬取抖音短视频 第23张

看到这种动态加载的机制,我们首先就应该想到selenium自动化测试工具,步骤是先用selenium打开视频页面,再点击播放按钮,将此时已经刷新完的网页源代码保留,

再从中提取到视频的真正网址,最后再将调试好的webdriver设置为无界面模式
实现代码:

from selenium import webdriver
from lxml import etree
from selenium.webdriver.chrome.options import Options
import requests
import json
import time

class Douyin:
    def page_num(self,max_cursor):
        #网址后面的随机参数(我着实剖析不出纪律)
        # 设置谷歌无界面浏览器
        chrome_options = Options()
        chrome_options.add_argument('--headless')
        chrome_options.add_argument('--disable-gpu')
        # chromdriver地址
        path = r'/home/jmhao/chromedriver'
        #随机码
        random_field = 'IU4uXRAbf-iiAwnGoS-puCFOLk&dytk=a61cb3ce173fbfa0465051b2a6a9027e'
        #网址的主体
        url = 'https://www.iesdouyin.com/web/api/v2/aweme/post/?sec_uid=MS4wLjABAAAAF5ZfVgdRbJ3OPGJPMFHnDp2sdJaemZo3Aw6piEtkdOA&count=21&max_cursor=' + str(max_cursor) + '&aid=1128&_signature=' + random_field
        #请求头
        headers = {
            'user-agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36',
        }
        response = requests.get(url,headers=headers).text
        #转换成json数据
        resp = json.loads(response)
        #提取到max_cursor
        max_cursor = resp['max_cursor']
        #遍历
        for data in resp["aweme_list"]:
            # id值
            video_id = data['aweme_id']
            # 视频简介
            video_title = data['desc']
            # 组织视频网址
            video_url = 'https://www.iesdouyin.com/share/video/{}/?mid=1'
            # 填充内容
            video_douyin = video_url.format(video_id)
            driver = webdriver.Chrome(executable_path=path, options=chrome_options)
            # 打开视频界面
            driver.get(video_douyin)
            # 点击播放按钮
            driver.find_element_by_class_name('play-btn').click()
            time.sleep(2)
            # 将网页源码存放到变量中
            information = driver.page_source
            # 退出
            driver.quit()
            html = etree.HTML(information)
            # 提取视频地址
            video_adress = html.xpath("//video[@class='player']/@src")
            print(video_adress)

        #判断住手组织网址的条件
        if max_cursor==0:
            return 1
        else:
            #否则循环组织网址
            douyin.page_num(max_cursor)

if __name__ == '__main__':
     douyin = Douyin()
     douyin.page_num(max_cursor=0)

打印一下视频的真实网址:
烟台百姓网:Python爬虫---爬取抖音短视频 第24张

下载视频

视频的真实网址我们已经获得了,接下来只剩下最后一步的操作了---->下载视频
视频下载的操作就异常简朴了:

    for i in video_adress:
        #请求视频
        video = requests.get(i,headers=headers).content
        with open('douyin/' + video_title,'wb') as f:
            print('正在下载:',video_title)
            f.write(video)

所有代码

from selenium import webdriver
from lxml import etree
from selenium.webdriver.chrome.options import Options
import requests
import json
import time

class Douyin:
    def page_num(self,max_cursor):
        #网址后面的随机参数(我着实剖析不出纪律)
        # 设置谷歌无界面浏览器
        chrome_options = Options()
        chrome_options.add_argument('--headless')
        chrome_options.add_argument('--disable-gpu')
        # chromdriver地址
        path = r'/home/jmhao/chromedriver'
        #随机码
        random_field = '.E3AgBAdou1.AOcbGzS2IvxNwJ&dytk=a61cb3ce173fbfa0465051b2a6a9027e'
        #网址的主体
        url = 'https://www.iesdouyin.com/web/api/v2/aweme/post/?sec_uid=MS4wLjABAAAAF5ZfVgdRbJ3OPGJPMFHnDp2sdJaemZo3Aw6piEtkdOA&count=21&max_cursor' + str(max_cursor) + '&aid=1128&_signature=' + random_field
        #请求头
        headers = {
            'user-agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36',
        }
        response = requests.get(url,headers=headers).text
        #转换成json数据
        resp = json.loads(response)
        #提取到max_cursor
        max_cursor = resp['max_cursor']
        #遍历
        for data in resp["aweme_list"]:
            # id值
            video_id = data['aweme_id']
            # 视频简介
            video_title = data['desc']
            # 组织视频网址
            video_url = 'https://www.iesdouyin.com/share/video/{}/?mid=1'
            # 填充内容
            video_douyin = video_url.format(video_id)
            driver = webdriver.Chrome(executable_path=path, options=chrome_options)
            # 打开视频界面
            driver.get(video_douyin)
            # 点击播放按钮
            driver.find_element_by_class_name('play-btn').click()
            time.sleep(2)
            # 将网页源码存放到变量中
            information = driver.page_source
            # 退出
            driver.quit()
            html = etree.HTML(information)
            # 提取视频地址
            video_adress = html.xpath("//video[@class='player']/@src")
            for i in video_adress:
                # 请求视频
                video = requests.get(i, headers=headers).content
                with open('douyin/' + video_title, 'wb') as f:
                    print('正在下载:', video_title)
                    f.write(video)

        #判断住手组织网址的条件
        if max_cursor==0:
            return 1
        else:
            douyin.page_num(max_cursor)
            return url

if __name__ == '__main__':
     douyin = Douyin()
     douyin.page_num(max_cursor=0)

实现效果

烟台百姓网:Python爬虫---爬取抖音短视频 第25张

可以看到这些视频已经下载到内陆了,我们在打开内陆文件夹看一下
烟台百姓网:Python爬虫---爬取抖音短视频 第26张

随便打开一个视频文件:
烟台百姓网:Python爬虫---爬取抖音短视频 第27张

可以播放!至此我这个问题版的抖音爬虫就做完了

待解决的问题

  • 若何获取主页中所有的id地址
  • 为什么请求的url后缀会一直转变,该怎么破解

实在所有的问题都指向了一个地方:该怎么获取小视频的id 若是大佬们有更好的方式可以获取id值,希望大佬们可以不惜提出建议让我把这个爬虫的功效再完善!谢谢列位!

,

Sunbet

Sunbet www.361223.com Sunbet是进入Sunbet(www.sunbet.in)的主力站点。Sunbet开放Sunbet会员开户网址、Sunbet代理开户、Sunbet手机版下载、Sunbet电脑客户端下载等业务。

转载声明:本站发布文章及版权归原作者所有,转载本站文章请注明文章来源自欧博网址!

本文链接:http://www.cx11yx.cn/post/976.html