搜索

爬虫案列


发布时间: 2022-11-24 18:46:00    浏览次数:47 次

工欲善其事必先利其器,我们经常需要在B站上保存自己想要的“学习资料”。对于单一的视频,我们可以用“B站下载助手”即时下载,安装地址:https://chrome.google.com/webstore/detail/bilibili哔哩哔哩下载助手/bfcbfobhcjbkilcbehlnlchiinokiijp?hl=zh-CN

打开你要播放的视频页面,在页面底部会弹出下载助手的主界面
image

操作比较傻瓜化,但是遇到多P视频操作起来就不是很有好了,需要逐个点击确认。课件什么的一个个下很麻烦,有这工夫点开,视频也都顺便看完了,这时候就需要批量下载了。

解放双手,首选Python,我们来看看Python中有什么骚操作可以满足我们的“学习需求”

安装you-get

you-get是一个基于python的多媒体内容下载开源工具,在控制台输入pip3 install you-get ,我这里已经安装好了,
image

安装FFmpeg

you-get是基于ffmpeg进行视频音频处理的,如果不装ffmpeg,通常下载的视频是声音画面分开的两个文件,后续需要合并及转码就不能完成了。下载地址:https://www.ffmpeg.org/

下载测试

  • 安装完成后就可以进行下载了,先下载一个B站普通视频,在命令行中输入
you-get https://www.bilibili.com/video/BV1xK411773N

image
可以看到下载的是1080P的MP4文件(按默认最高画质,有时候下载的是flv)。

可以使用--info/-i以查看所有可用画质与格式,使用--format以指定下载的格式
image
如果输入的是一个多P视频的地址,you-get会提示你使用--playlist参数

you-get: This is a multipart video. (use --playlist to download all parts.)

哦豁,这不就是我们寻找的批量下载吗,赶紧试试

you-get --playlist https://www.bilibili.com/video/BV1B5411W7TW

然而这样下载经常会遇到网络延迟中断,这时又得重新执行上面的命令。而且是逐个视频下载的,经常会卡在某一个视频上下不动(貌似服务器端有速率限制),网速并没有很好地利用,此方法能用,但不好用,而且python还没出手,还不够风骚。

多线程下载

那怎样才能发挥我们Python的功效,让操作过程骚起来呢?既然一个命令行只能同时下载一个文件,那么我们就采用多线程模式同时下载多个文件。下面这就走起来

import you_get
import threading
import os
import time

def download1080(count,url):
    print("thread "+ str(count) +" is running")
    os.system("you-get --format=dash-flv "+url)

def download720(count,url):
    print("thread "+ str(count) +" is running")
    os.system("you-get --format=dash-flv720 "+url)

def downloaddefault(count,url):
    print("thread "+ str(count) +" is running")
    os.system("you-get "+url)

def showinfo(count,url):
    print("thread "+ str(count) +" is running")
    os.system("you-get -i "+url)

def test(arg):
    print("thread "+ str(arg) +" is running")
    os.system("ping www.baidu.com")
    print("thread "+ str(arg) +" finish")


if __name__ == '__main__':

    url_seed = 'https://www.bilibili.com/video/BV1MJ411u7Bc?p='
    thread_list = []
    url_num = 33
    thread_num = 8

    for i in range(1,url_num+1):
        #为每个新URL创建下载线程
        url = url_seed + str(i)
        t = threading.Thread(target=download720, args=(i,url))
        #加入线程池并启动
        thread_list.append(t)
        t.start()
        
        #print(thread_list[0])

        #当线程池满时,等待线程结束
        while len(thread_list)>thread_num:  
            #移除已结束线程
            thread_list = [x for x in thread_list if x.is_alive()]
            time.sleep(3)
           # print("running threads_________" + str(thread_list))

        pass

这里采用os.system()函数提交shell命令。首先定义几个函数分别下载不同清晰度格式,"you-get --format=dash-flv "、"you-get --format=dash-flv720 "、"you-get --format=dash-flv480 "、"you-get --format=dash-flv360 "。

确定下载视频的URL链接公共部分,去掉数字后缀

url_seed = 'https://www.bilibili.com/video/BV1MJ411u7Bc?p='

B站中多P视频的URL链接有两种形式,第一种是刚点开标题后出现的合集链接,第二种是点开右侧播放列表任意p视频时出现,这里需要传入的是第二种URL链接,下载对应的p=n的视频

#点开总标题时出现
https://www.bilibili.com/video/BV1MJ411u7Bc

#点开各Part
https://www.bilibili.com/video/BV1MJ411u7Bc?p=1
https://www.bilibili.com/video/BV1MJ411u7Bc?p=2
https://www.bilibili.com/video/BV1MJ411u7Bc?p=3
......

thread_list列表充当一个简单线程池,存放活动的下载线程。

url_num = 33 代表分P视频的总数,在右侧选集列表查看,这里是33。

image
thread_num =8 定义了线程池的线程数量上限,根据自己电脑的核心数和网络带宽确定,通常4~8就够用了。

