2022年 11月 8日

用python爬视频,超详细,让下载成为可能(某站)

文章目录

  • 前言
  • 一、配置环境
  • 二、分析网页
  • 三、实现需求
  • 1.提取视频和音频地址
  • 2.下载视频和音频并保存
  • 3.合并视频和音频
  • 四、完整代码
  • 五、总结

前言

当你在苦恼某站为什么不能下载保存到本地时,来看这篇文章就对了,本文手把手教你怎么样爬某站视频,从配置环境,到分析网页找到视频接口,最后爬取视频,保姆级教学!!!

一、配置环境

因为某站是视频和音频分开的,所以我们还要把视频和音频合并在一起,在这里推荐用ffmpeg,本文也是用ffmpeg来合并的。
Nick Peng的安装教程!!
爬某站要用到的模块

import requests
import os  # 内置
import re  # 内置
import pprint
import parsel
import subprocess  # 内置
import json  # 内置
import pprint # 内置

# 内置模块源不需要安装
# 安装模块
pip install 模块名

# 如果觉得安装太慢,可以用镜像源, 我这用的是清华镜像源
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 模块名

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

配置好环境直接开干!!!

二、分析网页

分析网址:分析地址
这里介绍一下我自己的分析过程(赶时间可以直接跳过),大家都知道某站每个视频都有个关键字,通过这个关键字就能搜到视频,
关键字就是视频地址问号前面的

知道这个后,我当时想的是有这个关键字,那么视频下载地址是不是也有呢?于是我抱着试一试的心态,按F12打开开发者工具,按Ctry+f打开搜索框,把BV1eY411A7EE输入,确实有几个结果,但是一看都不是,难受。

于是,我只能在Network里去找,记住,按F12打开后,这时我们打开的Network是没有什么数据的,我们要重新刷新网页一下,重新抓包!!!,千万不要犯这么低级错误(虽然我犯过,那时我还好奇为什么啥都没有…),最后我只找到了这两个最像视频和音频地址。
在这里插入图片描述
我双击那个链接,结果弹出这个。
在这里插入图片描述
我当时一看到这个就蒙了,没办法,出现问题就解决问题,这种情况一般是没有权限,服务器拒绝访问,那我们用requests也爬不到,那这时候我们的防盗链登场了!
防盗链就是告诉服务器我是从哪个页面链接过来的,就这们简单。

看代码,加上防盗链就爬到了,因为某站视频和音频是分开的,不知道哪个是视频哪个是音频,于是我随机试了几个,发现数字大的是视频,数字小的是音频。如图

在这里插入图片描述
记住要找尾缀m4s结尾的地址,爬下来的文件视频保存为mp4,音频保存为mp3就行。

import requests

u = 'https://upos-sz-mirrorhwo1.bilivideo.com/upgcxcode/11/03/712170311/712170311-1-100023.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1652549671&gen=playurlv2&os=hwo1bv&oi=2871784383&trid=05b1c0e21f0a462dafbc95157c829522u&platform=pc&upsig=e104e6de253baac52d393c92e7d3a646&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&mid=1057432079&bvc=vod&nettype=0&orderid=0,3&agrr=1&bw=54053&logo=80000000'

headers = {'Referer': 'https://www.bilibili.com/video/BV1eY411A7EE?spm_id_from=333.851.b_7265636f6d6d656e64.6',
           'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36'
           }

response = requests.get(url=u, headers=headers).content

with open('wen.mp4', mode='wb') as f:
    f.write(response)


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

分析到,是不是感觉结束了?还没有哟,如果每一次爬某站的视频,都要打开开发者工具,然后去找那不是很麻烦吗?于是我接着再分析查询参数,如下

在这里插入图片描述

过程艰辛的,结果是美好的,只能一个个网址去找,一个个参数去分析,如果有更好的方法请告诉我(球球了),看图

在这里插入图片描述
一看到这个我就激动了,为什么因为这里有视频和音频的地址!!最主要的是和网页地址是一样的!!,那咱们只要有网页地址就能下载视频和音频,这不比上面的方法简单?

分析到这就结束了,按以下几步就能爬某站视频了!
爬网页视频网址,得到html数据,然后解析数据获得含有视频和音频地址的json数据,提取视频和音频网址,把视频和音频下载,最后用ffmpeg合并。

下面我们就来实现这几步。

三、实现需求

1.提取视频和音频地址

import requests
import re
import pprint
import json

# 视频网址
u = ''


# 定义一个发送请求的函数,因为后面还会调用
def get_url(url, referer=None):
    headers = {  'Referer': referer,
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36'
    }

    response = requests.get(url=url, headers=headers)
    # 返回response对象,后面还有二进制的数据,不能写死

    return response


