commit
81020b5660
@ -0,0 +1,54 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||||
|
<modelVersion>4.0.0</modelVersion> |
||||||
|
|
||||||
|
<groupId>org.pqh</groupId> |
||||||
|
<artifactId>format.danmu</artifactId> |
||||||
|
<version>1.0-SNAPSHOT</version> |
||||||
|
<properties> |
||||||
|
<maven.compiler.source>1.8</maven.compiler.source> |
||||||
|
<maven.compiler.target>1.8</maven.compiler.target> |
||||||
|
</properties> |
||||||
|
|
||||||
|
<dependencies> |
||||||
|
<dependency> |
||||||
|
<groupId>org.jsoup</groupId> |
||||||
|
<artifactId>jsoup</artifactId> |
||||||
|
<version>1.11.3</version> |
||||||
|
</dependency> |
||||||
|
|
||||||
|
<dependency> |
||||||
|
<groupId>com.alibaba</groupId> |
||||||
|
<artifactId>fastjson</artifactId> |
||||||
|
<version>1.2.51</version> |
||||||
|
</dependency> |
||||||
|
|
||||||
|
<dependency> |
||||||
|
<groupId>org.dom4j</groupId> |
||||||
|
<artifactId>dom4j</artifactId> |
||||||
|
<version>2.1.1</version> |
||||||
|
</dependency> |
||||||
|
|
||||||
|
<dependency> |
||||||
|
<groupId>com.luhuiguo</groupId> |
||||||
|
<artifactId>chinese-utils</artifactId> |
||||||
|
<version>1.0</version> |
||||||
|
</dependency> |
||||||
|
|
||||||
|
|
||||||
|
<dependency> |
||||||
|
<groupId>junit</groupId> |
||||||
|
<artifactId>junit</artifactId> |
||||||
|
<version>4.12</version> |
||||||
|
<scope>compile</scope> |
||||||
|
</dependency> |
||||||
|
|
||||||
|
<dependency> |
||||||
|
<groupId>commons-io</groupId> |
||||||
|
<artifactId>commons-io</artifactId> |
||||||
|
<version>2.6</version> |
||||||
|
</dependency> |
||||||
|
</dependencies> |
||||||
|
</project> |
@ -0,0 +1,57 @@ |
|||||||
|
import com.alibaba.fastjson.JSON; |
||||||
|
import com.alibaba.fastjson.JSONObject; |
||||||
|
import com.luhuiguo.chinese.ChineseUtils; |
||||||
|
import org.jsoup.Connection; |
||||||
|
import org.jsoup.Jsoup; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
public class AniGamerParser implements Parser<JSONObject> { |
||||||
|
|
||||||
|
private static final String INTERFACE_URL ="https://ani.gamer.com.tw/ajax/danmuGet.php"; |
||||||
|
|
||||||
|
@Override |
||||||
|
public String color(JSONObject content) { |
||||||
|
return Integer.parseInt(content.getString("color").replace("#", ""), 16)+""; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String size(JSONObject content) { |
||||||
|
if(content.getIntValue("size")==2){ |
||||||
|
return "30"; |
||||||
|
}else{ |
||||||
|
return "25"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String text(JSONObject content) { |
||||||
|
return ChineseUtils.toSimplified(content.getString("text")); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String style(JSONObject content) { |
||||||
|
if(content.getIntValue("position")==2){ |
||||||
|
return "2"; |
||||||
|
}else{ |
||||||
|
return "1"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String time(JSONObject content) { |
||||||
|
return (content.getDoubleValue("time")/10)+""; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<JSONObject> parse(String playUrl) { |
||||||
|
String tstr; |
||||||
|
try { |
||||||
|
tstr = Jsoup.connect(INTERFACE_URL).ignoreContentType(true).method(Connection.Method.POST).data("sn", playUrl.replaceAll("\\D+","")).execute().body(); |
||||||
|
} catch (IOException e) { |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
return JSON.parseArray(tstr).toJavaList(JSONObject.class); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,38 @@ |
|||||||
|
import org.apache.commons.io.FileUtils; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.io.IOException; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
public class BuildDanmu<T> { |
||||||
|
private Parser<T> parser; |
||||||
|
|
||||||
|
private static final String DANMU_HEADER="<?xml version=\"1.0\" encoding=\"UTF-8\"?><i>\n"; |
||||||
|
|
||||||
|
public BuildDanmu(Parser<T> parser) { |
||||||
|
this.parser = parser; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 生成弹幕 |
||||||
|
* @param playUrl 播放地址 |
||||||
|
* @param filepath 生成路径 |
||||||
|
*/ |
||||||
|
public void build(String playUrl,String filepath){ |
||||||
|
List<T> list=parser.parse(playUrl); |
||||||
|
|
||||||
|
File danmuFile=new File(filepath); |
||||||
|
|
||||||
|
StringBuffer sb=new StringBuffer(DANMU_HEADER); |
||||||
|
for(T t:list){ |
||||||
|
sb.append("<d p=\"").append(parser.time(t)).append(",").append(parser.style(t)).append(",").append(parser.size(t)).append(",").append(parser.color(t)) |
||||||
|
.append(",0,0,0,0\">").append(parser.text(t)).append("</d>").append("\n"); |
||||||
|
} |
||||||
|
sb.append("</i>"); |
||||||
|
try { |
||||||
|
FileUtils.writeStringToFile(danmuFile,sb.toString(),"UTF-8"); |
||||||
|
} catch (IOException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,30 @@ |
|||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* 弹幕内容解释器 |
||||||
|
* @param <T> |
||||||
|
*/ |
||||||
|
public interface Parser<T> { |
||||||
|
//弹幕颜色
|
||||||
|
String color(T content); |
||||||
|
|
||||||
|
//弹幕大小
|
||||||
|
String size(T content); |
||||||
|
|
||||||
|
//弹幕文本
|
||||||
|
String text(T content); |
||||||
|
|
||||||
|
//弹幕移动样式
|
||||||
|
String style(T content); |
||||||
|
|
||||||
|
//弹幕发送时间
|
||||||
|
String time(T content); |
||||||
|
|
||||||
|
/** |
||||||
|
* 根据视频播放地址解析弹幕数据 |
||||||
|
* @param playUrl |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
List<T> parse(String playUrl); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,91 @@ |
|||||||
|
import org.dom4j.DocumentException; |
||||||
|
import org.dom4j.Element; |
||||||
|
import org.dom4j.io.SAXReader; |
||||||
|
import org.jsoup.Jsoup; |
||||||
|
import org.jsoup.nodes.Document; |
||||||
|
import org.jsoup.select.Elements; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
public class SohuParser implements Parser<Element> { |
||||||
|
@Override |
||||||
|
public String color(Element content) { |
||||||
|
return content.attributeValue("c"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String size(Element content) { |
||||||
|
switch (content.attributeValue("s")) { |
||||||
|
case "l": |
||||||
|
return "30"; |
||||||
|
case "m": |
||||||
|
return "25"; |
||||||
|
default: |
||||||
|
return "18"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String text(Element content) { |
||||||
|
return content.getText(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String style(Element content) { |
||||||
|
if (content.attributeValue("m").contains("f")) { |
||||||
|
switch (content.attributeValue("p")) { |
||||||
|
case "t": |
||||||
|
case "m": |
||||||
|
return "5"; |
||||||
|
default: |
||||||
|
return "4"; |
||||||
|
} |
||||||
|
} else if (content.attributeValue("m").contains("l")) { |
||||||
|
switch (content.attributeValue("p")) { |
||||||
|
case "t": |
||||||
|
case "m": |
||||||
|
return "1"; |
||||||
|
default: |
||||||
|
return "2"; |
||||||
|
} |
||||||
|
} else { |
||||||
|
return "1"; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String time(Element content) { |
||||||
|
return content.attributeValue("v"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<Element> parse(String playUrl) { |
||||||
|
Document doc; |
||||||
|
try { |
||||||
|
doc = Jsoup.connect(playUrl).get(); |
||||||
|
} catch (IOException e) { |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
Elements videosrc=doc.select("meta[property=og:videosrc]"); |
||||||
|
if(videosrc.size()!=1){ |
||||||
|
throw new RuntimeException("该视频:"+playUrl+"找不到弹幕"); |
||||||
|
} |
||||||
|
String vid = videosrc.get(0).attr("content").replaceAll("\\D",""); |
||||||
|
|
||||||
|
SAXReader reader = new SAXReader(); |
||||||
|
|
||||||
|
org.dom4j.Document document; |
||||||
|
try { |
||||||
|
document = reader.read("http://cdn.danmu.56.com/xml/2/v_" + vid + ".xml"); |
||||||
|
} catch (DocumentException e) { |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
|
||||||
|
Element d = document.getRootElement().elements("d").get(0); |
||||||
|
|
||||||
|
return d.elements("c"); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
import com.alibaba.fastjson.JSONObject; |
||||||
|
import org.dom4j.Element; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
public class TestBuild { |
||||||
|
@Test |
||||||
|
public void test() throws IOException { |
||||||
|
BuildDanmu<Element> b1=new BuildDanmu<>(new SohuParser()); |
||||||
|
b1.build("https://tv.sohu.com/v/MjAxNzA2MjIvbjYwMDAxNzkzNC5zaHRtbA==.html?fid=847&pvid=4d4db6d26aa0a4ec","D://BuildDanmu.xml"); |
||||||
|
|
||||||
|
BuildDanmu<JSONObject> buildDanmu=new BuildDanmu<>(new AniGamerParser()); |
||||||
|
buildDanmu.build("https://ani.gamer.com.tw/animeVideo.php?sn=10852","D://AniGamerParser.xml"); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue