了解一些B站的API
使用的API均为WEB API
登录API (下载分辨率>480P的视频)
扫码登陆 (可能是最容易实现的api)
基本流程: 申请二维码URL及扫码密钥->生成二维码->轮询服务器->扫码登录后->获取cookie
申请二维码URL及扫码密钥
GET http://passport.bilibili.com/qrcode/getLoginUrl
密钥超时为180秒
json回复:
根对象:
字段 | 类型 | 内容 | 备注 |
---|---|---|---|
code | num | 返回值 | 0:成功 |
status | bool | true | 作用尚不明确 |
ts | num | 请求时间 | 时间戳 |
data | obj | 信息本体 |
data
对象:
字段 | 类型 | 内容 | 备注 |
---|---|---|---|
url | str | 二维码内容url | 恒为87字符 |
oauthKey | str | 扫码登录秘钥 | 恒为32字符 |
使用扫码登录
POST http://passport.bilibili.com/qrcode/getLoginInfo
密钥超时为180秒
验证登录成功后会进行设置以下cookie项:
DedeUserID
DedeUserID__ckMd5
SESSDATA
bili_jct
正文参数( application/x-www-form-urlencoded ):
参数名 | 类型 | 内容 | 必要性 | 备注 |
---|---|---|---|---|
oauthKey | str | 扫码登录秘钥 | 必要 | |
gourl | str | 跳转url | 非必要 | 默认为http://www.bilibili.com |
json回复:
根对象:
字段 | 类型 | 内容 | 备注 |
---|---|---|---|
code | num | 返回值 | 0:成功 |
message | str | 错误信息 | 正确无 |
ts | num | 扫码时间 | 错误无 |
status | bool | 扫码是否成功 | true:成功 false:未成功 |
data | 正确时:obj 错误时:num | 正确时:游戏分站url 错误时:错误代码 | 未成功时: -1:密钥错误 -2:密钥超时 -4:未扫描 -5:未确认 |
data 对象:
字段 | 类型 | 内容 | 备注 |
---|---|---|---|
url | str | 游戏分站跨域登录url |
密码登录/短信登录接口注意事项
GET https://passport.bilibili.com/x/passport-login/captcha?source=main_web
- 请求验证码参数,得到登录密钥
key
与极验idgt
和极验KEYchallenge
- 进行滑动or点击验证
- 返回验证结果
validate
与seccode
,进行短信或密码登录
此api详情请查看: SocialSisterYi/bilibili-API-collect/bilibili-API-collect/login/login_action
验证器开源链接:
密码登录
基本流程: 密码输入->人机验证通过->获取盐值->RSA加密->返回数据->获取cookie
获取盐值
GET http://passport.bilibili.com/login?act=getkey
json回复:
字段 | 类型 | 内容 | 备注 |
---|---|---|---|
hash | str | 密码校验盐值 | 有效时间为20s |
key | str | RSA公钥 | 公钥为固定值 |
加密
盐值+登录密码->然后使用RSA公钥进行加密
登录
POST http://passport.bilibili.com/web/login/v2
验证登录成功后会进行设置以下cookie项:
sid
DedeUserID
DedeUserID__ckMd5
SESSDATA
bili_jct
SESSDATA
和 bili_jct
正文参数( application/x-www-form-urlencoded ):
参数名 | 类型 | 内容 | 必要性 | 备注 |
---|---|---|---|---|
captchaType | num | 6 | 必要 | 必须为6 |
username | str | 用户登录账号 | 必要 | 手机号或邮箱地址 |
password | str | 加密后的带盐密码 | 必要 | base64格式 |
keep | bool | true | 必要 | 必须为true |
key | str | 登录秘钥 | 必要 | 从B站API获取 |
challenge | str | 极验challenge | 必要 | 从B站API获取 |
validate | str | 极验结果 | 必要 | 从极验获取 |
seccode | str | 极验结果 | 必要 | 从极验获取 |
json回复:
根对象:
字段 | 类型 | 内容 | 备注 |
---|---|---|---|
code | num | 返回值 | 0:成功 -400:请求错误 -629:账号或密码错误 -653:用户名或密码不能为空 -662:提交超时,请重新提交 -2001:缺少必要的的参数 -2100:需验证手机号或邮箱 2400:登录秘钥错误 2406:验证极验服务出错 86000:RSA解密失败 |
ts | num | 当前时间戳 | 成功时无此项 |
message | str | 错误信息 | 默认为0 |
data | obj | 数据本体 | 成功时有此项 |
短信验证码登录
基本流程: 获取国际地区代码->人机验证通过->发送验证码->返回数据->获取cookie
获取国际地区代码
GET http://passport.bilibili.com/web/generic/country/list
json回复:
根对象:
字段 | 类型 | 内容 | 备注 |
---|---|---|---|
code | num | 返回值 | 0:成功 |
data | obj | 数据本体 |
data
对象:
字段 | 类型 | 内容 | 备注 |
---|---|---|---|
common | array | 常用国家或地区 | |
others | array | 其他国家或地区 |
data
中的common
和others
数组:
项 | 类型 | 内容 | 备注 |
---|---|---|---|
0 | obj | 国家或地区1 | |
n | obj | 国家或地区(n+1) | |
…… | obj | …… | …… |
common
和others
数组中的对象:
字段 | 类型 | 内容 | 备注 |
---|---|---|---|
id | num | 国际代码值 | |
cname | str | 国家或地区名 | |
country_id | str | 国家或地区区号 |
发送短信验证码
POST http://passport.bilibili.com/x/passport-login/web/sms/send
正文参数( application/x-www-form-urlencoded ):
参数名 | 类型 | 内容 | 必要性 | 备注 |
---|---|---|---|---|
tel | num | 手机号码 | 必要 | |
cid | num | 国际地区代码 | 必要 | |
source | str | 固定为main_web | 必要 | |
token | str | 在获取gt,challenge处url有 | 必要 | |
challenge | str | 极验challenge | 必要 | 从B站API获取 |
validate | str | 极验结果 | 必要 | 从极验获取 |
seccode | str | 极验结果+|jordan | 必要 | 从极验获取 |
json回复:
根对象:
字段 | 类型 | 内容 | 备注 |
---|---|---|---|
code | num | 返回值 | 0:成功 -400:请求错误 1002:手机号格式错误 86203:短信发送次数已达上限 1003:验证码已经发送 1025:该手机号在哔哩哔哩有过永久封禁记录,无法再次注册或绑定新账号 2400:登录秘钥错误 2406:验证极验服务出错 |
message | str | 错误信息 | 成功为0 |
data | obj | 数据 | 内含captcha_key |
captcha_key
在下方传参时需要,请备用. 使用短信验证码登录
验证登录成功后会进行设置以下cookie项:
DedeUserID
DedeUserID__ckMd5
SESSDATA
bili_jct
正文参数( application/x-www-form-urlencoded ):
参数名 | 类型 | 内容 | 必要性 | 备注 |
---|---|---|---|---|
cid | num | 国际地区代码 | 必要 | |
tel | num | 手机号码 | 必要 | |
code | num | 短信验证码 | 必要 | 超时时间为5min |
source | str | 固定为main_web | 必要 | |
captcha_key | str | 上方发送短信验证码时的一个参数 | 必要 | |
go_url | str | 跳转url | 非必要 | 默认为https://www.bilibili.com |
keep | str | 未知 | 非必要 | 默认为true |
json回复:
根对象:
字段 | 类型 | 内容 | 备注 |
---|---|---|---|
code | num | 返回值 | 0:成功 -400:请求错误 1006:请输入正确的短信验证码 1007:短信验证码已过期 |
message | str | 错误信息 | |
data | obj | 信息本体 |
data
对象:
字段 | 类型 | 内容 | 备注 |
---|---|---|---|
is_new | bool | false | 未知,估计是未注册时自动注册新用户 |
status | num | 0 | 未知,可能0就是成功吧 |
url | str | 跳转url | 默认为https://www.bilibili.com |
获取下载视频URL
这里就不过多赘述了,有兴趣的可以去看看
喜闻乐见的代码环节
登录
package me.heartalborada.bilidownloader.utils;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import javafx.scene.control.Alert;
import me.heartalborada.bilidownloader.main;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.cookie.Cookie;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import static me.heartalborada.bilidownloader.utils.internet.sendPost;
public class login {
public static boolean checkIsLogin(){
String data= null;
try {
data = new internet().getWithCookie(
"http://api.bilibili.com/x/web-interface/nav",
"SESSDATA="+ main.SESSDATA+"; bili_jct="+main.bili_jct
);
} catch (IOException e) {
e.printStackTrace();
}
if (data != null) {
if(JsonParser.parseString(data).getAsJsonObject().get("code").getAsInt()==0){
return true;
}
}
return false;
}
public static class password{
private static String key="";
private static String encrypt(String str) {
//base64编码的公钥
byte[] decoded = org.apache.commons.codec.binary.Base64.decodeBase64(key);
RSAPublicKey pubKey = null;
String outStr = null;
try {
pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)));
} catch (InvalidKeySpecException | BadPaddingException | IllegalBlockSizeException | InvalidKeyException | NoSuchPaddingException | NoSuchAlgorithmException e) {
e.printStackTrace();
}
//RSA加密
return outStr;
}
private static String getHashAndKey(){
String data = null;
try {
data=new internet().Eget("http://passport.bilibili.com/login?act=getkey");
} catch (Exception e) {
e.printStackTrace();
}
key=JsonParser.parseString(data).getAsJsonObject().get("key").getAsString().replace("-----BEGIN PUBLIC KEY-----","").replace("-----END PUBLIC KEY-----","").replace("\n","");
return JsonParser.parseString(data).getAsJsonObject().get("hash").getAsString();
}
public static String[] getCaptcha(){
String data = null;
try {
data=new internet().Eget("https://passport.bilibili.com/web/captcha/combine?plat=6");
} catch (Exception e) {
e.printStackTrace();
}
JsonObject json = JsonParser.parseString(data).getAsJsonObject();
if(json.get("code").getAsInt()==0) {
json=json.getAsJsonObject("data").getAsJsonObject("result");
return new String[]{
json.get("gt").getAsString(),
json.get("challenge").getAsString(),
json.get("key").getAsString()
};
}
return null;
}
public static String getPw(String pw){
String pw1= getHashAndKey()+pw;
String tmp=null;
try {
tmp=encrypt(pw1);
} catch (Exception e) {
e.printStackTrace();
}
return tmp;
}
public static void doLogin(String acc, String pw, String[] captcha) {
HashMap<String,Object> map=new HashMap<>();
map.put("captchaType",6);
map.put("username", acc);
map.put("password", pw);
map.put("keep",true);
map.put("key",captcha[0]);
map.put("challenge",captcha[1]);
map.put("validate",captcha[2]);
map.put("seccode",captcha[3]);
try {
Object[] data=internet.sendPost("http://passport.bilibili.com/web/login/v2",map);
if (data != null) {
if(JsonParser.parseString(String.valueOf(data[0])).getAsJsonObject().get("code").getAsInt()==0){
JsonObject json=new JsonObject();
@SuppressWarnings("unchecked")
List<Cookie> list= (List<Cookie>) data[1];
for(Cookie cookie:list){
if(cookie.getName().equals("SESSDATA")){
json.addProperty("SESSDATA",cookie.getValue());
}
if(cookie.getName().equals("bili_jct")){
json.addProperty("bili_jct",cookie.getValue());
}
}
new file().write(main.cookie_file_dir,json.toString());
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.titleProperty().set("信息");
alert.setHeaderText("登录成功");
alert.showAndWait();
me.heartalborada.bilidownloader.gui.login.close();
me.heartalborada.bilidownloader.gui.captcha.close();
} else {
int code=JsonParser.parseString(String.valueOf(data[0])).getAsJsonObject().get("code").getAsInt();
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.titleProperty().set("错误");
switch (code){
case -400:
alert.setHeaderText("错误代码: "+code+" 请求错误\n请联系开发者");
break;
case -629:
alert.setHeaderText("错误代码: "+code+"-账号或密码错误\n请检查你的账号或密码");
break;
case -653:
alert.setHeaderText("错误代码: "+code+"-用户名或密码不能为空\n请检查你的账号或密码");
break;
case -662:
alert.setHeaderText("错误代码: "+code+"-提交超时,请重新提交\n请重新打开验证窗口并提交");
break;
case -2001:
alert.setHeaderText("错误代码: "+code+"-缺少必要的的参数\n请联系开发者");
break;
case -2110:
alert.setHeaderText("错误代码: "+code+"-需验证手机号或邮箱\n请使用验证码登录或扫码登陆");
break;
case 2400:
alert.setHeaderText("错误代码: "+code+"-登录秘钥错误\n请联系开发者");
break;
case 2406:
alert.setHeaderText("错误代码: "+code+"-验证极验服务出错\n请检查\"validate\"和\"seccode\"是否填写正确");
break;
case 86000:
alert.setHeaderText("错误代码: "+code+"-RSA解密失败\n请联系开发者");
break;
default:
alert.setHeaderText("错误代码: "+code+"-未知错误\n请联系开发者");
}
alert.showAndWait();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static class sms{
public static LinkedHashMap<String,Integer> getSmsLocationMap(){
String data= null;
try {
data = new internet().Eget("http://passport.bilibili.com/web/generic/country/list");
} catch (Exception e) {
e.printStackTrace();
}
JsonObject json= JsonParser.parseString(data).getAsJsonObject().get("data").getAsJsonObject();
LinkedHashMap<String,Integer> map=new LinkedHashMap<>();
JsonArray array=json.get("common").getAsJsonArray();
for(JsonElement o:array){
JsonObject json1= o.getAsJsonObject();
map.put(json1.get("cname").getAsString(),json1.get("country_id").getAsInt());
}
array=json.get("others").getAsJsonArray();
for(JsonElement o:array){
JsonObject json1= o.getAsJsonObject();
map.put(json1.get("cname").getAsString(),json1.get("country_id").getAsInt());
}
return map;
}
public static String[] getCaptcha(){
String data = null;
try {
data=new internet().Eget("https://passport.bilibili.com/x/passport-login/captcha?source=main_web");
} catch (Exception e) {
e.printStackTrace();
}
JsonObject json = JsonParser.parseString(data).getAsJsonObject();
if(json.get("code").getAsInt()==0) {
JsonObject res=json.getAsJsonObject("data");
return new String[]{
res.getAsJsonObject("geetest").get("gt").getAsString(),
res.getAsJsonObject("geetest").get("challenge").getAsString(),
res.get("token").getAsString()
};
}
return null;
}
public static String SendSmsCaptcha(long phone_num, int cid, String[] captcha){
HashMap<String,Object> map=new HashMap<>();
map.put("tel",phone_num);
map.put("cid",cid);
map.put("source","main_web");
map.put("token",captcha[0]);
map.put("challenge",captcha[1]);
map.put("validate",captcha[2]);
map.put("seccode",captcha[3]);
Object[] data=sendPost("http://passport.bilibili.com/x/passport-login/web/sms/send",map);
JsonObject json= JsonParser.parseString(String.valueOf(data[0])).getAsJsonObject();
if(json.get("code").getAsInt()==0){
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.titleProperty().set("信息");
alert.headerTextProperty().set("短信验证码已发送");
alert.showAndWait();
return json.getAsJsonObject("data").get("captcha_key").getAsString();
} else {
int code=json.get("code").getAsInt();
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.titleProperty().set("错误");
switch (code){
case -400:
alert.setHeaderText("错误代码: "+code+" -请求错误\n请联系开发者");
break;
case 1002:
alert.setHeaderText("错误代码: "+code+" -手机号格式错误\n请检查你的手机号和国家或区域是否填写正确");
break;
case 86203:
alert.setHeaderText("错误代码: "+code+" -短信发送次数已达上限\n请稍后重试");
break;
case 1003:
alert.setHeaderText("错误代码: "+code+" -验证码已经发送\n请稍后重试");
break;
case 1025:
alert.setHeaderText("错误代码: "+code+" -该手机号在哔哩哔哩有过永久封禁记录, 无法再次注册或绑定新账号\n请联系哔哩哔哩");
break;
case 2400:
alert.setHeaderText("错误代码: "+code+" -登录秘钥错误\n请联系开发者");
break;
case 2404:
alert.setHeaderText("错误代码: "+code+" -验证极验服务出错\n请检查\"validate\"和\"seccode\"是否填写正确");
break;
default:
alert.setHeaderText("错误代码: "+code+" -未知错误\n请联系开发者");
}
alert.showAndWait();
}
return "";
}
public static void doLogin(int cid, long phone_num, long sms_code,String captcha_key){
HashMap<String,Object> map=new HashMap<>();
map.put("cid",cid);
map.put("tel",phone_num);
map.put("code",sms_code);
map.put("captcha_key",captcha_key);
map.put("source","main_web");
try {
Object[] data=internet.sendPost("https://passport.bilibili.com/x/passport-login/web/login/sms",map);
if (data != null) {
if(JsonParser.parseString(String.valueOf(data[0])).getAsJsonObject().get("code").getAsInt()==0){
JsonObject json=new JsonObject();
@SuppressWarnings("unchecked")
List<Cookie> list= (List<Cookie>) data[1];
for(Cookie cookie:list){
if(cookie.getName().equals("SESSDATA")){
json.addProperty("SESSDATA",cookie.getValue());
}
if(cookie.getName().equals("bili_jct")){
json.addProperty("bili_jct",cookie.getValue());
}
}
new file().write(main.cookie_file_dir,json.toString());
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.titleProperty().set("信息");
alert.setHeaderText("登录成功");
alert.showAndWait();
me.heartalborada.bilidownloader.gui.login.close();
me.heartalborada.bilidownloader.gui.captcha.close();
} else {
int code=JsonParser.parseString(String.valueOf(data[0])).getAsJsonObject().get("code").getAsInt();
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.titleProperty().set("错误");
switch (code){
case -400:
alert.setHeaderText("错误代码: "+code+" 请求错误\n请联系开发者");
break;
case 1006:
alert.setHeaderText("错误代码: "+code+" 请输入正确的短信验证码\n请检查短信验证码是否填写正确");
break;
case 1007:
alert.setHeaderText("错误代码: "+code+" 短信验证码已过期\n请重新发送验证码");
break;
default:
alert.setHeaderText("错误代码: "+code+"-未知错误\n请联系开发者");
}
alert.showAndWait();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static class qr{
public static String getOauthKey(){
String data= null;
try {
data = new internet().Eget("http://passport.bilibili.com/qrcode/getLoginUrl");
} catch (Exception e) {
e.printStackTrace();
}
return JsonParser.parseString(data).getAsJsonObject().getAsJsonObject("data").get("oauthKey").getAsString();
}
public static String[] IsLogin(String OauthKey) throws IOException {
HashMap<String,Object> map=new HashMap<>();
map.put("oauthKey",OauthKey);
Object[] data=sendPost("http://passport.bilibili.com/qrcode/getLoginInfo",map);
JsonObject json=JsonParser.parseString(String.valueOf(data[0])).getAsJsonObject();
if(!json.get("status").getAsBoolean()){
if(json.get("data").getAsInt()==-4){
return new String[]{"0","未扫描"};
}
if(json.get("data").getAsInt()==-5){
return new String[]{"0","已扫描, 但未确认"};
}
}
if(json.get("status").getAsBoolean()){
JsonObject json1=new JsonObject();
@SuppressWarnings("unchecked")
List<Cookie> list= (List<Cookie>) data[1];
for(Cookie cookie:list){
if(cookie.getName().equals("SESSDATA")){
json1.addProperty("SESSDATA",cookie.getValue());
}
if(cookie.getName().equals("bili_jct")){
json1.addProperty("bili_jct",cookie.getValue());
}
}
new file().write(main.cookie_file_dir,json1.toString());
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.titleProperty().set("信息");
alert.setHeaderText("登录成功");
alert.show();
me.heartalborada.bilidownloader.gui.login.close();
return new String[]{"1",json.getAsJsonObject("data").get("url").getAsString()};
}
return new String[]{"0","未知错误, 错误代码"+json.get("data").getAsInt()};
}
}
}
获取视频URL:
package me.heartalborada.bilidownloader.utils;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import me.heartalborada.bilidownloader.main;
import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class video {
public static LinkedHashMap<String, Long> getCidList(String aid){
LinkedHashMap<String,Long> map=new LinkedHashMap<String,Long>();
String data=null;
try {
data=new internet().Eget("https://api.bilibili.com/x/web-interface/view?aid="+aid);
} catch (Exception e) {
e.printStackTrace();
}
JsonObject json= JsonParser.parseString(data).getAsJsonObject();
if(json.get("code").getAsInt()==0) {
JsonArray pages=json.get("data").getAsJsonObject().get("pages").getAsJsonArray();
int i=0;
for (JsonElement o : pages) {
map.put("P"+i+" "+o.getAsJsonObject().get("part").getAsString(),o.getAsJsonObject().get("cid").getAsLong());
i++;
}
}
return map;
}
public static String BVidToAid(String BVid){
String data=null;
try {
data=new internet().Eget("https://api.bilibili.com/x/web-interface/view?bvid="+BVid);
} catch (Exception e) {
e.printStackTrace();
}
JsonObject json=JsonParser.parseString(data).getAsJsonObject();
if(json.get("code").getAsInt()==0) {
return json.get("data").getAsJsonObject().get("aid").getAsString();
}
return "404";
}
private static JsonObject json;
public String getVideoUrl(String aid, long cid, int qn1){
String data=null;
try {
data=new internet().getWithCookie(
"https://api.bilibili.com/x/player/playurl?avid="+aid+"&cid="+cid+"&fourk=1&qn="+qn1,
"SESSDATA="+ main.SESSDATA+"; bili_jct="+main.bili_jct
);
} catch (Exception e) {
e.printStackTrace();
}
json=JsonParser.parseString(data).getAsJsonObject();
System.out.println(json);
if(json.get("code").getAsInt()==0){
return json.getAsJsonObject("data").get("durl").getAsJsonArray().get(0).getAsJsonObject().get("url").getAsString();
}
return "404";
}
public static LinkedHashMap<String,Integer> getQuality(String aid, long cid){
LinkedHashMap<String,Integer>map= new LinkedHashMap<>();
String data=null;
try {
data=new internet().Eget("https://api.bilibili.com/x/player/playurl?avid="+aid+"&cid="+cid+"&fourk=1");
} catch (Exception e) {
e.printStackTrace();
}
JsonObject json=JsonParser.parseString(data).getAsJsonObject();
if(json.get("code").getAsInt()==0){
JsonArray description= json.get("data").getAsJsonObject().get("accept_description").getAsJsonArray();
JsonArray quality= json.get("data").getAsJsonObject().get("accept_quality").getAsJsonArray();
for(int i=0;i<description.size();i++){
map.put(description.get(i).getAsString(),quality.get(i).getAsInt());
}
}
return map;
}
public static JsonObject getVideoJson(String aid){
String data=null;
try {
data = new internet().Eget("https://api.bilibili.com/x/web-interface/view?aid=" + aid);
} catch (Exception e) {
e.printStackTrace();
}
return JsonParser.parseString(data).getAsJsonObject();
}
public static String getVideoPic(JsonObject json){
return json.getAsJsonObject("data").get("pic").getAsString();
}
public static boolean checkStrIsNum(String str) {
Pattern NUMBER_PATTERN = Pattern.compile("-?[0-9]+(\\.[0-9]+)?");
String bigStr;
try {
/** 先将str转成BigDecimal,然后在转成String */
bigStr = new BigDecimal(str).toString();
} catch (Exception e) {
/** 如果转换数字失败,说明该str并非全部为数字 */
return false;
}
Matcher isNum = NUMBER_PATTERN.matcher(str);
if (!isNum.matches()) {
return false;
}
return true;
}
public static boolean videoIsExist(JsonObject json){
return json.get("code").getAsInt()==0;
}
}
然后再加上一点点UI就可以正常运行了
演示GIF:
我的开源项目:
🐂∠( ᐛ 」∠)_
tql