html = get_url(u).text
# 构建正则表达式,提取数据 window.__playinfo__=(.*?)</scrip>
# findall 返回的是列表
string_re = re.findall('window.__playinfo__=(.*?)</script>', html)[0]

json_data = json.loads(string_re)

# 美化数据输出,便于我们分析数据
# pprint.pprint(json_data)

audio = json_data['data']['dash']['audio'][0]['backupUrl'][0]

# 大家可以选择视频的清晰度
# video = json_data['data']['dash']['video'][1]['backupUrl'][0]
# 这个是清晰度最高的了
video = json_data['data']['dash']['video'][0]['backupUrl'][0]
# print(audio)
# print(video)


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

2.下载视频和音频并保存

import os
import requests

# 这段代码单独运行不会成功
# 这里定义一个保存数据函数,因为要保存两次
def save_file(data, file_name):
	# 提示
    tip = file_name.split('.')[0]
    # 如果没有'va'的目录就创建一个,有就不创建

    if not os.path.exists('va'):
        os.mkdir('va')
    # 数据将保存到va目录里
    with open('va\\' + file_name, mode='wb') as f:
        f.write(data)
    print(tip + '保存完成!')


# 防盗链

#
# 视频,音频是二进制数据
er_video = get_url(video, u).content
er_audio = get_url(audio, u).content

# 文件名一定要加尾缀
save_file(er_video, 'video.mp4')
save_file(er_audio, 'audio.mp3')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

3.合并视频和音频

import subprocess
import os


# 合并视频
def join_va(video_name, audio_file, new_name):
    str_cmd = 'ffmpeg -i ' + 'va/' + video_name + '.mp4' + ' -i ' + 'va/' + audio_file + '.mp3' + ' -acodec copy -vcodec copy ' + "va/" + new_name + '.mp4'
    print('开始合成')
    # 创建一个进程开始来执行这个指令
    subprocess.call(str_cmd, shell=True)
    '''选择是否删除原mp3、mp4文件'''
    flag = True
    if flag:
        try:
            os.remove('va/' + video_name + '.mp4')
            os.remove('va/' + audio_file + '.mp3')
            print('删除成公')
        except:
            print('未删除!')
    print('合成结束')

join_va('video', 'audio', 'new')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

四、完整代码

import requests
import re
import json
import os
import subprocess


# 定义一个发送请求的函数,因为后面还会调用
def get_url(url, referer=None):
    headers = {'Referer': referer,
               'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36'
               }

    response = requests.get(url=url, headers=headers)
    # 返回response对象,后面还有二进制的数据,不能写死
    return response


def return_url(url):
    html = get_url(url).text
    # findall 返回的是列表
    string_re = re.findall('window.__playinfo__=(.*?)</script>', html)[0]

    json_data = json.loads(string_re)

    audio = json_data['data']['dash']['audio'][0]['backupUrl'][0]
    video = json_data['data']['dash']['video'][0]['backupUrl'][0]
    return video, audio


def save_file(data, file_name):
    tip = file_name.split('.')[0]
    if not os.path.exists('va'):
        os.mkdir('va')
    with open('va\\' + file_name, mode='wb') as f:
        f.write(data)
    print(tip + '保存完成!')


def tied(url_va, u):
    # 返回的是元组

    er_video = get_url(url_va[0], u).content
    er_audio = get_url(url_va[1], u).content

    save_file(er_video, 'video.mp4')
    save_file(er_audio, 'audio.mp3')


def join_va(new_name):
    str_cmd = 'ffmpeg -i ' + 'va/' + 'video.mp4 ' + ' -i ' + 'va/' + 'audio.mp3' + ' -acodec copy -vcodec copy ' + "va/" + new_name + '.mp4'
    print('开始合成')
    subprocess.call(str_cmd, shell=True)
    '''选择是否删除原mp3、mp4文件'''
    flag = True
    if flag:
        try:
            os.remove('va/' + 'video.mp4')
            os.remove('va/' + 'audio.mp3')
            print('删除成公')
        except:
            print('未删除!')
    print('合成结束')


def main(a_url, new_file):
    url_va = return_url(a_url)
    tied(url_va, a_url)
    # 合成视频命名
    join_va(new_file)


if __name__ == '__main__':
    # 网页地址
    # 视频网址
    url = ''
    # 合成后的文件名 里已经加了尾缀,所以不需要加了
    new_name = 'cc'
    main(url, new_name)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80

五、总结

其实最主要的还是分析地址,找到接口,然后发送请求,就这么简单(写了好多博客,都不让过审,很无语,为什么别人能过)。
告诉各位,其实学爬虫最难的一步就是怎们找到对的地址,地址错了,其他都错了,所以第一步一定要对!!!。好了,如文章有错误,请指正,谢谢大家。