Java 語言與網(wǎng)絡(luò) 課程設(shè)計
題目名稱:用 JavaSocket 編程開發(fā)聊天室
用 JavaURL 編程爬取并分析網(wǎng)頁敏感詞 姓
名:
學(xué)
號:
專
業(yè):
信息安全
班
級:
1602 班
指導(dǎo)教師:
張偉
編寫日期:
2018 年 3 月 25 日星期日
目錄
第一章 開發(fā)工具及環(huán)境說明…………………………………2 第二章 網(wǎng)絡(luò)聊天程序業(yè)務(wù)分析………………………………3 第三章 網(wǎng)絡(luò)聊天程序系統(tǒng)設(shè)計………………………………4 一、 系統(tǒng)功能定義…………………………………………4 二、 關(guān)鍵問題設(shè)計…………………………………………4 1.系統(tǒng)模塊設(shè)計………………………………………4 2.系統(tǒng)類設(shè)計…………………………………………4 第四章 聊天程序源代碼清單…………………………………11 第五章 聊天程序運行結(jié)果與測試分析………………………23 第六章 用 JavaURL 編程爬取并分析網(wǎng)頁敏感詞業(yè)務(wù)分析…29 第七章 用 JavaURL 編程爬取并分析網(wǎng)頁敏感詞系統(tǒng)設(shè)計…30 一、 系統(tǒng)功能定義…………………………………………30 二、 關(guān)鍵問題設(shè)計…………………………………………30 1.系統(tǒng)模塊設(shè)計………………………………………30 2.系統(tǒng)類設(shè)計…………………………………………30 第八章 用 JavaURL 編程爬取并分析網(wǎng)頁敏感詞源代碼清單…38 第九章 用 JavaURL 編程爬取并分析網(wǎng)頁敏感詞運行結(jié)果與測試分析……………………………………………………………58 第十章 結(jié)論與心得……………………………………………62
第一章 開發(fā)工具及環(huán)境說明 開發(fā)工具:Intellij IDEA
環(huán)境說明:Windows 10
第二章 網(wǎng)絡(luò)聊天程序業(yè)務(wù)分析 一、實踐目的或任務(wù):
通過指導(dǎo)學(xué)生上機(jī)實踐,對 JavaSocket 編程、Java 多線程、Java 圖形用戶界面進(jìn)行掌握。
二、實踐基本要求:
1.了解實驗?zāi)康募皩嶒炘恚?2.編寫程序,并附上程序代碼和結(jié)果圖; 3.總結(jié)在編程過程中遇到的問題、解決辦法和收獲。
三、實踐的內(nèi)容或要求:
1. 用 Java 圖形用戶界面編寫聊天室服務(wù)器端和客戶端, 支持多個客戶端連接到一個服務(wù)器。每個客戶端能夠輸入賬號。
2. 可以實現(xiàn)群聊(聊天記錄顯示在所有客戶端界面)。
3. 完成好友列表在各個客戶端上顯示。
4. 可以實現(xiàn)私人聊天,用戶可以選擇某個其他用戶,單獨發(fā)送信息。
5. 服務(wù)器能夠群發(fā)系統(tǒng)消息,能夠強(qiáng)行讓某些用戶下線。
6. 客戶端的上線下線要求能夠在其他客戶端上面實時刷新。
第三章 網(wǎng)絡(luò)聊天程序系統(tǒng)設(shè)計 一、系統(tǒng)功能定義 本系統(tǒng)要實現(xiàn)的功能如下:
1. 客戶端
(1)登錄 客戶端系統(tǒng)運行,出現(xiàn)登錄界面。該界面出現(xiàn)在屏幕中間。用戶輸入其用戶名,然后建立與服務(wù)器的連接,輸入成功后顯示聊天界面。已經(jīng)登陸了聊天室的用戶的聊天記錄上面實時刷新上線下線消息,并且同時更新客戶端和服務(wù)器端的用戶列表。
(2)群聊 客戶端首先發(fā)送消息到服務(wù)器端,服務(wù)器端轉(zhuǎn)發(fā)給全體客戶端,所有客戶端接收消息并顯示在聊天記錄中。將消息寫入輸入框,點擊 “發(fā)送消息”即可在群內(nèi)發(fā)言。聊天記錄顯示在所有客戶端界面左邊,好友列表在各個客戶端右邊顯示。
(3)私聊 客戶端首先發(fā)送消息到服務(wù)器端,服務(wù)器端轉(zhuǎn)發(fā)給全體客戶端,所有客戶端接收消息,但是只有特定客戶端處理此消息。A 點擊右側(cè)好友列表的 B,然后點擊“私發(fā)消息”,即彈出私聊界面,將消息寫入輸入框,點擊 “發(fā)消息”即可與另一方私聊。B 的聊天界面顯示“系統(tǒng)提示:A 私聊了你”,然后點擊右側(cè)列表對應(yīng)好友的用戶名,并且點擊“發(fā)消息”即可查看對方的聊天記錄并與對方私聊。
2. 服務(wù)器端
(1)
群發(fā)系統(tǒng)消息 服務(wù)器將消息寫入輸入框,點擊 “群發(fā)消息”即可將消息發(fā)送給全體客戶端,在群內(nèi)顯示系統(tǒng)消息。
(2)
踢用戶下線 點擊用戶列表中對應(yīng)用戶的用戶名,然后點擊“踢出聊天室”即可關(guān)閉對應(yīng)客戶端的套接字,讓其在顯示“您已被系統(tǒng)請出聊天室!”后關(guān)閉會話窗口,強(qiáng)制下線。
二、關(guān)鍵問題設(shè)計 1.
系統(tǒng)模塊設(shè)計
1.1 聊天系統(tǒng)工作原理圖
1.2
系統(tǒng)功能模塊圖:
1.3 活動圖:
1)用戶登陸活動圖 首先填寫登陸信息,提交以后登陸成功,更新在線狀態(tài)。通知所有好友自己已經(jīng)上線。服務(wù)器再檢查是否有他的離線消息,如果有則立即發(fā)送給用戶。
2)發(fā)送消息活動圖 短消息發(fā)送以后,服務(wù)器端對應(yīng)的監(jiān)聽線程會接收到一個字符串。其中包含特殊含義的字符,對應(yīng)特定的聊天功能。
(1)客戶端 上線:LOGIN#nickname 下線:OFFLINE#nickname#msg 群發(fā)消息:MSG#nickname#msg 私發(fā)消息:第一次:FSMSG#send nickname#receive nicknmame#msg 第一次之后:SMSG#send nickname#receive nicknmame#msg (2)服務(wù)器端 群發(fā)消息:ALL#msg
踢人:OFFLINE#nickname 好友列表:USERS#nickname
2.
系統(tǒng)類設(shè)計
2.1 sever 類的設(shè)計
1.ChatThread:和客戶進(jìn)行消息通信的類。
Socket 又稱為套接字,是兩個程序進(jìn)行雙向數(shù)據(jù)傳輸?shù)木W(wǎng)絡(luò)通信的端點,一般由 IP + PORT 構(gòu)成。通常采用的端口是大于 1023 的小于 65535 的數(shù),1023之前一般被占用,如 80 被 HTTP 服務(wù)其占用,21 被 Telnet 占用,23 被 FTP 服務(wù)器占用等等。Socket 是一種底層的通信機(jī)制,通過 Socket 的數(shù)據(jù)是原始的字節(jié)流,必須經(jīng)過兩端的程序按照協(xié)議進(jìn)行處理和解釋。其分為兩類,面向連接的TCP/IP 通信,和非連接的 UDP 數(shù)據(jù)報通信,此次實驗聊天室是采用 TCP/IP 面向連接編寫的。
在服務(wù)器端和客戶端,分別使用 ServerSocket 和 Socket,基本流程如下:
(1)創(chuàng)建套接字 (2)打開連接的 IO (3)按照協(xié)議讀寫 (4)關(guān)閉資源
服務(wù)器用來聽,用來等待客戶端程序來尋找。如果客戶端的程序來尋找 9999端口,那么這個程序就會響應(yīng)。
服務(wù)器通過一個循環(huán)一直監(jiān)聽 9999 端口,當(dāng)有客戶端連接到端口時,并把連接的通信添加到服務(wù)器管理集合。
大致步驟:
(1)創(chuàng)建一個 socket 監(jiān)聽端口 9999。服務(wù)器從其連接套接字讀取一行字符 (2)通過循環(huán)實現(xiàn)一直監(jiān)聽 9999 端口 (3)當(dāng)有客戶端連接到端口時,把連接的客戶端傳到新的線程將連接的通信添加到服務(wù)器管理集合 (4)用 t userList 定義一個集合,用來存放不同的客戶端,可以往客戶端里添加個體,并能實現(xiàn)刪除 t userList 中斷開連接的線程 (5)循環(huán)讀取數(shù)據(jù),當(dāng)輸入流的數(shù)據(jù)不為空時,把數(shù)據(jù)發(fā)送到每一個客戶端 (6)沒有數(shù)據(jù)后,關(guān)閉輸入流 重寫線程,將 br 作為“聽筒”讀取全部客戶端發(fā)送的消息,ps 作為“話筒”向在線的全部客戶端發(fā)送消息,實現(xiàn)客戶端與服務(wù)器端的交互。
2.run:接受客戶連接請求的類 通過循環(huán)監(jiān)聽 9999 端口,當(dāng)有新用戶連接時,把連接的客戶端傳到新的線程,將連接的通信添加到服務(wù)器管理集合,并在聊天室內(nèi)發(fā)送新用戶上線的消息。
3.
sendMessage:將消息轉(zhuǎn)發(fā)給所有客戶端
4.handleAll:群發(fā)系統(tǒng)消息
5.handleExpel:強(qiáng)行讓某些用戶下線并發(fā)布下線消息
2.2 client 類的設(shè)計
1. handleSend():實現(xiàn)群聊
2. handleSS():實現(xiàn)私聊
3. handleSec():私聊界面
4. run:接受服務(wù)器消息的類
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( "#"); //判斷是否為服務(wù)器發(fā)來的登陸信息 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("群發(fā)消息");
//群發(fā)消息輸入欄
private JTextField jtf = new JTextField();
public server() throws Exception{
this.setTitle("服務(wù)器端");
this.add(userList, "North");//放在北面
this.add(jpl, "South");
//僅將群發(fā)消息輸入欄設(shè)為一欄
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);//群發(fā)消息
//實現(xiàn)群發(fā)
jbt1.addActionListener(this);
//實現(xiàn)踢人
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);
//發(fā)送 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,"服務(wù)器異常!");
System.exit(0);
}
}
}
//List 選擇事件監(jiān)聽
@Override
public void valueChanged(ListSelectionEvent e) {
}
//群發(fā)消息按鈕點擊事件監(jiān)聽
@Override
public void actionPerformed(ActionEvent e) {
String label = e.getActionCommand();
if(label.equals("群發(fā)消息")){
handleAll();
}else if(label.equals("踢出聊天室")){
try {
handleExpel();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
public void handleAll(){
if(!jtf.getText().equals("")){
sendMessage("ALL#" + jtf.getText());
//發(fā)送完后,是輸入框中內(nèi)容為空
jtf.setText("");
}
}//群發(fā)消息
public void handleExpel() throws IOException {
users.get(userList.getAnchorSelectionIndex()).s.close();//關(guān)閉套接字
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){//發(fā)送給所有用戶
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("關(guān)于");
private JMenuItem about = new JMenuItem("關(guān)于本軟件");
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("發(fā)消息");
private JButton jbt = new JButton("發(fā)送消息");
private JButton jbt1 = new JButton("私發(fā)消息");
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);
//鼠標(biāo)事件,點擊
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);
//鍵盤事件,實現(xiàn)當(dāng)輸完要發(fā)送的內(nèi)容后,直接按回車鍵,實現(xiàn)發(fā)送
//監(jiān)聽鍵盤相應(yīng)的控件必須是獲得焦點(focus)的情況下才能起作用
jtf.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER) {
ps.println("MSG#" + nickName + "#" +
jtf.getText());
//發(fā)送完后,是輸入框中內(nèi)容為空
jtf.setText("");
}
}
});
jtf.setFocusable(true);
//監(jiān)聽系統(tǒng)關(guān)閉事件,退出時給服務(wù)器端發(fā)出指定消息
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("#");
//判斷是否為服務(wù)器發(fā)來的登陸信息
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("系統(tǒng)消息:" + 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")){//只有發(fā)信人和私信人能看(第一次)
if(strs[2].equals(nickName)){//如果被私信人是自己則顯示系統(tǒng)消息
jTextArea.append(strs[1] + "說:" + strs[3] + "\n");
jta.append("系統(tǒng)提示:" + strs[1] + "私信了你" + "\n");
}else{//若自己為發(fā)信人
jTextArea.append( "我說:" + strs[3] + "\n");
}
}
}catch (Exception ex){
ex.printStackTrace();
javax.swing.JOptionPane.showMessageDialog(this, "您已被系統(tǒng)請出聊天室!");
ps.println("OFFLINE#" + nickName);
System.exit(0);
}
}
}
@Override
public void actionPerformed(ActionEvent e) {
String label = e.getActionCommand();
if(label.equals("發(fā)送消息")){//群發(fā)
handleSend();
}else if(label.equals("私發(fā)消息") && !userList.isSelectionEmpty()){//未點擊用戶不執(zhí)行
suser = userList.getSelectedValuesList().get(0);
handleSec();
}else if(label.equals("發(fā)消息")){
handleSS();
}else if(label.equals("關(guān)于本軟件")){
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#
發(fā)信人
# 收信人 # 內(nèi)容
ps.println("FSMSG#" + nickName + "#" + suser + "#" + jTextField.getText());
jTextField.setText("");
flag = true;
}
}//私聊中
public void handleSend(){
//發(fā)送信息時標(biāo)識一下來源
ps.println("MSG#" + nickName + "#" +
jtf.getText());
//發(fā)送完后,是輸入框中內(nèi)容為空
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();
} }
第五章
聊天程序運行結(jié)果與測試分析 1. 服務(wù)器界面 首先運行服務(wù)器界面,界面如圖。
服務(wù)器運行后,客戶可以登錄聊天室。服務(wù)器顯示在線用戶列表,客戶注冊時,能夠?qū)⒂脩裘嬖诜?wù)器端。服務(wù)器將消息寫入輸入框,點擊 “群發(fā)消息”即可將消息發(fā)送給全體客戶端,在群內(nèi)顯示系統(tǒng)消息。點擊用戶列表中對應(yīng)用戶的用戶名,然后點擊“踢出聊天室”即可關(guān)閉對應(yīng)客戶端的套接字,讓其在顯示“您已被系統(tǒng)請出聊天室!”后關(guān)閉會話窗口,強(qiáng)制下線。
2. 登錄界面 客戶端系統(tǒng)運行,出現(xiàn)登錄界面,如圖。
該界面出現(xiàn)在屏幕中間,在這個界面中:
輸入用戶名,并點擊“確定”按鈕,能夠連接到服務(wù)器,能夠到達(dá)聊天界面。
3.聊天界面 客戶登錄成功之后,出現(xiàn)聊天界面,如圖。
在這個界面中:
a) 標(biāo)題欄顯示當(dāng)前登陸的賬號。
b) 左邊顯示聊天記錄,右邊顯示在線用戶名單。
c) 客戶可以進(jìn)行群聊,也可以選擇一個在線賬號,與其進(jìn)行私聊。
(1)實現(xiàn)群聊
(2)刷新好友列表
(3)私聊
(4)服務(wù)器群發(fā)消息
(5)實現(xiàn)踢人
第六章 用 JavaURL 編程爬取并分析網(wǎng)頁敏感詞業(yè)務(wù)分析 一、實踐目的或任務(wù):
通過指導(dǎo)學(xué)生上機(jī)實踐,對 JavaURL 編程、Java 圖形界面進(jìn)行掌握。
二、實踐基本要求:
1.了解實驗?zāi)康募皩嶒炘恚?2.編寫程序,并附上程序代碼和結(jié)果圖; 3.總結(jié)在編程過程中遇到的問題、解決辦法和收獲。
三、實踐的內(nèi)容或要求:
1.編寫界面,輸入一個網(wǎng)址,能夠爬取該網(wǎng)址上所有的 HTML 源代碼。
2.對網(wǎng)址中的文本進(jìn)行提取。
3.建立敏感詞庫,用文本文件保存。
4.將該網(wǎng)址所對應(yīng)的文本中的敏感詞提取并高亮顯示。
5.編寫文本文件,可以存入多個網(wǎng)址;程序可爬取這些網(wǎng)址中的文本內(nèi)容,將敏感詞記錄存入另一個文件,格式自定。
6.編寫一個主界面,整合上述功能。
第七章 用 JavaURL 編程爬取并分析網(wǎng)頁敏感詞系統(tǒng)設(shè)計 一、系統(tǒng)功能定義 本系統(tǒng)要實現(xiàn)的功能如下:
1. 主界面
(1)網(wǎng)頁分析功能 運行 GUI,在輸入框輸入一個網(wǎng)址,選擇“爬取網(wǎng)頁”能夠爬取該網(wǎng)址上所有的 HTML 源代碼并在控制臺輸出,
(2)保存文本功能 將爬取的文本和敏感詞記錄保存在爬取文本.txt 中,同時將敏感詞記錄存入敏感詞記錄.txt。
(3)顯示文本功能 彈出的顯示文檔頁面可以將該網(wǎng)址所對應(yīng)的文本中的敏感詞高亮顯示。
(4)保存網(wǎng)址功能 選擇“保存網(wǎng)址”能夠?qū)⑺斎刖W(wǎng)址保存在文本文件 weblist.txt 中,此文件可以存入多個網(wǎng)址。
2. 批量爬取界面
(1)批量爬取功能 運行 WebGroup,點擊 “批量爬取”能通過循環(huán)運行 webPageResource 爬取weblist.txt 中網(wǎng)址中的內(nèi)容。
(2)保存文本功能 將 Weblist.txt 中網(wǎng)址中的文本內(nèi)容并存入批量爬取.txt 中,同時將敏感詞記錄存入敏感詞記錄.txt。
(3)顯示文本功能 彈出的顯示文檔頁面可以將該網(wǎng)址所對應(yīng)的文本中的內(nèi)容顯示。
二、 關(guān)鍵問題設(shè)計 1. 系統(tǒng)模塊設(shè)計
1.1 網(wǎng)絡(luò)爬蟲工作原理圖 (1)爬取網(wǎng)頁 http 源代碼及文本 通常在寫爬蟲程序時,httpClient 結(jié)合 Jsoup 共同使用即可實現(xiàn)完美的爬蟲系統(tǒng)。
httpClient 負(fù)責(zé)模擬瀏覽器發(fā)送請求,Jsoup 負(fù)責(zé)解析 httpClient 請求返回的 HTML 頁面,解析獲取需要的數(shù)據(jù)。HttpClient 是 Apache Jakarta Common 下的子項目,可以用來提供高效的、最新的、功能豐富的支持 HTTP 協(xié)議的客戶端編程工具包,并且它支持 HTTP 協(xié)議最新的版本和建議。
jsoup 是一款 Java 的 HTML 解析器,可直接解析某個 URL 地址、HTML 文本內(nèi)容。它提供了一套非常省力的 API,可通過 DOM,CSS 以及類似于 jQuery 的操作方法來取出和操作數(shù)據(jù)。
獲取此鏈接的 document 對象,并使用 toString 方法輸出:
(2)爬取網(wǎng)頁文本 jsoup elements 對象支持類似于 CSS (或 jquery)的選擇器語法,來實現(xiàn)非常強(qiáng)大和靈活的查找功能。.
這個 select 方法在 Document, Element,或 Elements 對象中都可以使用。且是上下文相關(guān)的,因此可實現(xiàn)指定元素的過濾,或者鏈?zhǔn)竭x擇訪問。Select方法將返回一個 Elements 集合,并提供一組方法來抽取和處理結(jié)果。
String text = document.select( "p").text(); // 取得文本
(3)敏感詞匹配 在實現(xiàn)文字過濾的算法中,DFA 是唯一比較好的實現(xiàn)算法。DFA 即Deterministic Finite Automaton,也就是確定有窮自動機(jī),它是是通過 event和當(dāng)前的 state 得到下一個 state,即 event+state=nextstate。
以 Java 中的 HashMap 來實現(xiàn) DFA 算法。具體過程如下(日本人,日本鬼子為例):
1、在 hashMap 中查詢“日”看其是否在 hashMap 中存在,如果不存在,則證明已“日”開頭的敏感詞還不存在,則我們直接構(gòu)建這樣的一棵樹。跳至 3。
2、如果在 hashMap 中查找到了,表明存在以“日”開頭的敏感詞,設(shè)置hashMap = hashMap.get("日"),跳至 1,依次匹配“本”、“人”。
3、判斷該字是否為該詞中的最后一個字。若是表示敏感詞結(jié)束,設(shè)置標(biāo)志位 isEnd = 1,否則設(shè)置標(biāo)志位 isEnd = 0;
(4)敏感詞高亮 敏感詞高亮部分我選擇使用 java 中的 public class DefaultHighlighter中的函數(shù) addHighlight (int
p0, int
p1, Highlighter.HighlightPainter p) 可以實現(xiàn)在視圖中添加一個高亮。
1.2
活動圖:
2. 系統(tǒng)類設(shè)計
2.1 GUI 類的設(shè)計
(使用 GUI form)
1.
writeFile:將網(wǎng)址保存在 weblist.txt 中
2.GUI:爬取網(wǎng)頁,并保存爬取文本在爬取文本.txt 中,打開“打開文件”界面。
2.2 WebGroup 類的設(shè)計
1. readInStrings:讀取 weblist.txt 中的網(wǎng)址
2. actionPerformed:批量爬取
2.3 webPageResource 類的設(shè)計
1.
getPageSource:爬取網(wǎng)頁 http 源代碼
2.
writeFile:保存文本文件
3. getItemContent:獲取文本和敏感詞并調(diào)用 writeFile 保存文本文件
2.4 SensitiveWordInit 類的設(shè)計
1. SensitiveWordInit:初始化敏感詞庫,將敏感詞加入到 HashMap 中,構(gòu)建DFA 算法模型
2.initKeyWord():初始化敏感詞庫
3.
readSensitiveWordFile:讀取敏感詞庫中的內(nèi)容,將內(nèi)容添加到 set 集合中
4. addSensitiveWordToHashMap:將敏感詞加入到 HashMap 中,構(gòu)建 DFA 算法模型
2.5 SensitivewordFilter 類的設(shè)計
1. SensitivewordFilter():構(gòu)造函數(shù),初始化敏感詞庫
2. getSensitiveWord:獲取文字中的敏感詞
3. CheckSensitiveWord:查文字中是否包含敏感字符,如果存在,則返回敏感詞字符的長度,不存在返回 0
2.6 ShowFileContent 類的設(shè)計
1. MyFrame:顯示文件內(nèi)容
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 編程爬取并分析網(wǎng)頁敏感詞源代碼清單 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("語句中包含敏感詞的個數(shù)為:" + 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("網(wǎng)址列表");
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月,新中國剛剛成立一年,
根據(jù)省局黨組《關(guān)于舉辦習(xí)近平談治國理政(第四卷)讀書班的通知》要求,我中心通過專題學(xué)習(xí)、專題研討以及交流分享等形式,系統(tǒng)的對《習(xí)近平談治國理政》(第四卷)進(jìn)行了深入的學(xué)習(xí)與交流,下面我就來談一談我個人
《習(xí)近平談治國理政》(第四卷)是在百年變局和世紀(jì)疫情相互疊加的大背景下,對以習(xí)近平同志為核心的黨中央治國理政重大戰(zhàn)略部署、重大理論創(chuàng)造、重大思想引領(lǐng)的系統(tǒng)呈現(xiàn)。它生動記錄了新一代黨中央領(lǐng)導(dǎo)集體統(tǒng)籌兩個
《真抓實干做好新發(fā)展階段“三農(nóng)工作”》是《習(xí)近平談治國理政》第四卷中的文章,這是習(xí)近平總書記在2020年12月28日中央農(nóng)村工作會議上的集體學(xué)習(xí)時的講話。文章指出,我常講,領(lǐng)導(dǎo)干部要胸懷黨和國家工作大
在《習(xí)近平談治國理政》第四卷中,習(xí)近平總書記強(qiáng)調(diào),江山就是人民,人民就是江山,打江山、守江山,守的是人民的心。從嘉興南湖中駛出的小小紅船,到世界上最大的執(zhí)政黨,在中國共產(chǎn)黨的字典里,“人民”一詞從來都
黨的十八大以來,習(xí)近平總書記以馬克思主義戰(zhàn)略家的博大胸襟和深謀遠(yuǎn)慮,在治國理政和推動全球治理中牢固樹立戰(zhàn)略意識,在不同場合多次圍繞戰(zhàn)略策略的重要性,戰(zhàn)略和策略的關(guān)系,提高戰(zhàn)略思維、堅定戰(zhàn)略自信、強(qiáng)化戰(zhàn)
《習(xí)近平談治國理政》第四卷集中展示了以習(xí)近平同志為核心的黨中央在百年變局和世紀(jì)疫情相互疊加背景下,如何更好地堅持和發(fā)展中國特色社會主義而進(jìn)行的生動實踐與理論探索;對于新時代堅持和發(fā)展什么樣的中國特色社
在黨組織的關(guān)懷下,我有幸參加了區(qū)委組織部組織的入黨積極分子培訓(xùn)班。為期一周的學(xué)習(xí),學(xué)習(xí)形式多樣,課程內(nèi)容豐富,各位專家的講解細(xì)致精彩,對于我加深對黨的創(chuàng)新理論的認(rèn)識、對黨的歷史的深入了解、對中共黨員的
《習(xí)近平談治國理政》第四卷《共建網(wǎng)上美好精神家園》一文中指出:網(wǎng)絡(luò)玩命是新形勢下社會文明的重要內(nèi)容,是建設(shè)網(wǎng)絡(luò)強(qiáng)國的重要領(lǐng)域。截至2021年12月,我國網(wǎng)民規(guī)模達(dá)10 32億,較2020年12月增長4
剛剛召開的中國共產(chǎn)黨第十九屆中央委員會第七次全體會議上討論并通過了黨的十九屆中央委員會向中國共產(chǎn)黨第二十次全國代表大會的報告、黨的十九屆中央紀(jì)律檢查委員會向中國共產(chǎn)黨第二十次全國代表大會的工作報告和《