Python爬一下抖音上小姐姐的视频~
在简书也码了1W多字了,发现还是爬虫类的文章看的人多。
算法工程师现在都啥价位了,你们还在看爬虫→_→
介绍
这次爬的是当下大火的APP--抖音,批量下载一个用户发布的所有视频。
各位也应该知道,抖音只有移动端,官网打开除了给你个APP下载二维码啥也没有,所以相比爬PC网站,还是遇到了更多的问题,也花了更多的时间,不过好在基本实现了,除了一点咱在后面说。
思路梳理
- 其实如果看了其他博主爬抖音的教程就发现,大部分都是通过fildder手机抓包来获取接口地址等信息,其实不用那么麻烦,我们通过分享选择链接形式就可以获取到信息:
image.png -
然后电脑访问这个链接,就可以打开页面了,不过很快我们就会发现一个问题,电脑访问这个地址发布视频是空的:
image.png -
谷歌Chrome浏览器有一个模拟手机访问的功能,我们选在iPhone X模式来访问页面,果然看到发布的视频了:
image.png -
我们接下来看下后台请求,不多,很快就找到我们需要的视频信息了,也能直接打开观看视频,到这感觉已经成功了一大半了:
image.png - 但很快我们有发现了新问题,可以看到莉哥总共发布了93个作品,但我们实际获取到但链接只有19个。其实我们用过抖音,包括微博这些应用的都知道,很多信息他们不是一次加载完的,当你拖动页面的时候才会继续加载。所以我们尝试上拉页面,就会发现后台又多了一个请求,返回了新加载的视频信息。
https://www.amemv.com/aweme/v1/aweme/post/?user_id=57720812347&count=21&max_cursor=0&aid=1128&_signature=KRLTTRAdclaWZCKrElzZVykS01&dytk=4830f6e279a5f53872aab9e9dc112d33
https://www.amemv.com/aweme/v1/aweme/post/?user_id=57720812347&count=21&max_cursor=1530363175000&aid=1128&_signature=KRLTTRAdclaWZCKrElzZVykS01&dytk=4830f6e279a5f53872aab9e9dc112d33
两个地址除了max_cursor其他都一样,其实就是上一条返回的json数据中的max_cursor就是下个链接中的max_cursor,然后has_more等于1的时候表示还未全部加载,这样逻辑就清楚了,我们只要先判断has_more是否等于1,等于1的时候我们将max_cursor的值传入下一个链接继续访问获取视频地址,直到has_more等于0为止。
image.png -
这样所有视频地址都有了,就开始下载吧!!
image.png
代码部分
# -*- coding: utf-8 -*- #date : 2018-07-29 #author : Awesome_Tang #version : Python 2.7.9 from selenium import webdriver from bs4 import BeautifulSoup import json import requests import sys import time import os import uuid from contextlib import closing from requests.packages.urllib3.exceptions import InsecureRequestWarning requests.packages.urllib3.disable_warnings(InsecureRequestWarning) class douyin_spider(object): """docstring for douyin_spider""" def __init__(self,user_id,_signature,dytk): print '*******DouYin_spider******' print 'Author : Awesome_Tang' print 'Date : 2018-07-29' print 'Version: Python2.7' print '**************************' print '' self.userid = user_id self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36'} mobile_emulation = {'deviceName': 'iPhone X'} # chrome浏览器模拟iPhone X进行页面访问 options = webdriver.ChromeOptions() options.add_experimental_option("mobileEmulation", mobile_emulation) self.browser = webdriver.Chrome(chrome_options=options) self._signature= _signature self.dytk= dytk self.url = 'https://www.amemv.com/aweme/v1/aweme/post/?user_id=%s&count=32&max_cursor=0&aid=1128&_signature=%s&dytk=%s'%(self.userid,self._signature,self.dytk) def handle_url(self): url_list = [self.url,] self.browser.get(self.url) web_data = self.browser.page_source soup = BeautifulSoup(web_data, 'lxml') web_data = soup.pre.string web_data = json.loads(str(web_data)) if web_data['status_code'] == 0: while web_data['has_more'] == 1: # 最大加载32条视频信息,has_more等于1表示还未全部加载完 max_cursor = web_data['max_cursor'] # 获取时间戳 url = 'https://www.amemv.com/aweme/v1/aweme/post/?user_id=%s&count=32&max_cursor=%s&aid=1128&_signature=%s&dytk=%s'%(self.userid,max_cursor,self._signature,self.dytk) url_list.append(url) self.browser.get(url) web_data = self.browser.page_source soup = BeautifulSoup(web_data, 'lxml') web_data = soup.pre.string web_data = json.loads(str(web_data)) else: max_cursor = web_data['max_cursor'] # 获取时间戳 url = 'https://www.amemv.com/aweme/v1/aweme/post/?user_id=%s&count=32&max_cursor=%s&aid=1128&_signature=%s&dytk=%s'%(self.userid,max_cursor,self._signature,self.dytk) url_list.append(url) else: url_list = [] return url_list def get_download_url(self,url_list): download_url = [] title_list = [] if len(url_list)> 0: for url in url_list: self.browser.get(url) web_data = self.browser.page_source soup = BeautifulSoup(web_data, 'lxml') web_data = soup.pre.string web_data = json.loads(str(web_data)) if web_data['status_code'] == 0: for i in range(len(web_data['aweme_list'])): download_url.append(web_data['aweme_list'][i]['video']['play_addr']['url_list'][0]) title_list.append(web_data['aweme_list'][i]['share_info']['share_desc'].encode('utf-8')) return download_url,title_list def videodownloader(self,url,title): size = 0 path = title+'.mp4' with closing(requests.get(url, headers = self.headers ,stream=True, verify=False)) as response: chunk_size = 1024 content_size = int(response.headers['content-length']) if response.status_code == 200: print '%s is downloading...'%title sys.stdout.write('[File Size]: %0.2f MB\n' % (content_size/chunk_size/1024)) with open(path, 'wb') as f: for data in response.iter_content(chunk_size=chunk_size): f.write(data) size += len(data) f.flush() sys.stdout.write('[Progress]: %0.2f%%' % float(size/content_size*100) + '\r') sys.stdout.flush() else: print response.status_code def run(self): url = 'https://www.amemv.com/aweme/v1/aweme/post/?user_id=%s&count=32&max_cursor=0&aid=1128&_signature=%s&dytk=%s'%(self.userid,self._signature,self.dytk) url_list = self.handle_url() download_url,title_list = self.get_download_url(url_list) for i in range(len(download_url)): url = download_url[i] title = title_list[i] self.videodownloader(url,title) if __name__ == '__main__': # 创建对象 # 传入三个参数,user_id,_signature,dytk douyin_spider = douyin_spider('95870186531','RFE1JhAbHxD7J8TA9HCumURRNT','539f2c59bb57577983b3818b7a7f32ef') douyin_spider.run() print '******DouYin_spider@Awesome_Tang、******'
问题
- 开始说了,目前还存在一个问题,我们看接口地址可以发现,目前需要5个参数分别是:
user_id, max_cursor,count,_signature, dytk
前面三个都没问题,而且我看有的博主5/6月份都文章都还只需要前三个参数,_signature, dytk是两个加密之后的参数,不知道咋加密的,而且selenium似乎也没有获取后台请求地址的方法,返回的视频地址也没有在页面进行渲染,所以现在还需要点击分享链接之后手动填入_signature, dytk两个值,有点冒傻气~
skr~skr~~

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
java源码-LinkedHashMap
开篇 LinkedHashMap是HashMap的变种,有一些额外的特性其中最重要的就是维护数据插入的有序性,这篇文章就是为了讲清楚LinkedHashMap的实现细节。 LinkedHashMap类图 LinkedHashMap类图 LinkedHashMap和HashMap的差别 LinkedHashMap可以认为是HashMap+LinkedList,即它既使用HashMap操作数据结构,又使用LinkedList维护插入元素的先后顺序。 LinkedHashMap除了维持Map的有序性质外,其他和HashMap是一模一样的, LinkedHashMap实现细节 从LinkedHashMap的类依赖图可以看出来,LinkedHashMap其实是继承自HashMap类,所以LinkedHashMap的所有接口基本上都是继承自己HashMap类,当然也存在一个非常核心的差别。 LinkedHashMap用于存储key/value的结果是继承自己HashMap的,但是LinkedHashMap本身维护着一个有序列表。 head是LinkedHashMap的列表头,tail是Link...
- 下一篇
关于mvn install命令执行报错问题
首先这个报错,通常要么是依赖问题,比如模块之间的依赖传递问题,通常报这种错误会在控制台提示。 或者是比如子工程分为test-entity、test-dao、test-service、test-web三者之间依赖传递,web依赖为service,service依赖于dao,dao依赖于entity。 比如修改了test-entity,没有及时执行mvn install,会导致test-web启动报错。这种报错,通常及时修改并mvn install是可以避免的。 不过在此讲的一个mvn install 报错问题,原因与上述所说无关。 问题出现的原因是:新开一个wordspace空间,新建maven项目,并在执行mvn install时报错 错误信息截图如下: 红色标记处是根本原因。 错误信息翻译过来的意思是:也许您是在JRE上运行,而不是在JDK中运行。 这就表示必须要在jdk环境运行,因为jdk中包含java工作需要的类库同时也包含java所需运行的环境jre。另外也不得不提到maven安装,安装maven的时候,前提必选安装jdk,没有jdk,maven是跑不起来。这就好比为什么安装...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- 设置Eclipse缩进为4个空格,增强代码规范
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS6,CentOS7官方镜像安装Oracle11G
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2全家桶,快速入门学习开发网站教程
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装