当你在苦恼某站为什么不能下载保存到本地时,来看这篇文章就对了,本文手把手教你怎么样爬某站视频,从配置环境,到分析网页找到视频接口,最后爬取视频,保姆级教学!!!
因为某站是视频和音频分开的,所以我们还要把视频和音频合并在一起,在这里推荐用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 模块名
配置好环境直接开干!!!
分析网址:分析地址
这里介绍一下我自己的分析过程(赶时间可以直接跳过),大家都知道某站每个视频都有个关键字,通过这个关键字就能搜到视频,
关键字就是视频地址问号前面的
知道这个后,我当时想的是有这个关键字,那么视频下载地址是不是也有呢?于是我抱着试一试的心态,按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)
分析到,是不是感觉结束了?还没有哟,如果每一次爬某站的视频,都要打开开发者工具,然后去找那不是很麻烦吗?于是我接着再分析查询参数,如下
过程艰辛的,结果是美好的,只能一个个网址去找,一个个参数去分析,如果有更好的方法请告诉我(球球了),看图
一看到这个我就激动了,为什么因为这里有视频和音频的地址!!最主要的是和网页地址是一样的!!,那咱们只要有网页地址就能下载视频和音频,这不比上面的方法简单?
分析到这就结束了,按以下几步就能爬某站视频了!
爬网页视频网址,得到html数据,然后解析数据获得含有视频和音频地址的json数据,提取视频和音频网址,把视频和音频下载,最后用ffmpeg合并。
下面我们就来实现这几步。
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__=(.*?)
# findall 返回的是列表
string_re = re.findall('window.__playinfo__=(.*?)', 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)
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')
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')
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__=(.*?)', 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)
其实最主要的还是分析地址,找到接口,然后发送请求,就这么简单(写了好多博客,都不让过审,很无语,为什么别人能过)。
告诉各位,其实学爬虫最难的一步就是怎们找到对的地址,地址错了,其他都错了,所以第一步一定要对!!!。好了,如文章有错误,请指正,谢谢大家。