从网页抓取视频(一个没有建立文件写入对象完整的实现代码的原理)
优采云 发布时间: 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) 好的,以上就是下载视频的简单实现,小弟就是刚学的不错,可能还有很多地方不太好,请大家多多指教。