下面就为每一个URL单独创建下载线程,启动下载,注意查看网页上最高支持的清晰度,选取不同的目标函数,这里最高清晰度为720P,选择target=download720。当线程池满了就等待先前的下载结束,每隔3秒查询一次

for i in range(1,url_num+1):
        #为每个新URL创建下载线程
        url = url_seed + str(i)
        t = threading.Thread(target=download720, args=(i,url))
        #加入线程池并启动
        thread_list.append(t)
        t.start()
        
        #print(thread_list[0])

        #当线程池满时,等待线程结束
        while len(thread_list)>thread_num:  
            #移除已结束线程
            thread_list = [x for x in thread_list if x.is_alive()]
            time.sleep(3)

将上述代码保存成download_with_you-get.py文件,下载新的合集时需要修改对应的url_seed,url_num和下载清晰度,然后在shell命令行中输入

python download_with_you-get.py

或者将上述命令保存成bat文件点击运行,这样就开始下载啦
image
image
image

我们看下效果,速度简直飞起,500Mbps带宽都跑满了,而且同时把弹幕文件也下载下来了,保存成xml文件,本地也可以看弹幕了,美滋滋。不过对于大多数课程视频,我们并不需要弹幕,可以在上面的bat文件加入一行 del *.xml 删除之。

如果网络负载过大,有时候会中断,或者请求时间过长导致程序退出,没关系,重新运行上面的bat就好了,you-get会自动断点续传,已下载的会跳过该文件。如果程序正常退出,那么所有的视频都下载好了。

image

文件重命名

不过等等,我们下载的视频文件都带了很长的父标题前缀,有时候文件列表里很难完全显示,需要把它简化一下,更清楚地看到是第几集,如上图,只需要保留小括号里边的内容作为文件名即可。

新建rename.py文件,内容如下

 coding: utf-8
import os
path = os.getcwd() +'\\'     

for f in os.listdir(path):
    if f.endswith(u'.mp4'):
        oldname = path + f 
        #print(f)
        f1 = f.split("(")
        try:
            f2 = f1[1].split(")")
        except:
            f2 = f1
        if f2[0].endswith(u'.mp4'):
            newname = path + f2[0]
        else:
            newname=path + f2[0] + '.mp4'
        os.rename(oldname,newname) 
        print(oldname,'======>',newname)

遍历当前文件夹下的所有文件,找出我们下载的MP4文件名,分割出小括号中间的内容作为新文件名,采用os.rename函数重命名文件。如果文件名中没有小括号(已经处理过),则沿用旧文件名,这样文件名就格式化好了
image
大会员视频

如何下载那些需要登录才能下载的视频呢,这时候就要用到cookies信息了。首先需要使用 firefox 火狐浏览器事先登录视频网站平台账号,在开始运行中输入%appdata%/Mozilla/firefox/profiles确定,会显示类似下面这样的文件夹
image
进入这个文件夹,找到 cookies.sqlite 文件,获得完整文件路径

// 每个人的文件夹名称可能不一样
86mdqb8b.default-release   
 
//完整文件路径
C:\Users\pizh12thu\AppData\Roaming\Mozilla\Firefox\Profiles\86mdqb8b.default-release\cookies.sqlite

在shell中输入以下内容,就可以下载大会员视频了

set cookie=C:\Users\pizh12thu\AppData\Roaming\Mozilla\Firefox\Profiles\86mdqb8b.default-release\cookies.sqlite
you-get -c %cookie% https://www.bilibili.com/bangumi/play/ep75275

指定--format=dash-hdflv2就可以下载大会员HD画质视频,我们修改一下py文件,提交命令时加上“-c %cookie%”参数,记得字符串前面加上r强制不转义,url_seed和url_num都做相应修改,target=downloadhd使用最高下载格式

def download1080(count,url):
    print("thread "+ str(count) +" is running")
    os.system(r"you-get -c %cookie% --format=dash-flv "+url)

def download720(count,url):
    print("thread "+ str(count) +" is running")
    os.system(r"you-get -c %cookie% --format=dash-flv720 "+url)

def downloadhd(count,url):
    print("thread "+ str(count) +" is running")
    os.system(r"you-get -c %cookie% --format=dash-hdflv2 "+url)

if __name__ == '__main__':

    url_seed = 'https://www.bilibili.com/bangumi/play/ep752' #后缀 + 74~85
    thread_list = []
    url_num = 85
    thread_num = 8

    for i in range(74,url_num+1):
        #为每个新URL创建下载线程
        url = url_seed + str(i)
        t = threading.Thread(target=downloadhd, args=(i,url))
        #加入线程池并启动
        thread_list.append(t)
        t.start()

image

image

转载自:https://zhuanlan.zhihu.com/p/365399646

免责声明 爬虫案列,资源类别:文本, 浏览次数:47 次, 文件大小:-- , 由本站蜘蛛搜索收录2022-11-24 06:46:00。此页面由程序自动采集,只作交流和学习使用,本站不储存任何资源文件,如有侵权内容请联系我们举报删除, 感谢您对本站的支持。 原文链接:https://www.cnblogs.com/tzmy/p/16922771.html