环境与工具:win10 + IDEA
语言与框架:Java+JavaFX+Maven
功能描述
根据视频ID抽取该视频下的评论人员信息,统计总人数。评论页数对应的就是实际总评论分页。展示的就是幸运观众信息。程序很简单~
一. 效果
二. 代码
#项目结构
1. Maven 的 pom.xml
<?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.example</groupId>
<artifactId>JAVAMid</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.54</version>
</dependency>
<dependency>
<groupId>com.jfoenix</groupId>
<artifactId>jfoenix</artifactId>
<version>8.0.4</version>
</dependency>
<dependency>
<groupId>io.datafx</groupId>
<artifactId>datafx</artifactId>
<version>8.0.1</version>
</dependency>
<dependency>
<groupId>io.datafx</groupId>
<artifactId>flow</artifactId>
<version>8.0.1</version>
</dependency>
<dependency>
<groupId>de.jensd</groupId>
<artifactId>fontawesomefx</artifactId>
<version>8.9</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
2. UrlMip.java
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
/**
* @author lu123
*/
public class UrlMip extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("/fxml/UrlMip.fxml"));
primaryStage.setTitle("小破站视频评论抽奖");
Scene scene = new Scene(root, 900, 465);
primaryStage.setScene(scene);
primaryStage.getIcons().add(new Image("/img/icon1.jpg"));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
3. MyController.java
package org.urltest.luyuno_o;
import com.alibaba.fastjson.JSONObject;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.chart.PieChart;
import javafx.scene.control.*;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import java.awt.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author lu123
*/
public class MyController {
@FXML
Label myLabel;
@FXML
private TextField myID;
@FXML
private ImageView myFigure;
@FXML
private PieChart pieChart;
@FXML
ListView<String> listView;
@FXML
private TextField pageNum;
@FXML
private TextField avID;
@FXML
private ListView<String> ffans;
@FXML
private Hyperlink avLink;
private static String pgNum="";
private static String avNum="";
private static Set<String> set = new HashSet<String>();
private static Map<String, Integer> map1 = new HashMap<String, Integer>();
private static String[] keys = map1.keySet().toArray(new String[0]);
private String fans;
private String name;
private String title;
private String sign;
private String attention;
private String imgUrl;
private Map<Integer,String> map;
{
map = new HashMap<>();
map.put(10,"十人突破");
map.put(100,"百人进阶");
map.put(1000,"千人进度");
map.put(10000,"万人UP");
map.put(100000,"十万粉丝");
map.put(1000000,"百万大佬");
map.put(10000000,"千万成就");
map.put(100000000,"额~");
}
@FXML
public void onButton(ActionEvent event){
String url1 = "https://api.bilibili.com/x/web-interface/card?mid="+myID.getText()+"&jsonp=jsonp&article=true";
String json = loadJson(url1);
System.out.println(json);
JSONObject jsonObject = JSONObject.parseObject(json);
String dataS = jsonObject.getString("data");
JSONObject jsonObject2 = JSONObject.parseObject(dataS);
String cardS = jsonObject2.getString("card");
JSONObject jsonObject3 = JSONObject.parseObject(cardS);
name = jsonObject3.getString("name");
sign = jsonObject3.getString("sign");
imgUrl = jsonObject3.getString("face");
title = JSONObject.parseObject(jsonObject3.getString("Official")).getString("title");
fans = jsonObject3.getString("fans");
attention = jsonObject3.getString("attention");
//System.out.println("m名字: "+name+" 签名:"+sign+ " 关注了: "+attention+" 粉丝数: "+fans);
//图片
Image image = new Image(imgUrl);
myFigure.setImage(image);
//myID.setText(name);
//饼图
pieChart.setData(getChartData());
//ListView
Map<Integer,String> map = new HashMap<>();
listView.setItems(getViewList());
}
//列表List
private ObservableList<String> getViewList(){
ObservableList<String> items =FXCollections.observableArrayList();
items.add("名 字:"+name);
items.add("标 签:"+title);
items.add("关 注:"+attention);
items.add("粉丝数:"+fans);
items.add("签 名:"+sign);
return items;
}
//参加活动粉丝列表ffans
private ObservableList<String> setFansParty(Set<String> set){
ObservableList<String> items =FXCollections.observableArrayList();
int cc=0;
items.add("活动人数: "+set.size());
for(String ss:set){
cc++;
items.add(Integer.toString(cc)+": "+ss);
}
return items;
}
//饼图List
private ObservableList<PieChart.Data> getChartData() {
ObservableList<PieChart.Data> answer = FXCollections.observableArrayList();
long fansNum = Integer.parseInt(fans);
long k = fansNum/10;
int n = 10;
while(k>0){
n = n*10;
k=k/10;
}
if(n<100000000){
answer.addAll(new PieChart.Data("已有粉丝", fansNum),
new PieChart.Data(map.get(n), n-fansNum));
}else{
answer.addAll(new PieChart.Data("已有粉丝", fansNum),
new PieChart.Data("大佬我们做朋友吧~", 0));
}
return answer;
}
//加载json数据
public String loadJson (String url) {
StringBuilder json = new StringBuilder();
try {
URL urlObject = new URL(url);
URLConnection uc = urlObject.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream()));
String inputLine = null;
while ( (inputLine = in.readLine()) != null) {
json.append(inputLine);
}
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return json.toString();
}
//爬取信息
@FXML
public void getComments(ActionEvent event){
if((!pgNum.equals(pageNum.getText())) || (!avNum.equals(avID.getText()))) {
map1 = new HashMap<String, Integer>();
set = new HashSet<>();
avLink.setAccessibleText("https://www.bilibili.com/video/av" + avID.getText());
avLink.setText("https://www.bilibili.com/video/av" + avID.getText());
int pageC = Integer.parseInt(pageNum.getText());
for (int page = 1; page <= pageC; page++) {
String url = "https://api.bilibili.com/x/v2/reply?jsonp=jsonp&pn=" + page +
"&type=1&oid=" + avID.getText() + "&sort=0";
String json = loadJson(url);
String reg = "\"mid\":\"[0-9]+\"";
String regname = "\"uname\":\"((?!\").)*\"";
//编译正则表达式
Pattern pattern = Pattern.compile(reg);
Pattern patternname = Pattern.compile(regname);
Matcher matcher = pattern.matcher(json);
Matcher matchername = patternname.matcher(json);
while (matchername.find()) {
String[] aa = matchername.group().split("\"");
set.add(aa[3]);
}
while (matcher.find()) {
String[] aa = matcher.group().split("\"");
map1.put(aa[3], 1);
}
}
keys = map1.keySet().toArray(new String[0]);
}
System.out.println(pgNum+" "+avNum);
pgNum = pageNum.getText();
avNum = avID.getText();
System.out.println(pgNum+" "+avNum);
//中奖号码fansNo
String fansNo="";
Random random = new Random();
fansNo = keys[random.nextInt(keys.length)];
myID.setText(fansNo);
onButton(event);
ffans.setItems(setFansParty(set));
}
//连接到外浏览器
@FXML
private void onHyperlink(ActionEvent event) throws URISyntaxException, IOException {
Desktop.getDesktop().browse(new URI(avLink.getText()));
}
}
4. UrlMip.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.chart.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<Pane prefHeight="469.0" prefWidth="892.0" xmlns="http://javafx.com/javafx/8.0.212" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.urltest.luyuno_o.MyController">
<Label fx:id="mylabel" layoutX="14.0" layoutY="9.0" prefHeight="32.0" prefWidth="65.0" text=" UID :" textOverrun="CLIP"/>
<TextField fx:id="myID" layoutX="81.0" layoutY="10.0" onAction="#onButton" prefHeight="30.0" prefWidth="266.0" text="321173469" />
<ImageView fx:id="myFigure" fitHeight="156.0" fitWidth="183.0" layoutX="14.0" layoutY="70.0" pickOnBounds="true" preserveRatio="true" />
<PieChart fx:id="pieChart" layoutX="14.0" layoutY="233.0" legendSide="BOTTOM" prefHeight="219.0" prefWidth="312.0" />
<ListView fx:id="listView" layoutX="204.0" layoutY="72.0" opacity="0.8" prefHeight="152.0" prefWidth="472.0" />
<Label layoutX="407.0" layoutY="274.0" prefHeight="32.0" prefWidth="95.0" text="评论页数" textOverrun="CLIP"/>
<TextField fx:id="pageNum" layoutX="506.0" layoutY="275.0" onAction="#onButton" prefHeight="30.0" prefWidth="164.0" text="1" />
<Label layoutX="424.0" layoutY="328.0" prefHeight="32.0" prefWidth="78.0" text="视频ID" textOverrun="CLIP">
</Label>
<TextField fx:id="avID" layoutX="506.0" layoutY="329.0" onAction="#onButton" prefHeight="30.0" prefWidth="164.0" text="15928671" />
<Button fx:id="choujiang" layoutX="575.0" layoutY="381.0" mnemonicParsing="false" onAction="#getComments" prefHeight="30.0" prefWidth="95.0" text="抽奖" />
<ListView fx:id="ffans" layoutX="683.0" layoutY="72.0" prefHeight="363.0" prefWidth="193.0" />
<Hyperlink fx:id="avLink" onAction="#onHyperlink" layoutX="318.0" layoutY="435.0" prefHeight="28.0" prefWidth="352.0" >https://www.bilibili.com</Hyperlink>
</Pane>