javafx实现读者文摘上的文章预览及下载

功能设计:

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) {
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) {
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>

界面设计完成后是这个样的:

javafx实现读者文摘上的文章预览及下载_第1张图片

生成控制类后插入数据并实现各个方法:

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 FileTest;//表格
 50     @FXML
 51     private TableColumn FileName;//第一列存文章名
 52     @FXML
 53     private TableColumn FilePath;//第二列存文章链接
 54     @FXML
 55 
 56     private Text Preview;//预览标题
 57     
 58     private ObservableList 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);
    }
}

最后实现的效果如下:

javafx实现读者文摘上的文章预览及下载_第2张图片

 至此,所有功能实现。

总结:

用到了Jsoup的知识爬取网页源代码,

用到了正则表达式进行数据匹配

用到了JDBC进行数据库连接并进行数据查找

用到了javafx内的TableView绑定数据操作

用到了流操作进行数据写入文件

重温了File类文件及文件夹的创建

重温了Alter弹窗

你可能感兴趣的:(javafx实现读者文摘上的文章预览及下载)