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 相关文章推荐
pyv8学习python和javascript变量进行交互
Dec 04 Python
Python中给List添加元素的4种方法分享
Nov 28 Python
Python re模块介绍
Nov 30 Python
使用C#配合ArcGIS Engine进行地理信息系统开发
Feb 19 Python
python 系统调用的实例详解
Jul 11 Python
python 实现一个贴吧图片爬虫的示例
Oct 12 Python
python3 pygame实现接小球游戏
May 14 Python
详解DeBug Python神级工具PySnooper
Jul 03 Python
基于Python实现2种反转链表方法代码实例
Jul 06 Python
对python中list的五种查找方法说明
Jul 13 Python
python 爬虫如何实现百度翻译
Nov 16 Python
Python读取pdf表格写入excel的方法
Jan 22 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语法速查表
2007/01/02 PHP
PHP判断表单复选框选中状态完整例子
2014/06/24 PHP
PHP中的数组处理函数实例总结
2016/01/09 PHP
PHP读取Excel类文件
2017/05/15 PHP
简单的无缝滚动程序-仅几行代码
2007/05/08 Javascript
js 分栏效果实现代码
2009/08/29 Javascript
javascript同页面多次调用弹出层具体实例代码
2013/08/16 Javascript
使用upstart把nodejs应用封装为系统服务实例
2014/06/01 NodeJs
jQuery使用before()和after()在元素前后添加内容的方法
2015/03/26 Javascript
Jquery插件之Fancybox丰富的弹出层效果附源码下载
2015/12/02 Javascript
JS禁止查看网页源代码的实现方法
2016/10/12 Javascript
预防网页挂马的方法总结
2016/11/03 Javascript
React-router中结合webpack实现按需加载实例
2017/05/25 Javascript
微信小程序实现折叠面板
2018/01/31 Javascript
vue中v-cloak解决刷新或者加载出现闪烁问题(显示变量)
2018/04/20 Javascript
解决vue this.$forceUpdate() 处理页面刷新问题(v-for循环值刷新等)
2018/07/26 Javascript
Vue2.x中利用@font-size引入字体图标报错的解决方法
2018/09/28 Javascript
详解ES6中的 Set Map 数据结构学习总结
2018/11/06 Javascript
如何使用vue slot创建一个模态框的实例代码
2020/05/24 Javascript
JavaScript实现H5接金币功能(实例代码)
2021/02/22 Javascript
将Django框架和遗留的Web应用集成的方法
2015/07/24 Python
Python 实现12306登录功能实例代码
2018/02/09 Python
Python中浅拷贝copy与深拷贝deepcopy的简单理解
2018/10/26 Python
python使用Paramiko模块实现远程文件拷贝
2019/04/30 Python
Django中提示消息messages的设置方式
2019/11/15 Python
从0到1使用python开发一个半自动答题小程序的实现
2020/05/12 Python
python 常见的排序算法实现汇总
2020/08/21 Python
如何基于Python爬虫爬取美团酒店信息
2020/11/03 Python
CSS3悬停效果案例应用
2012/11/21 HTML / CSS
教你如何一步一步用Canvas写一个贪吃蛇
2018/10/22 HTML / CSS
AVIS安飞士奥地利租车官网:提供奥地利、欧洲和全世界汽车租赁
2016/11/29 全球购物
施华洛世奇意大利官网:SWAROVSKI意大利
2018/07/23 全球购物
Ajax的工作原理
2015/12/04 面试题
美术专业学生个人自我评价
2013/09/19 职场文书
人事主管岗位职责
2014/01/30 职场文书
教学评估实施方案
2014/03/16 职场文书