功能设计:
1.实现读者文章的预览及下载
(实现了单击预览,双击下载)
2.实现文章查找
(实现了通过文章名查找(关键字)或者文章期数或年份(或者年份加期数))
实现步骤:
首先是数据库设计:
数据库使用一个数据表即可,三个字段,一个是filename用于储存文章名,一个是filepath用于储存文章链接,最后一个是time用于储存文章年份及期数。
create table duzhefile
(
filename char(20),
filepath char(100),
time char(6)
)
数据库创建成功后先将数据写入:
Duzhecurl.java
1 package All;
2
3 import java.sql.Connection;
4 import java.sql.PreparedStatement;
5
6 import org.jsoup.Jsoup;
7 import org.jsoup.nodes.Document;
8 import org.jsoup.select.Elements;
9
10 public class Duzhecurl {
11
12 public static void main(String[] args) throws Exception {
13 // 第一步:访问读者首页
14 String url = "https://www.dzwzzz.com/";
15 Document document = Jsoup.connect(url).get();
16
17 // 第二步:解析页面
18 Elements datatime = document.select("a");
19 //获取a标签
20 for(int num=0;num<datatime.size();num++) {
21 //判断文章链接
22 if(datatime.get(num).attr("href").charAt(4)=='_') {
23 //获取a标签中href属性的值
24 String deHref = datatime.get(num).attr("href");
25 System.out.println("开始获取"+deHref.substring(0, 4)+"年第"+deHref.substring(5,7)+"期");
26 String time = deHref.substring(0,4)+deHref.substring(5,7);
27 //访问不同期刊页面
28 String DuZhe = "https://www.dzwzzz.com/"+deHref;
29 Document newdocu = Jsoup.connect(DuZhe).get();
30 //获取a标签
31 Elements a_Elements = newdocu.select("a");
32 for(int i=0;i<a_Elements.size();i++) {
33 //判断是否是文章链接
34 if (a_Elements.get(i).attr("href").charAt(0)=='d'
35 &&a_Elements.get(i).attr("href").charAt(1)=='u')
36 {
37 //访问文章所在页
38 String purpose = "https://www.dzwzzz.com/"+deHref.substring(0, 8)+a_Elements.get(i).attr("href");
39 Document finaldocu = Jsoup.connect(purpose).get();
40 //获取文章标题
41 Elements h1_elements = finaldocu.select("h1");
42 String title = h1_elements.text();
43 //获取文章内容
44 Elements p_Elements = finaldocu.select("p");
45 String Content = p_Elements.text();
46 String sql = "insert into duzhefile values(?,?,?)";
47 Connection conn = Connect.getConnection();
48 PreparedStatement pstmt = conn.prepareStatement(sql);
49 pstmt.setString(1, title);
50 pstmt.setString(2, purpose);
51 pstmt.setString(3, time);
52 pstmt.execute();
53 System.out.println("文章地址"+purpose);
54 System.out.println(title+" 写入成功!");
55 }
56 }
57 }
58 }
59
60 }
61
62 }
数据库写入之后开始设计界面:
FirstPage.fxml
1 <?xml version="1.0" encoding="UTF-8"?>
2
3 <?import javafx.scene.paint.*?>
4 <?import javafx.scene.text.*?>
5 <?import java.lang.*?>
6 <?import javafx.scene.control.*?>
7 <?import javafx.scene.layout.*?>
8 <?import javafx.scene.layout.AnchorPane?>
9
10 <AnchorPane prefHeight="361.0" prefWidth="643.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="All.FirstPageController">
11 <children>
12 <Pane prefHeight="420.0" prefWidth="643.0">
13 <children>
14 <TextField fx:id="SelectFile" layoutX="27.0" layoutY="24.0" prefHeight="23.0" prefWidth="184.0" promptText="输入文件名搜索" />
15 <Button fx:id="Select" layoutX="236.0" layoutY="24.0" mnemonicParsing="false" onMouseClicked="#ClickToSelect" text="搜索" />
16 <TableView fx:id="FileTest" layoutY="74.0" onMouseClicked="#SelectFile" prefHeight="345.0" prefWidth="394.0">
17 <columns>
18 <TableColumn fx:id="FileName" editable="false" prefWidth="152.0" text="文件名" />
19 <TableColumn fx:id="FilePath" editable="false" prefWidth="241.0" text="路径" />
20 </columns>
21 </TableView>
22 <Text fx:id="Preview" layoutX="398.0" layoutY="-170.0" strokeType="OUTSIDE" strokeWidth="0.0" text="文件名" textAlignment="CENTER" wrappingWidth="246.12109375" y="200.0">
23 <font>
24 <Font size="18.0" />
25 </font>
26 <fill>
27 <RadialGradient centerX="0.40555555555555556" centerY="0.5" radius="0.5">
28 <stops>
29 <Stop color="#dd3b09" />
30 <Stop color="#00dff8" offset="1.0" />
31 </stops>
32 </RadialGradient>
33 </fill>
34 </Text>
35 <Text layoutX="22.0" layoutY="65.0" strokeType="OUTSIDE" strokeWidth="0.0" text="单击预览文章,双击下载文章" wrappingWidth="194.0" />
36 <Button fx:id="reset" layoutX="305.0" layoutY="24.0" mnemonicParsing="false" onMouseClicked="#ClickToReset" text="返回" />
37 <Text fx:id="content" layoutX="394.0" layoutY="62.0" strokeType="OUTSIDE" strokeWidth="0.0" text="内容预览" textAlignment="CENTER" wrappingWidth="253.12109375" />
38 </children>
39 </Pane>
40 </children>
41 </AnchorPane>
界面设计完成后是这个样的:
生成控制类后插入数据并实现各个方法:
FirstPageController.java
1 package All;
2
3 import java.io.File;
4 import java.io.FileNotFoundException;
5 import java.io.FileOutputStream;
6 import java.io.IOException;
7 import java.io.OutputStreamWriter;
8 import java.io.UnsupportedEncodingException;
9 import java.net.URL;
10 import java.sql.Connection;
11 import java.sql.PreparedStatement;
12 import java.sql.ResultSet;
13 import java.sql.SQLException;
14 import java.util.ResourceBundle;
15 import java.util.Scanner;
16 import java.util.regex.Matcher;
17 import java.util.regex.Pattern;
18
19 import org.jsoup.Jsoup;
20 import org.jsoup.nodes.Document;
21 import org.jsoup.select.Elements;
22 import org.omg.CORBA.PUBLIC_MEMBER;
23
24 import javafx.collections.FXCollections;
25 import javafx.collections.ObservableList;
26 import javafx.fxml.FXML;
27 import javafx.fxml.Initializable;
28 import javafx.scene.control.Alert;
29 import javafx.scene.control.Button;
30 import javafx.scene.control.Label;
31 import javafx.scene.control.TableColumn;
32 import javafx.scene.control.TableView;
33 import javafx.scene.control.TextArea;
34 import javafx.scene.control.TextField;
35 import javafx.scene.control.Alert.AlertType;
36 import javafx.scene.input.MouseEvent;
37 import javafx.scene.text.Text;
38
39 public class FirstPageController implements Initializable {
40 @FXML
41 private TextField SelectFile;//输入框
42 @FXML
43 private Button Select;//查找按钮
44 @FXML
45 private Button reset;//返回按钮
46 @FXML
47 private Text content;//预览内容
48 @FXML
49 private TableView<Data> FileTest;//表格
50 @FXML
51 private TableColumn<Data, String> FileName;//第一列存文章名
52 @FXML
53 private TableColumn<Data, String> FilePath;//第二列存文章链接
54 @FXML
55
56 private Text Preview;//预览标题
57
58 private ObservableList<Data> cellData = FXCollections.observableArrayList();
59 //用于存储数据Data类型的
60 @FXML
61 public void SelectFile(MouseEvent event) throws IOException {
62 Data data = FileTest.getSelectionModel().getSelectedItem();//获取所选择的行的Data对象
63 String filename = data.getFilename().getValue();//获取选择的Data对象的文章名
64 String url = data.getFilepath().getValue();//获取选择的Data对象的文章地址
65 Document doc;//用来存储爬取到的网页源码
66 String Finacontent;//用来存储文章内容
67 try {
68 doc = Jsoup.connect(url).get();//获取Data对象的文章源码
69 Elements p_Elements = doc.select("p");//查找P标签
70 String Content = p_Elements.text();//保存p标签的内容
71 Preview.setText(filename);//将文章名写入面板
72 content.setText(Content);//将P标签的内容写入预览内容框中
73 Finacontent = Content;//将文章内容传出去
74 } catch (IOException e) {
75 Finacontent = null;//告诉外面内容为空
76 }
77 if (event.getClickCount() == 2 && Finacontent.length() > 50) {
78 //如果点击了两下且文章内容大于50个字符则
79 File file = new File("E:/FileTest/" + filename + ".txt");
80 // 创建文件输出流
81 OutputStreamWriter fileOutputStream;
82 try {
83 fileOutputStream = new OutputStreamWriter(new FileOutputStream(file, true), "UTF-8");
84 // 这里的true功能是不覆盖原有内容,所以多次运行程序会造成重复
85 // 将文章内容写入文件
86 fileOutputStream.write(Finacontent.toString());
87 fileOutputStream.close();//关闭流操作
88 System.out.println(filename + " 下载成功!");//提示成功
89 //弹出弹窗提示下载成功
90 Alert alert = new Alert(AlertType.INFORMATION);
91 alert.setTitle("提示");
92 alert.setContentText("下载成功!!");
93 alert.setHeaderText("文章已保存到"+"E:/FileTest目录下");
94 alert.showAndWait();
95 } catch (UnsupportedEncodingException e) {
96 e.printStackTrace();
97 } catch (FileNotFoundException e) {
98 e.printStackTrace();
99 }
100
101 }
102 }
103 @FXML
104 public void ClickToReset(MouseEvent event) {
105 AddData();//如果点击了返回按钮则重新将数据写入表格
106 }
107 @FXML
108 public void ClickToSelect(MouseEvent event) {
109 String prama = SelectFile.getText();//获取输入框输入输入的内容
110 String strMatch1 = "^\\d{1,6}$";//正则表达式匹配1-6位数字
111 Pattern pattern = Pattern.compile(strMatch1);//使用匹配规则
112 Matcher matcher = pattern.matcher(prama);//进行匹配
113 String regex = "[\\u4E00-\\u9FA5]"; //正则表达式匹配汉字
114 Matcher m = Pattern.compile(regex).matcher(prama);//使用匹配汉字规则进行匹配
115 if (matcher.find()==true) {//如果匹配数字成功则进行数据库查找(对文章日期进行查找)
116 cellData.removeAll(cellData);//清空原有的cellData里的数据
117 Connection conn = Connect.getConnection();//获取数据库连接
118 String sql = "select * from duzhefile where time like ?";//定义数据库查询语句
119 try {
120 // 执行查询语句
121 PreparedStatement prep = conn.prepareStatement(sql);
122 prep.setString(1, '%' + prama.replace(" ", "") + '%');//将输入的内容除去空格后绑定到数据库语句中
123 ResultSet res = prep.executeQuery();//执行数据库查询语句并将结果返回到ResultSet对象中
124 while (res.next()) {//如果结果有下一行
125 String name = res.getString("filename");
126 String path = res.getString("filepath");
127 cellData.add(0, new Data(name, path));//将查询到的文章名和文章地址插入cellData中
128 }
129 if (!res.absolute(1)) {//如果查询结果不存在第一行(即为空),则弹窗提示查找结果为空
130 Alert alert = new Alert(AlertType.ERROR);
131 alert.setTitle("提示");
132 alert.setContentText("请重新输入!");
133 alert.setHeaderText("查询结果为空!");
134 alert.showAndWait();
135 AddData();//将所有数据重新插入(因为查询的时候清空了)
136 }
137 } catch (SQLException e) {
138 e.printStackTrace();
139 }
140 FileName.setCellValueFactory(cellData -> cellData.getValue().getFilename());
141 FilePath.setCellValueFactory(cellData -> cellData.getValue().getFilepath());
142 FileTest.setItems(cellData);//将cellData绑定到表格
143 }
144 else if (m.find()) {//如果匹配汉字成功
145 cellData.removeAll(cellData);//清空原有的数据
146 Connection conn = Connect.getConnection();//获取数据库连接
147 String sql = "select * from duzhefile where filename like ?";//定义数据库查询语句
148 try {
149 // 执行查询语句
150 PreparedStatement prep = conn.prepareStatement(sql);
151 prep.setString(1, '%'+ prama.replace(" ", "")+'%');//去除空格后绑定参数
152 ResultSet res = prep.executeQuery();//执行查询语句并返回结果
153 while (res.next()) {//如果查询结果不为空
154 String name = res.getString("filename");
155 String path = res.getString("filepath");
156 cellData.add(0, new Data(name, path));//将查询到的数据写入cellData中
157
158 }
159 if (!res.absolute(1)) {//如果查询结果不存在第一行(为空),则弹窗提示查找结果为空
160 Alert alert = new Alert(AlertType.ERROR);
161 alert.setTitle("提示");
162 alert.setContentText("请重新输入!");
163 alert.setHeaderText("查询结果为空!");
164 alert.showAndWait();
165 AddData();//将所有数据重新插入(因为查询的时候清空了)
166 }
167 } catch (SQLException e) {
168 e.printStackTrace();
169 }
170 FileName.setCellValueFactory(cellData -> cellData.getValue().getFilename());
171 FilePath.setCellValueFactory(cellData -> cellData.getValue().getFilepath());
172 FileTest.setItems(cellData);//将cellData绑定到表格中
173 }
174 else if(prama.length()==0){//如果输入的内容为空(即没有输入)则弹窗提示重新输入
175 AddData();
176 Alert alert = new Alert(AlertType.ERROR);
177 alert.setTitle("提示");
178 alert.setContentText("请重新输入!");
179 alert.setHeaderText("您输入的信息有误!\n输入文件名、年份、月份均可查找");
180 alert.showAndWait();
181 }
182 }
183
184 private Main main;
185 public void setMain(Main main) {
186 this.main = main;
187 }
188
189 @Override
190 public void initialize(URL location, ResourceBundle resources) {
191 AddData();//加载页面时写入数据
192 }
193
194 private void AddData() {//将数据库查询结果写入cellData中,封装成方法方便多次调用
195 Connection conn = Connect.getConnection();
196 String Strsql = "select * from duzhefile";
197 try {
198 // 执行查询语句
199 PreparedStatement prep = conn.prepareStatement(Strsql);
200 ResultSet res = prep.executeQuery();
201 while (res.next()) {
202 String name = res.getString("filename");
203 String path = res.getString("filepath");
204 cellData.add(0, new Data(name,path));
205
206 }
207 } catch (SQLException e) {
208 e.printStackTrace();
209 }
210 FileName.setCellValueFactory(cellData -> cellData.getValue().getFilename());
211 FilePath.setCellValueFactory(cellData -> cellData.getValue().getFilepath());
212 FileTest.setItems(cellData);
213 }
214
215 }
用到的Data类如下:
Data.java
1 package All;
2
3 import javafx.beans.property.SimpleStringProperty;
4
5 public class Data {
6 private SimpleStringProperty filename;
7 private SimpleStringProperty filepath;
8
9
10 public Data(String name,String path) {
11 this.filename = new SimpleStringProperty(name);
12 this.filepath = new SimpleStringProperty(path);
13 }
14
15
16 public SimpleStringProperty getFilename() {
17 return filename;
18 }
19
20
21 public void setFilename(String filename) {
22 this.filename = new SimpleStringProperty(filename);
23 }
24
25
26 public SimpleStringProperty getFilepath() {
27 return filepath;
28 }
29
30
31 public void setFilepath(String filepath1) {
32 this.filepath = new SimpleStringProperty(filepath1);
33 }
34 }
数据库连接类如下:
Connect.java
package All;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
public class Connect {
// 连接数据库url
static String url;
// 创建Properties对象
static Properties info = new Properties();
// 驱动程序加载
static {
// 获得属性文件输入流
InputStream input = Connect.class.getResourceAsStream("config.properties");
try {
// 加载属性文件内容到Properties对象
info.load(input);
// 从属性文件中取出url
url = info.getProperty("url");
// 从属性文件中取出driver
String driverClassName = info.getProperty("driver");
Class.forName(driverClassName);
System.out.println("驱动程序加载成功...");
} catch (ClassNotFoundException e) {
System.out.println("驱动程序加载失败...");
} catch (IOException e) {
System.out.println("加载属性文件失败...");
}
}
// 获得数据库连接
public static Connection getConnection() {
// 创建数据库连接
Connection conn = null;
try {
conn = DriverManager.getConnection(url, info);
System.out.println("数据库连接成功!");
} catch (SQLException e) {
System.out.println("数据库连接失败!");
System.out.println(url);
System.out.println(info);
}
return conn;
}
}
最后主类如下:
Main.java
package All;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class Main extends Application{
private Stage primaryStage;
@Override
public void start(Stage primaryStage){
this.primaryStage = primaryStage;
try {
FirstPage();
} catch (IOException e) {
e.printStackTrace();
}
}
public void FirstPage() throws IOException {
FXMLLoader loder = new FXMLLoader(Main.class.getResource("FirstPage.fxml"));
AnchorPane root = loder.load();
Scene scene = new Scene(root);
FirstPageController controller = loder.getController();
controller.setMain(this);
primaryStage.setTitle("读者文摘");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
最后实现的效果如下:
至此,所有功能实现。
总结:
用到了Jsoup的知识爬取网页源代码,
用到了正则表达式进行数据匹配
用到了JDBC进行数据库连接并进行数据查找
用到了javafx内的TableView绑定数据操作
用到了流操作进行数据写入文件
重温了File类文件及文件夹的创建
重温了Alter弹窗