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实现基于HTTP文件传输实例
Nov 08 Python
深入理解NumPy简明教程---数组3(组合)
Dec 17 Python
Python访问MongoDB,并且转换成Dataframe的方法
Oct 15 Python
python 找出list中最大或者最小几个数的索引方法
Oct 30 Python
Python数据分析:手把手教你用Pandas生成可视化图表的教程
Dec 15 Python
python使用response.read()接收json数据的实例
Dec 19 Python
python集成开发环境配置(pycharm)
Feb 14 Python
keras中的backend.clip用法
May 22 Python
python使用nibabel和sitk读取保存nii.gz文件实例
Jul 01 Python
python 删除excel表格重复行,数据预处理操作
Jul 06 Python
Django项目如何正确配置日志(logging)
Apr 29 Python
python装饰器代码解析
Mar 23 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下统计用户在线时间的一种尝试
2010/08/26 PHP
wamp安装后自定义配置的方法
2014/08/23 PHP
PHP fastcgi模式上传大文件(大约有300多K)报错
2014/09/28 PHP
CodeIgniter集成smarty的方法详解
2016/05/26 PHP
Thinkphp5结合layer弹窗定制操作结果页面
2017/07/07 PHP
一个简单的javascript类定义例子
2009/09/12 Javascript
jquery插件制作 自增长输入框实现代码
2012/08/17 jQuery
jquery中的查找parents与closest方法之间的区别
2013/12/02 Javascript
在JavaScript中使用timer示例
2014/05/08 Javascript
JS辨别访问浏览器判断是android还是ios系统
2014/08/19 Javascript
jQuery实现给页面换肤的方法
2015/05/30 Javascript
jquery+CSS实现的水平布局多级网页菜单效果
2015/08/24 Javascript
Nodejs中的this详解
2016/03/26 NodeJs
JQuery DIV 动态隐藏和显示的方法
2016/06/23 Javascript
jquery+css3问卷答题卡翻页动画效果示例
2016/10/26 Javascript
JS焦点图,JS 多个页面放多个焦点图的实例
2016/12/08 Javascript
vue 实现的树形菜的实例代码
2018/03/19 Javascript
JS中创建自定义类型的常用模式总结【工厂模式,构造函数模式,原型模式,动态原型模式等】
2019/01/19 Javascript
如何在JavaScript中优雅的提取循环内数据详解
2019/03/04 Javascript
python3 实现对图片进行局部切割的方法
2018/12/05 Python
python读取并写入mat文件的方法
2019/07/12 Python
python使用writerows写csv文件产生多余空行的处理方法
2019/08/01 Python
python多线程高级锁condition简单用法示例
2019/11/07 Python
使用Python进行防病毒免杀解析
2019/12/13 Python
Python类反射机制使用实例解析
2019/12/30 Python
戴尔新加坡官网:Dell Singapore
2020/12/13 全球购物
档案接收函范文
2014/01/10 职场文书
会计顶岗实习心得
2014/01/25 职场文书
初级会计求职信范文
2014/02/15 职场文书
亚运会口号
2014/06/20 职场文书
税务职业生涯规划书范文
2014/09/16 职场文书
服务整改报告
2014/11/06 职场文书
综合素质评价思想道德自我评价
2015/03/09 职场文书
国王的演讲观后感
2015/06/03 职场文书
MySQL分区表实现按月份归类
2021/11/01 MySQL
CSS使用Flex和Grid布局实现3D骰子
2022/08/05 HTML / CSS