NiceLeeのBlog 用爱发电 bilibili~

Java 爬虫练习-bilibili视频下载 (五)

2019-03-02
nIceLee

阅读:


其实之前到(四),整个框架,包括下载、登录等功能已经基本完成,可以结束了。
但是,自己用着感觉不是很爽,下载异常后,整个视频都要重新下;而且前面HTML5的播放源没搞定一直是块心病,Flash将死未死这么多年,搞定这一块也是防患于未然。
是时候再搞一波事情了(๑•̀ㅂ•́)و✧

要做的事情

  • 增加在已下载文件的基础上继续下载的功能
    这个比较简单,改下HTTP请求的头部,本地稍稍改下代码逻辑即可。

  • 增加对HTML5播放源的下载支持
    这个可能会有麻烦,下载这方面不是问题;粗略看了一下,这个源分成了视频、音频两个部分,而且浏览器播放的时候是分成一段一段下载的,目前试着下了一整段,直接用播放器是打不开的。
    这个问题在于要不要模仿浏览器一段一段下载的行为,以及下下来后怎么处理。

以上,本文先讨论第一件事情。

思路

很难想象播放源的服务器会不支持断点续传,事实证明,B站也不例外。
那么问题就简单了。

原来的下载流程大概是这样子(有些步骤先后顺序可以替换):
根据avId生成对应文件名 + .part后缀(若存在便删除,重新下载)
–> 根据avId构造HTTP请求头部
–> 开始下载(从零开始)
–> 下载完毕后去掉后缀

根据avId生成对应文件名 + .part后缀(若存在,获取文件size)
–> 根据avId构造HTTP请求头部(range: bytes=size-)
–> 开始下载(先跳过f.seek(size))
–> 下载完毕后去掉后缀

实现

  • 获取下载进度,并修改HTTP请求头部
    long offset = 0;
    if (fileDownloadPart.exists()) {
      offset = fileDownloadPart.length();
      headers.put("range", "bytes=" + offset + "-");
    }
    
  • 获取文件随机访问对象,跳过已下载部分
    RandomAccessFile raf = new RandomAccessFile(fileDownloadPart, "rw");
    raf.seek(offset);
    

备注

也许有的朋友对HTTP协议不太熟悉,这里简单讲一下,如果服务器支持的话,客户端可以通过HTTP请求的头部Range标签来访问文件的部分内容,而不是整个文件。
这样,就给断点续传和多线程下载提供了可能。

源代码


内容
隐藏