java编写聊天室和爬虫实验报告
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. 客户端
(1)登录 客户端系统运行,出现登录界面。该界面出现在屏幕中间。用户输入其用户名,然后建立与服务器的连接,输入成功后显示聊天界面。已经登陆了聊天室的用户的聊天记录上面实时刷新上线下线消息,并且同时更新客户端和服务器端的用户列表。
(2)群聊 客户端首先发送消息到服务器端,服务器端转发给全体客户端,所有客户端接收消息并显示在聊天记录中。将消息写入输入框,点击 “发送消息”即可在群内发言。聊天记录显示在所有客户端界面左边,好友列表在各个客户端右边显示。
(3)私聊 客户端首先发送消息到服务器端,服务器端转发给全体客户端,所有客户端接收消息,但是只有特定客户端处理此消息。A 点击右侧好友列表的 B,然后点击“私发消息”,即弹出私聊界面,将消息写入输入框,点击 “发消息”即可与另一方私聊。B 的聊天界面显示“系统提示:A 私聊了你”,然后点击右侧列表对应好友的用户名,并且点击“发消息”即可查看对方的聊天记录并与对方私聊。
2. 服务器端
(1)
群发系统消息 服务器将消息写入输入框,点击 “群发消息”即可将消息发送给全体客户端,在群内显示系统消息。
(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,基本流程如下:
(1)创建套接字 (2)打开连接的 IO (3)按照协议读写 (4)关闭资源
服务器用来听,用来等待客户端程序来寻找。如果客户端的程序来寻找 9999端口,那么这个程序就会响应。
服务器通过一个循环一直监听 9999 端口,当有客户端连接到端口时,并把连接的通信添加到服务器管理集合。
大致步骤:
(1)创建一个 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)实现群聊
(2)刷新好友列表
(3)私聊
(4)服务器群发消息
(5)实现踢人
第六章 用 JavaURL 编程爬取并分析网页敏感词业务分析 一、实践目的或任务:
通过指导学生上机实践,对 JavaURL 编程、Java 图形界面进行掌握。
二、实践基本要求:
1.了解实验目的及实验原理; 2.编写程序,并附上程序代码和结果图; 3.总结在编程过程中遇到的问题、解决办法和收获。
三、实践的内容或要求:
1.编写界面,输入一个网址,能够爬取该网址上所有的 HTML 源代码。
2.对网址中的文本进行提取。
3.建立敏感词库,用文本文件保存。
4.将该网址所对应的文本中的敏感词提取并高亮显示。
5.编写文本文件,可以存入多个网址;程序可爬取这些网址中的文本内容,将敏感词记录存入另一个文件,格式自定。
6.编写一个主界面,整合上述功能。
第七章 用 JavaURL 编程爬取并分析网页敏感词系统设计 一、系统功能定义 本系统要实现的功能如下:
1. 主界面
(1)网页分析功能 运行 GUI,在输入框输入一个网址,选择“爬取网页”能够爬取该网址上所有的 HTML 源代码并在控制台输出,
(2)保存文本功能 将爬取的文本和敏感词记录保存在爬取文本.txt 中,同时将敏感词记录存入敏感词记录.txt。
(3)显示文本功能 弹出的显示文档页面可以将该网址所对应的文本中的敏感词高亮显示。
(4)保存网址功能 选择“保存网址”能够将所输入网址保存在文本文件 weblist.txt 中,此文件可以存入多个网址。
2. 批量爬取界面
(1)批量爬取功能 运行 WebGroup,点击 “批量爬取”能通过循环运行 webPageResource 爬取weblist.txt 中网址中的内容。
(2)保存文本功能 将 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(); // 取得文本
(3)敏感词匹配 在实现文字过滤的算法中,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();
...
上一篇:乡镇脱贫攻坚规划
下一篇:开掘工厂厂长劳动模范申报材料