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实现百度关键词排名查询
Mar 30 Python
Python中的面向对象编程详解(下)
Apr 13 Python
PyQt5每天必学之关闭窗口
Apr 19 Python
python实现多层感知器
Jan 18 Python
python3.4 将16进制转成字符串的实例
Jun 12 Python
在交互式环境中执行Python程序过程详解
Jul 12 Python
python利用re,bs4,requests模块获取股票数据
Jul 29 Python
PyCharm无法识别PyQt5的2种解决方法,ModuleNotFoundError: No module named 'pyqt5'
Feb 17 Python
python实现拼图小游戏
Feb 22 Python
关于Python turtle库使用时坐标的确定方法
Mar 19 Python
Python基于template实现字符串替换
Nov 27 Python
PyQt实现计数器的方法示例
Jan 18 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
用PHP发电子邮件
2006/10/09 PHP
个人写的PHP验证码生成类分享
2014/08/21 PHP
PHP图像处理类库MagickWand用法实例分析
2015/05/21 PHP
CodeIgniter与PHP5.6的兼容问题
2015/07/16 PHP
微信支付开发动态链接Native支付
2016/07/12 PHP
Javascript valueOf 使用方法
2008/12/28 Javascript
一组JS创建和操作表格的函数集合
2009/05/07 Javascript
js将控件隐藏的方法及display属性介绍
2013/07/04 Javascript
利用javascript数组长度循环数组内所有元素
2013/12/27 Javascript
让alert不出现弹窗的两种方法
2014/05/18 Javascript
javascript学习笔记--数字格式类型
2014/05/22 Javascript
javascript实现禁止复制网页内容
2014/12/16 Javascript
js实现禁止中文输入的方法
2015/01/14 Javascript
jQuery+ajax简单实现文件上传的方法
2016/06/03 Javascript
深入理解jquery中extend的实现
2016/12/22 Javascript
jQuery实现复选框的全选和反选
2017/02/02 Javascript
详解axios在vue中的简单配置与使用
2017/05/10 Javascript
浅谈Vue.js中的v-on(事件处理)
2017/09/05 Javascript
vue 之 .sync 修饰符示例详解
2018/04/21 Javascript
Vue 报错TypeError: this.$set is not a function 的解决方法
2018/12/17 Javascript
vuejs中父子组件之间通信方法实例详解
2020/01/17 Javascript
详解Vue的ref特性的使用
2020/01/24 Javascript
JS检测浏览器开发者工具是否打开的方法详解
2020/10/02 Javascript
基于Django contrib Comments 评论模块(详解)
2017/12/08 Python
利用Python产生加密表和解密表的实现方法
2019/10/15 Python
python实现人性化显示金额数字实例详解
2020/09/25 Python
Python爬虫破解登陆哔哩哔哩的方法
2020/11/17 Python
Ray-Ban雷朋奥地利官网:全球领先的太阳眼镜品牌
2020/10/12 全球购物
如果NULL和0作为空指针常数是等价的,那我到底该用哪一个
2014/09/16 面试题
网管求职信
2014/03/03 职场文书
学校文明单位申报材料
2014/05/06 职场文书
小学毕业典礼演讲稿
2014/09/09 职场文书
教师专业技术工作总结2015
2015/05/13 职场文书
2015年全民创业工作总结
2015/07/23 职场文书
纪检部部长竞选稿
2015/11/21 职场文书
Python办公自动化之Excel(中)
2021/05/24 Python