python 抓取知乎指定回答下视频的方法


Posted in Python onJuly 09, 2020

前言

现在知乎允许上传视频,奈何不能下载视频,好气哦,无奈之下研究一下了,然后撸了代码,方便下载视频保存。

接下来以 猫为什么一点也不怕蛇? 回答为例,分享一下整个下载过程。

调试一下

打开 F12, 找到光标,如下图:

python 抓取知乎指定回答下视频的方法

然后将光标移动到视频上。如下图:

python 抓取知乎指定回答下视频的方法

咦这是什么?视野中出现了一条神秘的链接: https://www.zhihu.com/video/xxxxx,让我们将这条链接复制到浏览器上,然后打开:

python 抓取知乎指定回答下视频的方法

似乎这就是我们要找的视频,不要着急,让我们看一看,网页的请求,然后你会发现一个很有意思的请求(重点来了):

python 抓取知乎指定回答下视频的方法

让我们自己看一下数据吧:

{
	"playlist": {
		"ld": {
			"width": 360,
			"format": "mp4",
			"play_url": "https://vdn.vzuu.com/LD/05fc411e-d8e0-11e8-bb8b-0242ac112a0b.mp4?auth_key=1541477643-0-0-987c2c504d14ab1165ce2ed47759d927&expiration=1541477643&disable_local_cache=1",
			"duration": 17,
			"size": 1123111,
			"bitrate": 509,
			"height": 640
		},
		"hd": {
			"width": 720,
			"format": "mp4",
			"play_url": "https://vdn.vzuu.com/HD/05fc411e-d8e0-11e8-bb8b-0242ac112a0b.mp4?auth_key=1541477643-0-0-8b8024a22a62f097ca31b8b06b7233a1&expiration=1541477643&disable_local_cache=1",
			"duration": 17,
			"size": 4354364,
			"bitrate": 1974,
			"height": 1280
		},
		"sd": {
			"width": 480,
			"format": "mp4",
			"play_url": "https://vdn.vzuu.com/SD/05fc411e-d8e0-11e8-bb8b-0242ac112a0b.mp4?auth_key=1541477643-0-0-5948c2562d817218c9a9fc41abad1df8&expiration=1541477643&disable_local_cache=1",
			"duration": 17,
			"size": 1920976,
			"bitrate": 871,
			"height": 848
		}
	},
	"title": "",
	"duration": 17,
	"cover_info": {
		"width": 720,
		"thumbnail": "https://pic2.zhimg.com/80/v2-97b9435a0c32d01c7c931bd00120327d_b.jpg",
		"height": 1280
	},
	"type": "video",
	"id": "1039146361396174848",
	"misc_info": {}
}

没错了,我们要下载的视频就在这里面,其中 ld 代表普清,sd 代表标清, hd 代表高清,把相应链接再次在浏览器打开,然后右键保存就可以下载视频了。

代码

知道整个流程是什么样子,接下来撸代码的过程就简单了,这里就不过再做过多解释了,直接上代码:

# -*- encoding: utf-8 -*-

import re
import requests
import uuid
import datetime


