在做短视频的时候,朋友经常问我这样的问题:
1. 有没有免费短视频去水印解析网站?
2. 短视频下载怎么不要水印?
3. 短视频怎么去水印?
我去网上找了一遍,要么限制次数,要么看完广告才能下载
最后还是自己做了一个,代码贴出来给你们改善
快手去水印已经不能用了,懒得改
需要导jsoup包
这富文本编辑框有点拉跨,xml格式竟然给我转换
<dependency>
<groupId>org.json</groupId>
<artifactId>jsoup</artifactId >
<version>1.12.2</version >
</dependency >
实现代码
import cn.hutool.core.map.MapUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/** org.jsoup jsoup 1.12.2 */
public class VideoService {
/** * 方法描述: 快手解析下载视频 * 用Jsoup 爬快手视频
* 1、首先获取js信息
* 2、取出window.pageData的信息
* @param url
* @author lxb
*/
public static String kuaiShouParseUrl(String url) {
HashMap headers = new HashMap<>();
headers.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
headers.put("Accept-Charset", "GB2312,utf-8;q=0.7,*;q=0.7");
headers.put("Accept-Encoding", "gzip, deflate, sdch, br");
headers.put("Accept-Language", "zh-cn,zh;q=0.8");
headers.put("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16D57 Version/12.0 Safari/604.1");
String redirectUrl = HttpUtil.createGet(url).addHeaders(headers).execute().header("Location");
System.out.println(redirectUrl); String body = HttpUtil.createGet(redirectUrl).addHeaders(headers).execute().body();
Document doc = Jsoup.parse(body); Elements videoElement = doc.select("script[type=text/javascript]");
String videoInfo = videoElement.get(3).data().replaceAll("window.pageData= ", "");
// 获取当前视频用户信息 JSONObject json = JSONObject.parseObject(videoInfo);
// 获取当前视频信息 JSONObject video = json.getJSONObject("video");
// 无水印视频地址 String videoUrl = video.getString("srcNoMark");
// 截取前面的数据 videoUrl = videoUrl.substring(0, videoUrl.indexOf("?")); return videoUrl; }
/** * 抖音解析下载视频 * 用Jsoup 解析
* 1、先获取该抖音视频ID
* 2、调用抖音接口获取视频真实地址 https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids= + 抖音视频ID
* 3、获取抖音无水印地址 把 https://aweme.snssdk.com/aweme/v1/playwm/ 的playwm替换成play
* 4、重新请求一次抖音无水印地址获取该视频原地址 * @param url
* @author lxb
*/
public static String douYinParseUrl(String url) {
String videoUrl = "";
try { Connection con= Jsoup.connect(url);
con.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
con.header("Accept-Charset", "GB2312,utf-8;q=0.7,*;q=0.7");
con.header("Accept-Encoding", "gzip, deflate, sdch, br");
con.header("Accept-Language", "zh-cn,zh;q=0.8");
con.header("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16D57 Version/12.0 Safari/604.1"); Connection.Response resp= con.method(Connection.Method.GET).execute(); String respUrl = resp.url().toString(); /** * 加上/video/这个7位数 * 获取 视频ID = 获取/video/ 和 / 中间的数据 */ String itemId = respUrl.split("/video/")[1].split("/")[0]; /** * (固定)https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids= * videoUrl = 视频链接 + 视频ID */ String trueAddress= "https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=" + itemId; String jsonStr = Jsoup.connect(trueAddress).ignoreContentType(true).execute().body(); JSONObject obj = JSONObject.parseObject(jsonStr); // 获取当前的视频的真实url String videoAddress= obj.getJSONArray("item_list").getJSONObject(0).getJSONObject("video").getJSONObject("play_addr").getJSONArray("url_list").get(0).toString(); /** * https://aweme.snssdk.com/aweme/v1/playwm/?video_id= * 把playwm替换成play */ videoAddress = videoAddress.replaceAll("playwm", "play"); // 重新请求一次抖音无水印地址 Map headers = MapUtil.newHashMap(); headers.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); headers.put("Accept-Charset", "GB2312,utf-8;q=0.7,*;q=0.7"); headers.put("Accept-Encoding", "gzip, deflate, sdch, br"); headers.put("Accept-Language", "zh-cn,zh;q=0.8"); headers.put("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16D57 Version/12.0 Safari/604.1"); // 该视频的原地址 videoUrl = HttpUtil.createGet(videoAddress).addHeaders(headers).execute().header("Location"); }catch (Exception e){ e.printStackTrace(); } return videoUrl; } /** * 抖音火山解析下载视频 * @param url * @author lxb */ public static String huoShanParseUrl(String url) { String videoUrl = ""; try { Connection con= Jsoup.connect(url); con.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); con.header("Accept-Charset", "GB2312,utf-8;q=0.7,*;q=0.7"); con.header("Accept-Encoding", "gzip, deflate, sdch, br"); con.header("Accept-Language", "zh-cn,zh;q=0.8"); con.header("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16D57 Version/12.0 Safari/604.1"); Connection.Response resp= con.method(Connection.Method.GET).execute(); String respUrl = resp.url().toString(); String itemId = respUrl.split("item_id=")[1].split("&")[0]; /** * (固定)https://share.huoshan.com/api/item/info?item_id= * videoUrl = 视频链接 + 视频ID */ String trueAddress= "https://share.huoshan.com/api/item/info?item_id=" + itemId; String jsonStr = Jsoup.connect(trueAddress).ignoreContentType(true).execute().body(); JSONObject obj = JSONObject.parseObject(jsonStr); // 获取当前的视频的真实url String video_url= obj.getJSONObject("data").getJSONObject("item_info").getString("url"); String video_id = video_url.split("video_id=")[1].split("&")[0]; String real_url = "http://hotsoon.snssdk.com/hotsoon/item/video/_playback/?video_id=" + video_id; // 重新请求一次无水印地址 Map headers = MapUtil.newHashMap(); headers.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); headers.put("Accept-Charset", "GB2312,utf-8;q=0.7,*;q=0.7"); headers.put("Accept-Encoding", "gzip, deflate, sdch, br"); headers.put("Accept-Language", "zh-cn,zh;q=0.8"); headers.put("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16D57 Version/12.0 Safari/604.1"); // 该视频的原地址 videoUrl = HttpUtil.createGet(real_url).addHeaders(headers).execute().header("Location"); }catch (Exception e){ e.printStackTrace(); } return videoUrl; } /** * 微视解析下载视频 * @param url * @author lxb */ public static String weiShiParseUrl(String url) { String videoUrl = ""; try { Connection con= Jsoup.connect(url); con.header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); con.header("Accept-Charset", "GB2312,utf-8;q=0.7,*;q=0.7"); con.header("Accept-Encoding", "gzip, deflate, sdch, br"); con.header("Accept-Language", "zh-cn,zh;q=0.8"); con.header("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16D57 Version/12.0 Safari/604.1"); Connection.Response resp= con.method(Connection.Method.GET).execute(); String respUrl = resp.url().toString(); String itemId = respUrl.split("feedid=")[1].split("&")[0]; /** * (固定)https://h5.qzone.qq.com/webapp/json/weishi/WSH5GetPlayPage?feedid * videoUrl = 视频链接 + 视频ID */ String trueAddress= "https://h5.qzone.qq.com/webapp/json/weishi/WSH5GetPlayPage?feedid=" + itemId; String jsonStr = Jsoup.connect(trueAddress).ignoreContentType(true).execute().body(); JSONObject obj = JSONObject.parseObject(jsonStr); // 获取当前的视频的真实url videoUrl= obj.getJSONObject("data").getJSONArray("feeds").getJSONObject(0).getString("video_url"); }catch (Exception e){ e.printStackTrace(); } return videoUrl; } public static void main(String[] args){// System.out.println(weiShiParseUrl(Utils.filterUrl("嗨,我正在参加微视“谁是王者人气英雄”挑战赛,快来帮我投票吧!>>https://h5.weishi.qq.com/weishi/wsplay/challenge2?feedid=78sKriqyF1KyJk2cT&challegeid=100543&spid=1558186608003629&qua=v1_iph_weishi_8.2.7_241_app_a&chid=127081004&pkg=&attach=cp_reserves3_1190370002")));// System.out.println(huoShanParseUrl(filterUrl("金名美食(家常菜)在火山分享了视频,快来围观!传送门戳我>>https://share.huoshan.com/hotsoon/s/FJ8Wl9cV0d8/ 复制此链接,打开【抖音火山版】,直接观看视频~")));// System.out.println(kuaishouParseUrl(filterUrl("出去玩就这?就这? #黑丝 https://v.kuaishou.com/6lIPLQ 复制此消息,打开【快手】直接观看!")));// System.out.println(douYinParseUrl(filterUrl("二三十岁人了,都是老样子,人很普通,说话又不够甜,长得也一般般,重要是,还没什么钱。#情感文字视频 https://v.douyin.com/JPoaJry/ 复制此链接,打开抖音,直接看观视频!")));// System.out.println(filterUrl("二三十岁人了,都是老样子,人很普通,说话又不够甜,长得也一般般,重要是,还没什么钱。#情感文字视频 https://v.douyin.com/JPoaJry/ 复制此链接,打开抖音,直接看观视频!")); } // 保存视频 public static void save(String s) throws Exception { long start = System.currentTimeMillis(); // 打开和URL之间的连接 HttpURLConnection conn2 = (HttpURLConnection) new URL(s).openConnection(); // 设置通用的请求属性 conn2.setRequestProperty("accept", "*/*"); conn2.setRequestProperty("connection", "Keep-Alive"); conn2.setRequestProperty("Accept-Charset", "utf-8"); conn2.setRequestProperty("Content-Type", "audio/mp3"); conn2.setRequestProperty("user-agent", "Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); conn2.setRequestMethod("GET"); conn2.connect(); // 定义BufferedReader输入流来读取URL的响应 InputStream in2 = conn2.getInputStream(); String last = ".mp4"; if (s.contains("mp4")) { last = ".mp4"; } else if (s.contains("mp3")) { last = ".mp3"; } else { last = ".mp4"; } //文件保存的位置 FileOutputStream fileOutputStream = new FileOutputStream(new File("D:\\" + new Date().getTime() + last)); byte[] b = new byte[1024 * 5]; int len; while ((len = in2.read(b)) != -1) { fileOutputStream.write(b, 0, len); } long end = System.currentTimeMillis(); System.out.println("用时间:" + (end - start) + "毫秒"); fileOutputStream.flush(); fileOutputStream.close(); }}
就这样了,我累了,斗不过这个富文本编辑框,将就看看吧