Java 語言與網絡 課程設計
題目名稱:用 JavaSocket 編程開發聊天室
用 JavaURL 編程爬取并分析網頁敏感詞 姓
名:
學
號:
專
業:
信息安全
班
級:
1602 班
指導教師:
張偉
編寫日期:
2018 年 3 月 25 日星期日
目錄
第一章 開發工具及環境說明…………………………………2 第二章 網絡聊天程序業務分析………………………………3 第三章 網絡聊天程序系統設計………………………………4 一、 系統功能定義…………………………………………4 二、 關鍵問題設計…………………………………………4 1.系統模塊設計………………………………………4 2.系統類設計…………………………………………4 第四章 聊天程序源代碼清單…………………………………11 第五章 聊天程序運行結果與測試分析………………………23 第六章 用 JavaURL 編程爬取并分析網頁敏感詞業務分析…29 第七章 用 JavaURL 編程爬取并分析網頁敏感詞系統設計…30 一、 系統功能定義…………………………………………30 二、 關鍵問題設計…………………………………………30 1.系統模塊設計………………………………………30 2.系統類設計…………………………………………30 第八章 用 JavaURL 編程爬取并分析網頁敏感詞源代碼清單…38 第九章 用 JavaURL 編程爬取并分析網頁敏感詞運行結果與測試分析……………………………………………………………58 第十章 結論與心得……………………………………………62
第一章 開發工具及環境說明 開發工具:Intellij IDEA
環境說明:Windows 10
第二章 網絡聊天程序業務分析 一、實踐目的或任務:
通過指導學生上機實踐,對 JavaSocket 編程、Java 多線程、Java 圖形用戶界面進行掌握。
二、實踐基本要求:
1.了解實驗目的及實驗原理; 2.編寫程序,并附上程序代碼和結果圖; 3.總結在編程過程中遇到的問題、解決辦法和收獲。
三、實踐的內容或要求:
1. 用 Java 圖形用戶界面編寫聊天室服務器端和客戶端, 支持多個客戶端連接到一個服務器。每個客戶端能夠輸入賬號。
2. 可以實現群聊(聊天記錄顯示在所有客戶端界面)。
3. 完成好友列表在各個客戶端上顯示。
4. 可以實現私人聊天,用戶可以選擇某個其他用戶,單獨發送信息。
5. 服務器能夠群發系統消息,能夠強行讓某些用戶下線。
6. 客戶端的上線下線要求能夠在其他客戶端上面實時刷新。
第三章 網絡聊天程序系統設計 一、系統功能定義 本系統要實現的功能如下:
1. 客戶端
?。?)登錄 客戶端系統運行,出現登錄界面。該界面出現在屏幕中間。用戶輸入其用戶名,然后建立與服務器的連接,輸入成功后顯示聊天界面。已經登陸了聊天室的用戶的聊天記錄上面實時刷新上線下線消息,并且同時更新客戶端和服務器端的用戶列表。
?。?)群聊 客戶端首先發送消息到服務器端,服務器端轉發給全體客戶端,所有客戶端接收消息并顯示在聊天記錄中。將消息寫入輸入框,點擊 “發送消息”即可在群內發言。聊天記錄顯示在所有客戶端界面左邊,好友列表在各個客戶端右邊顯示。
?。?)私聊 客戶端首先發送消息到服務器端,服務器端轉發給全體客戶端,所有客戶端接收消息,但是只有特定客戶端處理此消息。A 點擊右側好友列表的 B,然后點擊“私發消息”,即彈出私聊界面,將消息寫入輸入框,點擊 “發消息”即可與另一方私聊。B 的聊天界面顯示“系統提示:A 私聊了你”,然后點擊右側列表對應好友的用戶名,并且點擊“發消息”即可查看對方的聊天記錄并與對方私聊。
2. 服務器端
?。?)
群發系統消息 服務器將消息寫入輸入框,點擊 “群發消息”即可將消息發送給全體客戶端,在群內顯示系統消息。
?。?)
踢用戶下線 點擊用戶列表中對應用戶的用戶名,然后點擊“踢出聊天室”即可關閉對應客戶端的套接字,讓其在顯示“您已被系統請出聊天室!”后關閉會話窗口,強制下線。
二、關鍵問題設計 1.
系統模塊設計
1.1 聊天系統工作原理圖
1.2
系統功能模塊圖:
1.3 活動圖:
1)用戶登陸活動圖 首先填寫登陸信息,提交以后登陸成功,更新在線狀態。通知所有好友自己已經上線。服務器再檢查是否有他的離線消息,如果有則立即發送給用戶。
2)發送消息活動圖 短消息發送以后,服務器端對應的監聽線程會接收到一個字符串。其中包含特殊含義的字符,對應特定的聊天功能。
(1)客戶端 上線:LOGIN#nickname 下線:OFFLINE#nickname#msg 群發消息:MSG#nickname#msg 私發消息:第一次:FSMSG#send nickname#receive nicknmame#msg 第一次之后:SMSG#send nickname#receive nicknmame#msg (2)服務器端 群發消息:ALL#msg
踢人:OFFLINE#nickname 好友列表:USERS#nickname
2.
系統類設計
2.1 sever 類的設計
1.ChatThread:和客戶進行消息通信的類。
Socket 又稱為套接字,是兩個程序進行雙向數據傳輸的網絡通信的端點,一般由 IP + PORT 構成。通常采用的端口是大于 1023 的小于 65535 的數,1023之前一般被占用,如 80 被 HTTP 服務其占用,21 被 Telnet 占用,23 被 FTP 服務器占用等等。Socket 是一種底層的通信機制,通過 Socket 的數據是原始的字節流,必須經過兩端的程序按照協議進行處理和解釋。其分為兩類,面向連接的TCP/IP 通信,和非連接的 UDP 數據報通信,此次實驗聊天室是采用 TCP/IP 面向連接編寫的。
在服務器端和客戶端,分別使用 ServerSocket 和 Socket,基本流程如下:
?。?)創建套接字 (2)打開連接的 IO (3)按照協議讀寫 (4)關閉資源
服務器用來聽,用來等待客戶端程序來尋找。如果客戶端的程序來尋找 9999端口,那么這個程序就會響應。
服務器通過一個循環一直監聽 9999 端口,當有客戶端連接到端口時,并把連接的通信添加到服務器管理集合。
大致步驟:
?。?)創建一個 socket 監聽端口 9999。服務器從其連接套接字讀取一行字符 (2)通過循環實現一直監聽 9999 端口 (3)當有客戶端連接到端口時,把連接的客戶端傳到新的線程將連接的通信添加到服務器管理集合 (4)用 t userList 定義一個集合,用來存放不同的客戶端,可以往客戶端里添加個體,并能實現刪除 t userList 中斷開連接的線程 (5)循環讀取數據,當輸入流的數據不為空時,把數據發送到每一個客戶端 (6)沒有數據后,關閉輸入流 重寫線程,將 br 作為“聽筒”讀取全部客戶端發送的消息,ps 作為“話筒”向在線的全部客戶端發送消息,實現客戶端與服務器端的交互。
2.run:接受客戶連接請求的類 通過循環監聽 9999 端口,當有新用戶連接時,把連接的客戶端傳到新的線程,將連接的通信添加到服務器管理集合,并在聊天室內發送新用戶上線的消息。
3.
sendMessage:將消息轉發給所有客戶端
4.handleAll:群發系統消息
5.handleExpel:強行讓某些用戶下線并發布下線消息
2.2 client 類的設計
1. handleSend():實現群聊
2. handleSS():實現私聊
3. handleSec():私聊界面
4. run:接受服務器消息的類
5.好友列表在各個客戶端上顯示,客戶端的上線下線要求能夠在其他客戶端上面實時刷新 DefaultListModel<String> dl = new DefaultListModel<String>(); private JList<String> userList = new JList<String>( dl); JScrollPane listPane = new JScrollPane( userList); listPane.setPreferredSize(dim2); west.add( listPane,BorderLayout. CENTER ); //上線:
String msg = br.readLine(); String[] strs = msg.split( "#"); //判斷是否為服務器發來的登陸信息 if(strs[0].equals( "LOGIN")){
if(!strs[1].equals( nickName)){
jta.append(strs[1] + " " 上線啦!\ \ n");
dl.addElement(strs[1]);
userList.repaint();
} //下線:
else if(strs[0].equals( "OFFLINE")){
dl.removeElement(strs[1]);
userList.repaint(); }
第四章
聊天程序源代碼清單 1.sever package chat;
import javax.swing.*; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList;
class server extends JFrame implements Runnable, ListSelectionListener, ActionListener {
private Socket s = null;
private ServerSocket ss = null;
private ArrayList<ChatThread> users = new ArrayList<ChatThread>();
DefaultListModel<String> dl = new DefaultListModel<String>();
private JList<String> userList = new JList<String>(dl);
private JPanel jpl = new JPanel();
private JButton jbt = new JButton("踢出聊天室");
private JButton jbt1 = new JButton("群發消息");
//群發消息輸入欄
private JTextField jtf = new JTextField();
public server() throws Exception{
this.setTitle("服務器端");
this.add(userList, "North");//放在北面
this.add(jpl, "South");
//僅將群發消息輸入欄設為一欄
jtf.setColumns(1);
jtf.setBackground(Color.pink);
jpl.setLayout(new BorderLayout());
jpl.add(jtf, BorderLayout.NORTH);
jpl.add(jbt,BorderLayout.EAST);//踢出聊天室
jpl.add(jbt1, BorderLayout.WEST);//群發消息
//實現群發
jbt1.addActionListener(this);
//實現踢人
jbt.addActionListener(this);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setLocation(400,100);
this.setSize(300, 400);
this.setVisible(true);
this.setAlwaysOnTop(true);
ss = new ServerSocket(9999);
new Thread(this).start();
}
@Override
public void run() {
while(true){
try{
s = ss.accept();
ChatThread ct = new ChatThread(s);
users.add(ct);
//發送 Jlist 里的用戶登陸信息
ListModel<String> model = userList.getModel();
for(int i = 0; i < model.getSize(); i++){
ct.ps.println("USERS#" + model.getElementAt(i));
}
ct.start();
}catch (Exception ex){
ex.printStackTrace();
javax.swing.JOptionPane.showMessageDialog(this,"服務器異常!");
System.exit(0);
}
}
}
//List 選擇事件監聽
@Override
public void valueChanged(ListSelectionEvent e) {
}
//群發消息按鈕點擊事件監聽
@Override
public void actionPerformed(ActionEvent e) {
String label = e.getActionCommand();
if(label.equals("群發消息")){
handleAll();
}else if(label.equals("踢出聊天室")){
try {
handleExpel();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
public void handleAll(){
if(!jtf.getText().equals("")){
sendMessage("ALL#" + jtf.getText());
//發送完后,是輸入框中內容為空
jtf.setText("");
}
}//群發消息
public void handleExpel() throws IOException {
users.get(userList.getAnchorSelectionIndex()).s.close();//關閉套接字
sendMessage("OFFLINE#" + userList.getSelectedValuesList().get(0));
dl.removeElement(userList.getSelectedValuesList().get(0));
userList.repaint();
}//踢人
public class ChatThread extends Thread{
Socket s = null;
private BufferedReader br = null;
private PrintStream ps = null;
public boolean canRun = true;
String nickName = null;
public ChatThread(Socket s) throws Exception{
this.s = s;
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
ps = new PrintStream(s.getOutputStream());
}
public void run(){
while(canRun){
try{
String msg = br.readLine();
String[] strs = msg.split("#");
if(strs[0].equals("LOGIN")){//收到來自客戶端的上線消息
nickName = strs[1];
dl.addElement(nickName);
sendMessage(msg);
}else if(strs[0].equals("MSG") || strs[0].equals("SMSG") || strs[0].equals("FSMSG")){
sendMessage(msg);
}else if(strs[0].equals("OFFLINE")){//收到來自客戶端的下線消息
sendMessage(msg);
//System.out.println(msg);
dl.removeElement(strs[1]);
// 更新 List 列表
userList.repaint();
}
}catch (Exception ex){}
}
}
}
public void sendMessage(String msg){//發送給所有用戶
for(ChatThread ct : users){
ct.ps.println(msg);
}
}
public static void main(String[] args) throws Exception{
new server();
}
}
2.client package chat;
import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket;
public class client extends JFrame implements Runnable,ActionListener {
//north
private JMenuBar bar = new JMenuBar();
private JMenu menu = new JMenu("關于");
private JMenuItem about = new JMenuItem("關于本軟件");
private JMenuItem exit = new JMenuItem("退出");
JPanel north = new JPanel();
//west
JPanel west = new JPanel();
DefaultListModel<String> dl = new DefaultListModel<String>();
private JList<String> userList = new JList<String>(dl);
JScrollPane listPane = new JScrollPane(userList);
//center
JPanel center = new JPanel();
JTextArea jta = new JTextArea(10,20);
JScrollPane js = new JScrollPane(jta);
JPanel operPane = new JPanel();
JLabel input = new JLabel("請輸入:");
JTextField jtf = new JTextField(24);
JButton jButton = new JButton("發消息");
private JButton jbt = new JButton("發送消息");
private JButton jbt1 = new JButton("私發消息");
private BufferedReader br = null;
private PrintStream ps = null;
private String nickName = null;
JTextArea jTextArea = new JTextArea();
JTextField jTextField = new JTextField();
String suser = new String();
boolean flag = false;
public cllient() throws Exception{
//north
bar.add(menu);
menu.add(about);
menu.add(exit);
about.addActionListener(this);
exit.addActionListener(this);
BorderLayout bl = new BorderLayout();
north.setLayout(bl);
north.add(bar,BorderLayout.NORTH);
add(north,BorderLayout.NORTH);
//west
Dimension dim = new Dimension(100,150);
west.setPreferredSize(dim);
Dimension dim2 = new Dimension(100,300);
listPane.setPreferredSize(dim2);
BorderLayout bl2 = new BorderLayout();
west.setLayout(bl2);
west.add(listPane,BorderLayout.CENTER);//顯示好友列表哈哈
add(west,BorderLayout.EAST);
userList.setFont(new Font("隸書",Font.BOLD,18));
//center
jta.setEditable(false);
jtf.setBackground(Color.pink);
BorderLayout bl3 = new BorderLayout();
center.setLayout(bl3);
FlowLayout fl = new FlowLayout(FlowLayout.LEFT);
operPane.setLayout(fl);
operPane.add(input);
operPane.add(jtf);
operPane.add(jbt, BorderLayout.WEST);
operPane.add(jbt1, BorderLayout.EAST);
center.add(js,BorderLayout.CENTER);
center.add(operPane,BorderLayout.SOUTH);
add(center,BorderLayout.CENTER);
js.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
//鼠標事件,點擊
jbt.addActionListener(this);
jbt1.addActionListener(this);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
//this.setAlwaysOnTop(true);
nickName = JOptionPane.showInputDialog("用戶名:");
this.setTitle(nickName + "的聊天室");
this.setSize(600,400);
this.setVisible(true);
Socket s = new Socket("127.0.0.1", 9999);
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
ps = new PrintStream(s.getOutputStream());
new Thread(this).start();
ps.println("LOGIN#" + nickName);
//鍵盤事件,實現當輸完要發送的內容后,直接按回車鍵,實現發送
//監聽鍵盤相應的控件必須是獲得焦點(focus)的情況下才能起作用
jtf.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER) {
ps.println("MSG#" + nickName + "#" +
jtf.getText());
//發送完后,是輸入框中內容為空
jtf.setText("");
}
}
});
jtf.setFocusable(true);
//監聽系統關閉事件,退出時給服務器端發出指定消息
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
ps.println("OFFLINE#" + nickName);
}
});
}
public void run(){
while (true){
try{
String msg = br.readLine();
String[] strs = msg.split("#");
//判斷是否為服務器發來的登陸信息
if(strs[0].equals("LOGIN")){
if(!strs[1].equals(nickName)){
jta.append(strs[1] + "上線啦!\n");
dl.addElement(strs[1]);
userList.repaint();
}
}else if(strs[0].equals("MSG")){
if(!strs[1].equals(nickName)){
jta.append(strs[1] + "說:" + strs[2] + "\n");
}else{
jta.append("我說:" + strs[2] + "\n");
}
}else if(strs[0].equals("USERS")){
dl.addElement(strs[1]);
userList.repaint();
} else if(strs[0].equals("ALL")){
jta.append("系統消息:" + strs[1] + "\n");
}else if(strs[0].equals("OFFLINE")){
jta.append(strs[1] + "下線啦!\n");
dl.removeElement(strs[1]);
userList.repaint();
}else if((strs[2].equals(nickName) || strs[1].equals(nickName)) && strs[0].equals("SMSG")){
if(!strs[1].equals(nickName)){
jTextArea.append(strs[1] + "說:" + strs[3] + "\n");
}else{
jTextArea.append("我說:" + strs[3] + "\n");
}
}else if((strs[2].equals(nickName) || strs[1].equals(nickName))&& strs[0].equals("FSMSG")){//只有發信人和私信人能看(第一次)
if(strs[2].equals(nickName)){//如果被私信人是自己則顯示系統消息
jTextArea.append(strs[1] + "說:" + strs[3] + "\n");
jta.append("系統提示:" + strs[1] + "私信了你" + "\n");
}else{//若自己為發信人
jTextArea.append( "我說:" + strs[3] + "\n");
}
}
}catch (Exception ex){
ex.printStackTrace();
javax.swing.JOptionPane.showMessageDialog(this, "您已被系統請出聊天室!");
ps.println("OFFLINE#" + nickName);
System.exit(0);
}
}
}
@Override
public void actionPerformed(ActionEvent e) {
String label = e.getActionCommand();
if(label.equals("發送消息")){//群發
handleSend();
}else if(label.equals("私發消息") && !userList.isSelectionEmpty()){//未點擊用戶不執行
suser = userList.getSelectedValuesList().get(0);
handleSec();
}else if(label.equals("發消息")){
handleSS();
}else if(label.equals("關于本軟件")){
JOptionPane.showMessageDialog(this, "世界上最可愛的人制作");
}else if(label.equals("退出")){
JOptionPane.showMessageDialog(this, "您已成功退出!");
ps.println("OFFLINE#" + nickName);
System.exit(0);
} else{
System.out.println("不識別的事件");
}
}
public void handleSS(){
if(flag){
ps.println("SMSG#" + nickName + "#" + suser + "#" + jTextField.getText());
jTextField.setText("");
}else{//首次私信格式為"FSMSG#
發信人
# 收信人 # 內容
ps.println("FSMSG#" + nickName + "#" + suser + "#" + jTextField.getText());
jTextField.setText("");
flag = true;
}
}//私聊中
public void handleSend(){
//發送信息時標識一下來源
ps.println("MSG#" + nickName + "#" +
jtf.getText());
//發送完后,是輸入框中內容為空
jtf.setText("");
}//群聊
public void handleSec(){
JFrame jFrame = new JFrame();
jFrame.add(jButton, BorderLayout.SOUTH);
jFrame.add(jTextField, BorderLayout.NORTH);
jFrame.add(jTextArea,BorderLayout.CENTER);
jButton.addActionListener(this);
jTextArea.setFont(new Font("宋體", Font.PLAIN,15));
jTextField.setBackground(Color.pink);
jFrame.setSize(400,300);
jFrame.setLocation(400,150);
jFrame.setTitle("與" + userList.getSelectedValuesList().get(0) + "私聊中");
jFrame.setVisible(true);
jFrame.addWindowListener(new WindowListener() {
@Override
public void windowOpened(WindowEvent e) {
}
public void windowClosing(WindowEvent e) {
flag = false;
//JOptionPane.showMessageDialog(this, "您已成功退出!");
}
@Override
public void windowClosed(WindowEvent e) {
}
@Override
public void windowIconified(WindowEvent e) {
}
@Override
public void windowDeiconified(WindowEvent e) {
}
@Override
public void windowActivated(WindowEvent e) {
}
@Override
public void windowDeactivated(WindowEvent e) {
}
});
}//私聊窗口
public static void main(String[] args)throws Exception{
new client();
} }
第五章
聊天程序運行結果與測試分析 1. 服務器界面 首先運行服務器界面,界面如圖。
服務器運行后,客戶可以登錄聊天室。服務器顯示在線用戶列表,客戶注冊時,能夠將用戶名存在服務器端。服務器將消息寫入輸入框,點擊 “群發消息”即可將消息發送給全體客戶端,在群內顯示系統消息。點擊用戶列表中對應用戶的用戶名,然后點擊“踢出聊天室”即可關閉對應客戶端的套接字,讓其在顯示“您已被系統請出聊天室!”后關閉會話窗口,強制下線。
2. 登錄界面 客戶端系統運行,出現登錄界面,如圖。
該界面出現在屏幕中間,在這個界面中:
輸入用戶名,并點擊“確定”按鈕,能夠連接到服務器,能夠到達聊天界面。
3.聊天界面 客戶登錄成功之后,出現聊天界面,如圖。
在這個界面中:
a) 標題欄顯示當前登陸的賬號。
b) 左邊顯示聊天記錄,右邊顯示在線用戶名單。
c) 客戶可以進行群聊,也可以選擇一個在線賬號,與其進行私聊。
(1)實現群聊
?。?)刷新好友列表
(3)私聊
(4)服務器群發消息
?。?)實現踢人
第六章 用 JavaURL 編程爬取并分析網頁敏感詞業務分析 一、實踐目的或任務:
通過指導學生上機實踐,對 JavaURL 編程、Java 圖形界面進行掌握。
二、實踐基本要求:
1.了解實驗目的及實驗原理; 2.編寫程序,并附上程序代碼和結果圖; 3.總結在編程過程中遇到的問題、解決辦法和收獲。
三、實踐的內容或要求:
1.編寫界面,輸入一個網址,能夠爬取該網址上所有的 HTML 源代碼。
2.對網址中的文本進行提取。
3.建立敏感詞庫,用文本文件保存。
4.將該網址所對應的文本中的敏感詞提取并高亮顯示。
5.編寫文本文件,可以存入多個網址;程序可爬取這些網址中的文本內容,將敏感詞記錄存入另一個文件,格式自定。
6.編寫一個主界面,整合上述功能。
第七章 用 JavaURL 編程爬取并分析網頁敏感詞系統設計 一、系統功能定義 本系統要實現的功能如下:
1. 主界面
(1)網頁分析功能 運行 GUI,在輸入框輸入一個網址,選擇“爬取網頁”能夠爬取該網址上所有的 HTML 源代碼并在控制臺輸出,
?。?)保存文本功能 將爬取的文本和敏感詞記錄保存在爬取文本.txt 中,同時將敏感詞記錄存入敏感詞記錄.txt。
?。?)顯示文本功能 彈出的顯示文檔頁面可以將該網址所對應的文本中的敏感詞高亮顯示。
?。?)保存網址功能 選擇“保存網址”能夠將所輸入網址保存在文本文件 weblist.txt 中,此文件可以存入多個網址。
2. 批量爬取界面
?。?)批量爬取功能 運行 WebGroup,點擊 “批量爬取”能通過循環運行 webPageResource 爬取weblist.txt 中網址中的內容。
?。?)保存文本功能 將 Weblist.txt 中網址中的文本內容并存入批量爬取.txt 中,同時將敏感詞記錄存入敏感詞記錄.txt。
(3)顯示文本功能 彈出的顯示文檔頁面可以將該網址所對應的文本中的內容顯示。
二、 關鍵問題設計 1. 系統模塊設計
1.1 網絡爬蟲工作原理圖 (1)爬取網頁 http 源代碼及文本 通常在寫爬蟲程序時,httpClient 結合 Jsoup 共同使用即可實現完美的爬蟲系統。
httpClient 負責模擬瀏覽器發送請求,Jsoup 負責解析 httpClient 請求返回的 HTML 頁面,解析獲取需要的數據。HttpClient 是 Apache Jakarta Common 下的子項目,可以用來提供高效的、最新的、功能豐富的支持 HTTP 協議的客戶端編程工具包,并且它支持 HTTP 協議最新的版本和建議。
jsoup 是一款 Java 的 HTML 解析器,可直接解析某個 URL 地址、HTML 文本內容。它提供了一套非常省力的 API,可通過 DOM,CSS 以及類似于 jQuery 的操作方法來取出和操作數據。
獲取此鏈接的 document 對象,并使用 toString 方法輸出:
(2)爬取網頁文本 jsoup elements 對象支持類似于 CSS (或 jquery)的選擇器語法,來實現非常強大和靈活的查找功能。.
這個 select 方法在 Document, Element,或 Elements 對象中都可以使用。且是上下文相關的,因此可實現指定元素的過濾,或者鏈式選擇訪問。Select方法將返回一個 Elements 集合,并提供一組方法來抽取和處理結果。
String text = document.select( "p").text(); // 取得文本
?。?)敏感詞匹配 在實現文字過濾的算法中,DFA 是唯一比較好的實現算法。DFA 即Deterministic Finite Automaton,也就是確定有窮自動機,它是是通過 event和當前的 state 得到下一個 state,即 event+state=nextstate。
以 Java 中的 HashMap 來實現 DFA 算法。具體過程如下(日本人,日本鬼子為例):
1、在 hashMap 中查詢“日”看其是否在 hashMap 中存在,如果不存在,則證明已“日”開頭的敏感詞還不存在,則我們直接構建這樣的一棵樹。跳至 3。
2、如果在 hashMap 中查找到了,表明存在以“日”開頭的敏感詞,設置hashMap = hashMap.get("日"),跳至 1,依次匹配“本”、“人”。
3、判斷該字是否為該詞中的最后一個字。若是表示敏感詞結束,設置標志位 isEnd = 1,否則設置標志位 isEnd = 0;
(4)敏感詞高亮 敏感詞高亮部分我選擇使用 java 中的 public class DefaultHighlighter中的函數 addHighlight (int
p0, int
p1, Highlighter.HighlightPainter p) 可以實現在視圖中添加一個高亮。
1.2
活動圖:
2. 系統類設計
2.1 GUI 類的設計
?。ㄊ褂?GUI form)
1.
writeFile:將網址保存在 weblist.txt 中
2.GUI:爬取網頁,并保存爬取文本在爬取文本.txt 中,打開“打開文件”界面。
2.2 WebGroup 類的設計
1. readInStrings:讀取 weblist.txt 中的網址
2. actionPerformed:批量爬取
2.3 webPageResource 類的設計
1.
getPageSource:爬取網頁 http 源代碼
2.
writeFile:保存文本文件
3. getItemContent:獲取文本和敏感詞并調用 writeFile 保存文本文件
2.4 SensitiveWordInit 類的設計
1. SensitiveWordInit:初始化敏感詞庫,將敏感詞加入到 HashMap 中,構建DFA 算法模型
2.initKeyWord():初始化敏感詞庫
3.
readSensitiveWordFile:讀取敏感詞庫中的內容,將內容添加到 set 集合中
4. addSensitiveWordToHashMap:將敏感詞加入到 HashMap 中,構建 DFA 算法模型
2.5 SensitivewordFilter 類的設計
1. SensitivewordFilter():構造函數,初始化敏感詞庫
2. getSensitiveWord:獲取文字中的敏感詞
3. CheckSensitiveWord:查文字中是否包含敏感字符,如果存在,則返回敏感詞字符的長度,不存在返回 0
2.6 ShowFileContent 類的設計
1. MyFrame:顯示文件內容
2.
MyFileFilter:選擇顯示文件的類型
3.敏感詞高亮 private JTextArea txtInfo = new JTextArea(50, 50);
switch ( fileDlg.showOpenDialog( this)) {
case JFileChooser. APPROVE_OPTION :
txtInfo.setText( null );
String filePath = fileDlg.getSelectedFile().getAbsolutePath();
setTitle( fileDlg.getSelectedFile().getName() );
showFileContent( filePath );
Highlighter highLighter = txtInfo.getHighlighter();
String text = txtInfo.getText();
File file= new File( "D:\ \\ \ Web Spider\ \\ \ 敏感詞記錄 .txt");
FileReader fr= null;
try {
fr = new FileReader(file);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
BufferedReader br= new BufferedReader(fr);
DefaultHighlighter.DefaultHighlightPainter p = new DefaultHighlighter.DefaultHighlightPainter(Color. RED );
String keyWord=" "";
try {
while((keyWord=br.readLine())!= null){
int pos = 0;
while ((pos = text.indexOf(keyWord, pos)) >= 0)
{
try
{
highLighter.addHighlight(pos, pos + keyWord.length(), p);
pos += keyWord.length();
}
catch (BadLocationException ex)
{
ex.printStackTrace();
}
}
}
} catch (IOException e1) {
e1.printStackTrace();
}
try {
fr.close();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
br.close();
} catch (IOException e1) {
e1.printStackTrace();
} }
第八章 用 JavaURL 編程爬取并分析網頁敏感詞源代碼清單 1.GUI package spider;
import org.jsoup.nodes.Document;
import javax.swing.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.*;
public class GUI {
public String url;
public SensitivewordFilter filter = new SensitivewordFilter();
//public webPageResource wpr=new webPageResource();
public GUI() {
SpiderButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e){
String s1=jft.getText();
//writeOutStrings1("webtouse",s1);
//webPageResource wpr=new webPageResource();
webPageResource wpr=new webPageResource();
//Set<String> set=filter.getSensitiveWord(string,1);
//public webPageResource wpr=new webPageResource();
Document document=wpr.getPageSource(s1);
String title = document.title();
String text = document.select("p").text(); // 取得字符串中的文本
String htmls= wpr.getPageSource(s1).toString();
System.out.println(htmls);
// wpr.saveArticle(title,text);
wpr.writeFile("D:\\Web Spider\\爬取文本.txt",title+"\n"+text+"\n");
//wpr.writeFile("D:\\Web Spider\\爬取文本.txt",wpr.ItContent);
wpr.getItemContent(s1);
ShowFileContent sfc=new ShowFileContent();
MyFrame myfram=new MyFrame("打開文件");
// System.out.println("語句中包含敏感詞的個數為:" + set );
}
});
SaveButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String s2=jft.getText();
writeFile("D:\\Web Spider\\weblist.txt",s2+"\n");
}
});
}
public static void main(String[] args) {
JFrame frame = new JFrame("GUI");
frame.setContentPane(new GUI().panel1);
frame.setLocation(400,300);
frame.setSize(350, 150);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame.pack();
frame.setVisible(true);
}
private JPanel panel1;
private JButton SaveButton;
private JButton SpiderButton;
private JTextField jft;
public void writeFile(String filename, String str){
try{
FileOutputStream fos = new FileOutputStream(filename, true);
byte[] b = str.getBytes();
fos.write(b);
fos.close();
}catch (FileNotFoundException e){
e.printStackTrace();
}catch (IOException ioe){
ioe.printStackTrace();
}
}
}
2. WebGroup package spider;
import org.jsoup.nodes.Document;
import javax.swing.*; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.Font; import java.awt.event.*; import java.io.*;
public class WebGroup extends JFrame implements ActionListener{
private static JTextArea txtInfo = new JTextArea(50, 50);
private JButton btnOpen = new JButton("
批量爬取
");
private JScrollPane sp = new JScrollPane(txtInfo);
private JPanel btnPane = new JPanel();
//static int lines;
//static String line = " ";
public WebGroup(){
super("網址列表");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
btnPane.add(btnOpen);
btnOpen.setActionCommand("spider");
btnOpen.addActionListener(this);
txtInfo.setFont(new Font("宋體", Font.PLAIN, 16));
txtInfo.setBackground(Color.WHITE);
txtInfo.setForeground(Color.black);
Container cp = getContentPane();
cp.add(btnPane, BorderLayout.SOUTH);
cp.add(sp, BorderLayout.CENTER);
this.setPreferredSize(new Dimension(500, 400));
this.setLocation(400, 200);
this.setVisible(true);
this.pack();
String path = "D:\\Web spider\\weblist.txt";
File file = new File(path);
readInStrings(file);
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand() == "spider") {
String path = "D:\\Web spider\\weblist.txt";
File file = new File(path);
readInStrings(file);
Reader reader = null;
try {
reader = new FileReader(file);
BufferedReader buf = new BufferedReader(reader);
int lines = 0;
String line = " ";
while ((line = buf.readLine()) != null) {
String s = line;
webPageResource wpr = new webPageResource();
...
推薦訪問: 爬蟲 編寫 聊天室上一篇:鄉鎮脫貧攻堅規劃
下一篇:開掘工廠廠長勞動模范申報材料
在偉大祖國73華誕之際,我參加了單位組織的“光影鑄魂”主題黨日活動,集中觀看了抗美援朝題材影片《長津湖》,再一次重溫這段悲壯歷史,再一次深刻感悟偉大抗美援朝精神。1950年10月,新中國剛剛成立一年,
根據省局黨組《關于舉辦習近平談治國理政(第四卷)讀書班的通知》要求,我中心通過專題學習、專題研討以及交流分享等形式,系統的對《習近平談治國理政》(第四卷)進行了深入的學習與交流,下面我就來談一談我個人
《習近平談治國理政》(第四卷)是在百年變局和世紀疫情相互疊加的大背景下,對以習近平同志為核心的黨中央治國理政重大戰略部署、重大理論創造、重大思想引領的系統呈現。它生動記錄了新一代黨中央領導集體統籌兩個
《真抓實干做好新發展階段“三農工作”》是《習近平談治國理政》第四卷中的文章,這是習近平總書記在2020年12月28日中央農村工作會議上的集體學習時的講話。文章指出,我常講,領導干部要胸懷黨和國家工作大
在《習近平談治國理政》第四卷中,習近平總書記強調,江山就是人民,人民就是江山,打江山、守江山,守的是人民的心。從嘉興南湖中駛出的小小紅船,到世界上最大的執政黨,在中國共產黨的字典里,“人民”一詞從來都
黨的十八大以來,習近平總書記以馬克思主義戰略家的博大胸襟和深謀遠慮,在治國理政和推動全球治理中牢固樹立戰略意識,在不同場合多次圍繞戰略策略的重要性,戰略和策略的關系,提高戰略思維、堅定戰略自信、強化戰
《習近平談治國理政》第四卷集中展示了以習近平同志為核心的黨中央在百年變局和世紀疫情相互疊加背景下,如何更好地堅持和發展中國特色社會主義而進行的生動實踐與理論探索;對于新時代堅持和發展什么樣的中國特色社
在黨組織的關懷下,我有幸參加了區委組織部組織的入黨積極分子培訓班。為期一周的學習,學習形式多樣,課程內容豐富,各位專家的講解細致精彩,對于我加深對黨的創新理論的認識、對黨的歷史的深入了解、對中共黨員的
《習近平談治國理政》第四卷《共建網上美好精神家園》一文中指出:網絡玩命是新形勢下社會文明的重要內容,是建設網絡強國的重要領域。截至2021年12月,我國網民規模達10 32億,較2020年12月增長4
剛剛召開的中國共產黨第十九屆中央委員會第七次全體會議上討論并通過了黨的十九屆中央委員會向中國共產黨第二十次全國代表大會的報告、黨的十九屆中央紀律檢查委員會向中國共產黨第二十次全國代表大會的工作報告和《