class DownloadVideo:

  __slots__ = [
    'url', 'video_name', 'url_format', 'download_url', 'video_number',
    'video_api', 'clarity_list', 'clarity'
  ]

  def __init__(self, url, clarity='ld', video_name=None):
    self.url = url
    self.video_name = video_name
    self.url_format = "https://www.zhihu.com/question/\d+/answer/\d+"
    self.clarity = clarity
    self.clarity_list = ['ld', 'sd', 'hd']
    self.video_api = 'https://lens.zhihu.com/api/videos'

  def check_url_format(self):
    pattern = re.compile(self.url_format)
    matches = re.match(pattern, self.url)
    if matches is None:
      raise ValueError(
        "链接格式应符合:https://www.zhihu.com/question/{number}/answer/{number}"
      )
    return True

  def get_video_number(self):
    try:
      headers = {
        'User-Agent':
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'
      }
      response = requests.get(self.url, headers=headers)
      response.encoding = 'utf-8'
      html = response.text
      video_ids = re.findall(r'data-lens-id="(\d+)"', html)
      if video_ids:
        video_id_list = list(set([video_id for video_id in video_ids]))
        self.video_number = video_id_list[0]
        return self
      raise ValueError("获取视频编号异常:{}".format(self.url))
    except Exception as e:
      raise Exception(e)

  def get_video_url_by_number(self):
    url = "{}/{}".format(self.video_api, self.video_number)

    headers = {}
    headers['Referer'] = 'https://v.vzuu.com/video/{}'.format(
      self.video_number)
    headers['Origin'] = 'https://v.vzuu.com'
    headers[
      'User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36'
    headers['Content-Type'] = 'application/json'

    try:
      response = requests.get(url, headers=headers)
      response_dict = response.json()
      if self.clarity in response_dict['playlist']:
        self.download_url = response_dict['playlist'][
          self.clarity]['play_url']
      else:
        for clarity in self.clarity_list:
          if clarity in response_dict['playlist']:
            self.download_url = response_dict['playlist'][
              self.clarity]['play_url']
            break
      return self
    except Exception as e:
      raise Exception(e)

  def get_video_by_video_url(self):
    response = requests.get(self.download_url)
    datetime_str = datetime.datetime.now().strftime("%Y-%m-%d %H-%M-%S")
    if self.video_name is not None:
      video_name = "{}-{}.mp4".format(self.video_name, datetime_str)
    else:
      video_name = "{}-{}.mp4".format(str(uuid.uuid1()), datetime_str)
    path = "{}".format(video_name)
    with open(path, 'wb') as f:
      f.write(response.content)

  def download_video(self):

    if self.clarity not in self.clarity_list:
      raise ValueError("清晰度参数异常,仅支持:ld(普清),sd(标清),hd(高清)")

    if self.check_url_format():
      return self.get_video_number().get_video_url_by_number().get_video_by_video_url()


if __name__ == '__main__':
  a = DownloadVideo('https://www.zhihu.com/question/53031925/answer/524158069')
  print(a.download_video())

结语

代码还有优化空间,这里面我只是下载了回答中的第一个视频,理论上应该存在一个回答下可以有多个视频的。如果还有什么疑问或者建议,可以多多交流。

以上就是python 抓取知乎指定回答下视频的方法的详细内容,更多关于python 抓取视频的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python ldap实现登录实例代码
Sep 30 Python
解决Python字典写入文件出行首行有空格的问题
Sep 27 Python
Python贪心算法实例小结
Apr 22 Python
Django项目中添加ldap登陆认证功能的实现
Apr 04 Python
python打包exe开机自动启动的实例(windows)
Jun 28 Python
python使用原始套接字发送二层包(链路层帧)的方法
Jul 22 Python
python3中的eval和exec的区别与联系
Oct 10 Python
python实现广度优先搜索过程解析
Oct 19 Python
Python实现字符串中某个字母的替代功能
Oct 21 Python
Python实现Wordcloud生成词云图的示例
Mar 30 Python
Python telnet登陆功能实现代码
Apr 16 Python
PyQt5多线程防卡死和多窗口用法的实现
Sep 15 Python
Django ORM判断查询结果是否为空,判断django中的orm为空实例
Jul 09 #Python
Python Selenium模块安装使用教程详解
Jul 09 #Python
OpenCV 使用imread()函数读取图片的六种正确姿势
Jul 09 #Python
django模型类中,null=True,blank=True用法说明
Jul 09 #Python
Python pip安装第三方库实现过程解析
Jul 09 #Python
详细分析Python可变对象和不可变对象
Jul 09 #Python
OpenCV4.1.0+VS2017环境配置的方法步骤
Jul 09 #Python
You might like
跟我学小偷程序之成功偷取首页(第三天)
2006/10/09 PHP
桌面中心(三)修改数据库
2006/10/09 PHP
php中用加号与用array_merge合并数组的区别深入分析
2013/06/03 PHP
深入理解PHP中mt_rand()随机数的安全
2017/10/12 PHP
Mootools 1.2教程 正则表达式
2009/09/15 Javascript
jquery与google map api结合使用 控件,监听器
2010/03/04 Javascript
JQuery的Validation插件中Remote验证的中文问题
2010/07/26 Javascript
JSON 数据格式介绍
2012/01/13 Javascript
js改变文章字体大小的实例代码
2013/11/27 Javascript
JS OffsetParent属性深入解析
2014/01/13 Javascript
node.js中的http.response.removeHeader方法使用说明
2014/12/14 Javascript
JavaScript中length属性的使用方法
2015/06/05 Javascript
jQuery中常用的遍历函数用法实例总结
2015/09/01 Javascript
JavaScript中Window对象的属性及事件
2015/12/25 Javascript
javascript常见数字进制转换实例分析
2016/04/21 Javascript
angular1.x ui-route传参的三种写法小结
2018/08/31 Javascript
Vue 实时监听窗口变化 windowresize的两种方法
2018/11/06 Javascript
mock.js模拟前后台交互
2019/07/25 Javascript
layer扩展打开/关闭动画的方法
2019/09/23 Javascript
微信小程序 下拉刷新及上拉加载原理解析
2019/11/06 Javascript
JQuery样式与属性设置方法分析
2019/12/07 jQuery
vue element-ul实现展开和收起功能的实例代码
2020/11/25 Vue.js
Python json模块使用实例
2015/04/11 Python
Python小程序 控制鼠标循环点击代码实例
2019/10/08 Python
python+opencv3生成一个自定义纯色图教程
2020/02/19 Python
Python之变量类型和if判断方式
2020/05/05 Python
django跳转页面传参的实现
2020/09/17 Python
HTML5 body设置自适应全屏
2020/05/07 HTML / CSS
h5移动端调用支付宝、微信支付的实现
2020/06/08 HTML / CSS
adidas旗下高尔夫装备供应商:TaylorMade Golf(泰勒梅高尔夫)
2016/08/28 全球购物
什么是Smarty变量操作符?如何使用Smarty变量操作符
2014/07/18 面试题
先进事迹演讲稿
2014/09/01 职场文书
党的群众路线教育实践活动对照检查材料思想汇报
2014/09/19 职场文书
员工自我评价范文
2015/03/11 职场文书
政府会议通知范文
2015/04/15 职场文书
音乐之声观后感
2015/06/04 职场文书