从网页抓取视频(一个没有建立文件写入对象完整的实现代码的原理)

优采云 发布时间: 2021-11-05 18:05

  从网页抓取视频(一个没有建立文件写入对象完整的实现代码的原理)

  用Java的IO流从网上下载视频的原理是在URL对象和目标地址之间建立链接,从这个链接中以IO流的形式读取下载视频的二进制数据,然后写入它到本地文件。

  因为小弟比较好吃,他不会下载那些加密的视频链接。在这里我找到了一个没有掩码的url来测试:

  代码思路首先建立一个链接对象,获取一个网页的链接;从链接对象获取输入流并读取数据;建立输出流将数据写入本地文件。代码

  获取链接对象

  public class download {

//定义一个HttpURLConnection在外面,因为要在finally中关闭

HttpURLConnection connection = null;

public static void main(String[] args) {

try {

//获取链接对象

URL url = new URL(videoUrl);

HttpURLConnection connection = url.openConnection();

connection.setRequestProperty("Range","bytes=0-");

connection.connect();

if(connection.getResponseCode() / 100 != 2){

System.out.println("链接资源失败...");

return;

}

} catch (MalformedURLException e) {

e.printStackTrace();

} finally {

HttpURLConnection.disconnect();

}

}

}

  好,现在来说说上面代码的作用:

  1.URL url = 新 URL(videoUrl);

  是获取URL的资源对象,传入的字符串就是对应的地址;

  2.HttpURLConnection connection = url.openConnection();

  是获取链接对象,就是依赖这个对象来获取流;

  3.connection.setRequestProperty("Range","bytes=0-");

  range表示读取范围,bytes=0-表示从0字节到最大字节,表示读取所有资源

  4.connection.connect();

  建立网页链接,链接成功后即可获取流;

  5.connection.getResponseCode() / 100 != 2

  这个判断的意思是,如果建立链接返回的对应代码在200到300之间,则为成功,否则链接失败

  获取流实现:

  InputStream inputStream = connection.getInputStream();

  获取流只需要一行代码,直接从连接对象中获取。

  实现文件写入:这里是RandomAccessFile的对象。

  String fileName = url.getFile();

fileName = fileName.substring(fileName.lastIndexOf("/")+1);

RandomAccessFile randomAccessFile = new RandomAccessFile(fileName,"rw");

  1. 第一行代码是获取文件名。这是一个解释。根据这个url,我们得到的fileName是/C79EBFF6107CE4389C33DC5901307461-20.mp4,意思是getFile获取的是.com路径后面的文件名,所以我用截取字符串的方式来获取文件名,当然, 也可以自行设置随机文件名

  2.字符串截取

  3.创建文件写入对象

  完整的实现代码贴在下面:

  package download;

import java.io.BufferedInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.RandomAccessFile;

import java.net.HttpURLConnection;

import java.net.MalformedURLException;

import java.net.URL;

public class DownloadVideo {

private static String videoUrl = "http://aqiniu.tangdou.com/C79EBFF6107CE4389C33DC5901307461-20.mp4";

private static final int MAX_BUFFER_SIZE = 1000000;

public static void main(String[] args) {

HttpURLConnection connection = null;

InputStream inputStream = null;

RandomAccessFile randomAccessFile = null;

try {

// 1.获取连接对象

URL url = new URL(videoUrl);

connection = (HttpURLConnection) url.openConnection();

connection.setRequestProperty("Range", "bytes=0-");

connection.connect();

if(connection.getResponseCode() / 100 != 2) {

System.out.println("连接失败...");

return;

}

// 2.获取连接对象的流

inputStream = connection.getInputStream();

//已下载的大小

int downloaded = 0;

//总文件的大小

int fileSize = connection.getContentLength();

String fileName = url.getFile();

fileName = fileName.substring(fileName.lastIndexOf("/") + 1);

// 3.把资源写入文件

randomAccessFile = new RandomAccessFile(fileName,"rw");

while(downloaded < fileSize) {

// 3.1设置缓存流的大小

byte[] buffer = null;

if(fileSize - downloaded >= MAX_BUFFER_SIZE) {

buffer = new byte[MAX_BUFFER_SIZE];

}else {

buffer = new byte[fileSize - downloaded];

}

// 3.2把每一次缓存的数据写入文件

int read = -1;

int currentDownload = 0;

long startTime = System.currentTimeMillis();

while(currentDownload < buffer.length) {

read = inputStream.read();

buffer[currentDownload ++] = (byte) read;

}

long endTime = System.currentTimeMillis();

double speed = 0.0;

if(endTime - startTime > 0) {

speed = currentDownload / 1024.0 / ((double)(endTime - startTime)/1000);

}

randomAccessFile.write(buffer);

downloaded += currentDownload;

randomAccessFile.seek(downloaded);

System.out.printf("下载了进度:%.2f%%,下载速度:%.1fkb/s(%.1fM/s)%n",downloaded * 1.0 / fileSize * 10000 / 100,speed,speed/1000);

}

} catch (MalformedURLException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}finally {

try {

connection.disconnect();

inputStream.close();

randomAccessFile.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

public static void demo() {

try {

URL url = new URL(videoUrl);

} catch (MalformedURLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

  下面是对上述代码的补充说明。MAX_BUFFER_SIZE 是我设置的缓存大小。在注释3.1中,判断当前剩余下载大小是否大于缓存,如果不是,则设置缓存大小为剩余。

  while(currentDownload < buffer.length) {

read = inputStream.read();

buffer[currentDownload ++] = (byte) read;

}

  此代码根据缓存的大小读取和写入该大小的字节。然后依次写入缓存的大小直到结束。

  这样做的好处是可以提高效率,保护硬盘,而不需要频繁的硬件写入。

  控制台输出:

  下载进度:11.59%,下载速度:388.0kb/s(0.4M/s)

  下载进度:23.19%,下载速度:262.5kb/s(0.3M/s)

  下载进度:34.78%,下载速度:261.0kb/s(0.3M/s)

  下载进度:46.38%,下载速度:258.3kb/s(0.3M/s)

  下载进度:57.97%,下载速度:260.0kb/s(0.3M/s)

  下载进度:69.57%,下载速度:260.9kb/s(0.3M/s)

  下载进度:81.16%,下载速度:257.4kb/s(0.3M/s)

  下载进度:92.75%,下载速度:252.3kb/s(0.3M/s)

  下载进度:100.00%,下载速度:286.5kb/s(0.3M/s) 好的,以上就是下载视频的简单实现,小弟就是刚学的不错,可能还有很多地方不太好,请大家多多指教。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线