栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

nuaa计算机网络课设

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

nuaa计算机网络课设

《计算机网络课程设计》报告
  • 姓名:sunshinewinter
  • 完成日期:2021.11
  • 本次实验,我完成了全部实验题。
目录

文章目录
  • 《计算机网络课程设计》报告
    • 目录
    • 项目1 网络爬虫系统实验
      • 1、实验目的
      • 2、实验原理
      • 3、实验思路
      • 4、代码框架与分析
      • 5、实验代码
      • 6、遇到的问题以及解决方法
      • 7、运行结果分析与评价
    • 项目2 聊天室系统实现
      • 1、实验目的
      • 2、实验原理
      • 3、实验思路
      • 4、代码框架与分析
      • 5、实验代码
      • 6、遇到的问题以及解决方法
      • 7、运行结果分析与评价
    • 其他备注

项目1 网络爬虫系统实验 1、实验目的

1、理解计算机网络协议的基本原理和思想;

2、通过采用C++或Java等语言,实现网络爬虫抓取过程;

3、实现分析HTML语言,抽取文本;

4、实现友好化交互界面。

2、实验原理

网络爬虫基本结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rYkI30XX-1652271228776)(E:study计算机网络temp1.png)]

3、实验思路

本次实验使用了request和beaytifulSoup俩个库进行html的解析与内容获取。

思路:

1、确定所需爬取小说内容的网站,获取该页面的URL和其网站根目录的URL;

2、根据URL利用request库向服务器发起GET请求,从而获取该HTML网页信息;

3、解析HTML信息,通过审查该网页元素(右键网页—>检查),获取标签信息,利用BeautifulSoup查找标签,获取所需信息:小说名,章节名和章节URL;

4、在本地创建以小说名为名字的文件夹,用于存储获取的章节内容;

5、通过循环语句不断对各个章节内容发起GET请求获取HTML信息,并利用BeautifulSoup查找标签,提取该章节小说内容。创建以该章节名为名字的.txt文件,将提取出来的内容存入该文件。

4、代码框架与分析

总体框架:

1、头文件与宏定义

2、get请求目标url,获取html

3、解析html,并查找其中小说名和章节名所在标签

4.根据解析内容利用for循环获取章节url并重复第2-3步,获取该章节内容并存入以该章节为名的txtx文件中。

代码分析:

#python库的引用

#宏定义
#  (1)爬取的小说对应网站网址(target)和该网站根目录(index_path)(本次实验以爬取笔趣阁中小说《诡秘之主》为例)
#  (2)设定爬取的该小说内容的存储路径(save_path)

#向target网站服务器发送请求,并根据打印出来的网页编码格式,修改该响应内容的编码格式(此处例子是UTF-8),防止后续分析时出现乱码。
#通过BeautifulSoup解析该html(soup参数记录该结果)
#根据网页元素,利用findall()函数查找到标签类型为div,属性为class = listmain的标签,利用list_tag获取该标签列表
#同上述理,获取h1标签为小说名,并根据小说名创建该文件夹(如果存储路径下不存在该文件)

#(由于该网站存在隐藏列表的坑,所以分开成为俩个for循环获取)
#1、前十章
#     每个循环获取一个标签为‘dd’的内容,获取其中章节名和章节网址;
#	  访问该网址内容,获取html信息后解析获取正文文本;
#	  将当前章节写入文件
#2、后续(同前十章思路,仅仅是根据网页内容将list_tag内容修改为对于span标签的查找)
5、实验代码
import requests
from bs4 import BeautifulSoup
import os

target = "https://www.biquge7.com/book/636/"   #爬取的小说对应网站
index_path='https://www.biquge7.com'           #该网站根目录

save_path = 'E:/book'   #文本保存路径

req = requests.get(url = target)
req.encoding = 'utf-8'
soup = BeautifulSoup(req.text,"html.parser")   #解析html
list_tag = soup.findAll(name="div", attrs={"class" :"listmain"})

story_title = str(soup.h1)    #获取小说名称
print('story_title:',story_title[4:8])     #去除小说名中的h1标签内容
dir_path = save_path+'/'+story_title[4:8]  #根据小说名创建文件夹
if not os.path.exists(dir_path):
    os.path.join(save_path,story_title)
    os.mkdir(dir_path)

i = 1
for dd_tag in list_tag[0].dl.find_all('dd'):    #循获取前十章章节名称与章节对应的网址
    if i < 11: 
        chapter_name = dd_tag.string    #章节名      
        chapter_url = index_path+dd_tag.a.get('href')   #章节网址
        print(chapter_url)    
        chapter_req = requests.get(url = chapter_url)   #访问该章节详情网址,爬取正文
        chapter_req.encoding = 'utf-8'
        chapter_soup = BeautifulSoup(chapter_req.text, "html.parser")
            
        content_tag = chapter_soup.findAll(name="div", attrs={"class" :"Readarea ReadAjax_content"}) #解析出来正文所在的标签
        temp = str(content_tag[0].text)
        content_text = temp.replace(" ", "n")  #获取正文文本
        with open(dir_path+'/'+chapter_name+'.txt', 'w') as f: #将当前章节写入文件
            f.write(content_text.encode("gbk", 'ignore').decode("gbk", "ignore"))
    i = i + 1

#第十章之后做了隐藏操作,通过跳过该隐藏脚本进行读取后续章节
list_tag = soup.findAll(name="span", attrs={"class" :"dd_hide"})  #隐藏章节,读取类似前十章
for dd_tag in list_tag[0].find_all('dd'):
    chapter_name = dd_tag.string    #章节名
    chapter_url = index_path+dd_tag.a.get('href')   #章节网址
    print(chapter_url)    
    chapter_req = requests.get(url = chapter_url)   #访问该章节详情网址,爬取正文
    chapter_req.encoding = 'utf-8'
    chapter_soup = BeautifulSoup(chapter_req.text, "html.parser")
            
    content_tag = chapter_soup.findAll(name="div", attrs={"class" :"Readarea ReadAjax_content"}) #解析出来正文所在的标签
    content_text = str(content_tag[0].text)  #获取正文文本
    with open(dir_path+'/'+chapter_name+'.txt', 'w') as f: #将当前章节写入文件
        f.write(content_text.encode("gbk", 'ignore').decode("gbk", "ignore"))
6、遇到的问题以及解决方法

1、使用soup.div(id="list")函数获取div标签下内容为空

解决方法:改为使用findAll()函数,获取信息列表并对第一个列表信息提前需要的内容。

2、爬取章节文本内容时,总是不打印后续章节内容(只显示前十章)

解决方法:根据获取的html内容的打印结果,发现在十章后出现了一个’dd’标签内容为:以下为隐藏列表的JS脚本,经过查看html代码,发现下面的章节信息都在span标签下。所以通过分开循环获取后续章节内容。

7、运行结果分析与评价

1、运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vKMWZlcT-1652271228777)(E:study计算机网络temp2.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ruSqUcr0-1652271228777)(E:study计算机网络temp3.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l7LtY2LG-1652271228777)(E:study计算机网络temp4.png)]

2、结果分析:

总体来说,从准确率和爬取速度来说,本次实验十分成功。单重for循环使得时间复杂度并不高。唯一缺陷是企图通过replace()函数将空格改为换行,但是不知为何无法实现。

项目2 聊天室系统实现 1、实验目的

1、熟悉计算机网络编程,掌握基于Socket编程;

2、实现聊天室的客户端和聊天室服务器段,同时实现用户友好化的交互界面;

3、实现具有一定的并发处理能力。

2、实验原理

socket是“open—write/read—close”模式的一种实现。

socket中TCP的三次握手建立:

  • 客户端向服务器发送一个SYN J
  • 服务器向客户端响应一个SYN K,并对SYN J进行确认ACK J+1
  • 客户端再想服务器发一个确认ACK K+1

​ 当客户端调用connect时,触发了连接请求,向服务器发送了SYN J包,此时connect进入阻塞状态;服务器监听到连接请求,即收到SYN J包,调用accept函数接收请求向客户端发送SYN K ,ACK J+1,此时accept进入阻塞状态;客户端收到服务器的SYN K ,ACK J+1之后,connect返回,并对SYN K进行确认;服务器收到ACK K+1时,accept返回,至此三次握手完毕,连接建立。

3、实验思路

​ 本次实验通过Socket通信实现功能,采用客户端/服务器(C/S)架构模式,编写聊天室程序。除此之外,本次实验运用了多线程,可实现并发与多点对多点的聊天以及一定的私聊技术。对于在线用户列表,本次实验进行了json相关数据包的处理。

客户端:注册用户名和IP地址,在登陆后的聊天室中可进行聊天功能,能看到该聊天室在线用户与聊天信息,并,并且可在该聊天室发送信息。

服务端:接收用户信息,以及完成消息的接收与转发功能,支持整个聊天室的运行。

c.py:(客户端)

1、登录界面

设置界面窗口,并与输入的ip地址建立连接,发送用户名信息。

2、聊天室界面

设置界面窗口。接受来自服务器的信息并更新列表和消息界面;将用户想要发送的信息发给服务端。

s.py:(服务端)服务端在接受到数据后,会对其进行一些处理然后发送给客户端,如下图,对于聊天内容,服务端直接发送给客户端,而对于用户列表,便由json.dumps处理后发送。

4、代码框架与分析

c.py

#头文件

#宏定义
#	IP,PORT,在线用户列表框,列表框开关设置,用户列表

#登录窗口图形界面

#登录设置
#	获取用户名数据

#建立连接
#	socket链接,如果存在该用户,发送;否则提示无该用户

#聊天窗口界面

#消息界面

#在线用户列表界面

#发送消息

#接收来自服务器的消息
#	如果新增用户,则重载列表,否则直接打印接收到的聊天内容;

#结束

s.py

#头文件

#宏定义
#	ip,port,消息队列,用户信息,线程

#onlines   统计当前在线用户

#chatserver类	聊天服务功能
#	初始化
#	接收客户端发来的用户名
#	将地址和数据存入消息列表
#	处理数据后发送给客户端
#	多线程处理

#主函数
5、实验代码

c.py

import socket
import tkinter
import tkinter.messagebox
import threading
import json
import tkinter.filedialog
from tkinter.scrolledtext import ScrolledText

IP = ''
PORT = ''
user = ''
listbox1 = ''   #在线用户列表框
show = 1        #列表框开关设置
users = []      #在线用户列表
chat = '------ welcome -------' #聊天对象

#登陆窗口图形界面设置
root0 = tkinter.Tk()
root0.geometry("400x247")
root0.title('Meeting & Chat')  #标题
root0.resizable(0,0)
one = tkinter.Label(root0, width = 400, height = 247, bg = "Ivory")
one.pack()

IP0 = tkinter.StringVar()
IP0.set('')
USER = tkinter.StringVar()
USER.set('')

labelIP = tkinter.Label(root0, text = 'IP address', bg = "Ivory")  #ip地址框
labelIP.place(x = 30, y = 55, width = 100, height = 40)
entryIP = tkinter.Entry(root0, width = 60, textvariable = IP0)
entryIP.place(x = 145, y = 60, width = 200, height = 30)

labelUSER = tkinter.Label(root0,text='username',bg="Ivory")        #用户名框
labelUSER.place(x = 30, y = 100, width = 100, height = 40)
entryUSER = tkinter.Entry(root0, width = 60, textvariable = USER)
entryUSER.place(x = 145, y = 105, width = 200, height = 30)

def Login(*args):   #登录设置
	global IP, PORT, user
	IP, PORT = entryIP.get().split(':')
	user = entryUSER.get()
	if not user:  #用户名为空
		tkinter.messagebox.showwarning('warning', message='username should not be blank!!!')
	else:
		root0.destroy()

loginButton = tkinter.Button(root0, text = "Login In", command = Login,bg="Lavender")  #登录键
loginButton.place(x = 150, y = 160, width = 110, height = 30)
root0.bind('', Login)

root0.mainloop()

#建立连接
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((IP, int(PORT)))
if user:   #存在该用户时
  s.send(user.encode())  #发送用户名
else:
  s.send('There is no such username!!!'.encode())
  user = IP + ':' + PORT

#聊天窗口
root1 = tkinter.Tk()
root1.geometry("660x517")
root1.title('ChattingRoom')
root1.resizable(0,0)

#消息界面
listbox = ScrolledText(root1, bg = 'MintCream')
listbox.place(x = 4, y = 4, width = 640, height = 312)
listbox.tag_config('tag1', foreground='Brown',background = "Lavender")
listbox.insert(tkinter.END, 'Welcome to the chatting Room!Try to talk now ~', 'tag1')

INPUT = tkinter.StringVar()
INPUT.set('')
entryIuput = tkinter.Entry(root1, width = 120, textvariable = INPUT, bg = 'MintCream')
entryIuput.place(x = 4,y = 324, width = 652, height = 152)

#在线用户列表
listbox1 = tkinter.Listbox(root1, bg = 'MintCream')
listbox1.place(x = 520, y = 4, width = 134, height = 312)

def send(*args):
	message = entryIuput.get() + '~' + user + '~' + chat
	s.send(message.encode())
	INPUT.set('')

sendButton = tkinter.Button(root1, text ="SEND",anchor = 'n', command = send, font=('Helvetica', 10), bg = 'LightBlue')
sendButton.place(x = 560, y = 480, width = 55, height = 30)
root1.bind('', send)

#接收来自服务器的消息
def receive():
	global uses
	while True:
		data = s.recv(1024)
		data = data.decode()
		print(data)
		try:
			uses = json.loads(data)   #重载在线用户列表
			listbox1.delete(0, tkinter.END)
			listbox1.insert(tkinter.END, "online member")
			listbox1.insert(tkinter.END, "------member list-------")
			for x in range(len(uses)):
				listbox1.insert(tkinter.END, uses[x])
			users.append('------member list-------')
		except:
			data = data.split('~')    #聊天内容打印
			message = data[0]
			userName = data[1]
			chatwith = data[2]
			message = 'n' + message
			if chatwith == '------member list-------':  #群聊
				if userName == user:
					listbox.insert(tkinter.END, message)
				else:
					listbox.insert(tkinter.END, message)
			elif userName == user or chatwith == user:  #私聊
				if userName == user:
					listbox.tag_config('tag2', foreground ='Orange')
					listbox.insert(tkinter.END, message, 'tag2')
				else:
					listbox.tag_config('tag3', foreground ='green')
					listbox.insert(tkinter.END, message, 'tag3')

			listbox.see(tkinter.END)
r = threading.Thread(target = receive)
r.start() # 开始线程接收信息

root1.mainloop()
s.close()

s.py

import socket
import threading
import queue
import json #json.dumps(some):打包  json.loads(some):解包
import os
import os.path
import sys

IP = '127.0.0.1'
PORT = 8800   # 端口
messages = queue.Queue()   #消息队列
users = []    #0:userName 1:connection
lock = threading.Lock()

def onlines():  #统计当前在线人员
  online = []   #在线人员列表
  for i in range(len(users)):
    online.append(users[i][0])   #添加新用户
  return online

class ChatServer(threading.Thread):  #聊天服务功能
  global users, que, lock

  def __init__(self):     #构造函数
    threading.Thread.__init__(self)  #初始化
    self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    os.chdir(sys.path[0])

  #接收来自客户端的用户名。若用户名为空,则使用用户的IP与端口作为用户名;若用户名重复,则在用户名后依此加上后缀数字2,3,4……
  def receive(self, conn, addr):  #接收消息
    user = conn.recv(1024)        #用户名称
    user = user.decode()
    if user == '用户名不存在':     #用户名不存在时
      user = addr[0] + ' : ' + str(addr[1])
    tag = 1
    temp = user
    for i in range(len(users)):   #如果重名,则加数字
      if users[i][0] == user:
        tag = tag + 1
        user = temp + str(tag)
    users.append((user, conn))
    USERS = onlines()
    self.Load(USERS,addr)
    
    #接受用户端发来的消息(即聊天内容),结束后关闭连接
    try:
      while True:
        message = conn.recv(1024)      #发送消息
        message = message.decode()
        message = user + ':' + message
        self.Load(message,addr)
      conn.close()

    #若用户断开连接,则将该用户从列表中删除,并更新用户列表
    except:  
      j = 0      #断开连接
      for man in users:
        if man[0] == user:
          users.pop(j)    #服务器端删除退出的用户
          break
        j = j+1

      USERS = onlines()
      self.Load(USERS,addr)
      conn.close()

  #将地址与数据存入messages队列
  def Load(self, data, addr):
    lock.acquire()   #获取列表
    try:
      messages.put((addr, data))  #加入列表
    finally:
      lock.release()    

  #服务端在接受到数据后,会对其进行一些处理后发送给客户端
  def sendData(self): # 发送数据
    while True:
      if not messages.empty():   #非空信息,发送
        message = messages.get()
        if isinstance(message[1], str):
          for i in range(len(users)):
            data = ' ' + message[1]
            users[i][1].send(data.encode())
            print(data)
            print('n')

        if isinstance(message[1], list):  #转发
          data = json.dumps(message[1])
          for i in range(len(users)):
            try:
              users[i][1].send(data.encode())
            except:
              pass

  #继承threading.Thread类,从而实现多线程
  def run(self):
    self.s.bind((IP,PORT))
    self.s.listen(5)
    q = threading.Thread(target = self.sendData)
    q.start()
    while True:
      conn, addr = self.s.accept()
      t = threading.Thread(target = self.receive, args = (conn, addr))
      t.start()
    self.s.close()
    
if __name__ == '__main__':   #main函数
  cserver = ChatServer()
cserver.start()
6、遇到的问题以及解决方法

1、图形化界面不熟,会出现各个框图重叠的现象。

解决方案:通过不断调试完成界面设计。

2、出现了无法进行群聊只能私聊的情况。

解决方案:经过分析,发现是参数匹配错误,使得群聊情况无法跳转。

7、运行结果分析与评价

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gscjZBim-1652271228777)(E:study计算机网络temp5.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7xNTjusD-1652271228778)(E:study计算机网络temp6.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XAGBkYIv-1652271228778)(E:study计算机网络temp7.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k4nUnbXe-1652271228778)(E:study计算机网络temp8.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lfja3Yho-1652271228778)(E:study计算机网络temp9.png)]

结果分析:

​ 本次实验基于socket和ykinter成功完成了一个带图形界面的简易聊天室程序,速度较快且支持多人,效果不错。

其他备注

参考内容:

Python3网络爬虫快速入门实战解析_Jack-Cui-CSDN博客_python 爬虫快速入门

github.com

(1条消息) 手把手教你利用爬虫爬网页(Python代码)_Python大本营的博客-CSDN博客

socket–socket()、bind()、listen()、connect()、accept()、recv()、send()、select()、close()、shutdown() - 未闻花开 - 博客园 (cnblogs.com)

Python实现网络聊天室的示例代码(支持多人聊天与私聊)_python_脚本之家 (jb51.net)

tkinter模块常用参数(python3) - 覆手为云p - 博客园 (cnblogs.com)

/article/details/90206227/?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0.no_search_link&spm=1001.2101.3001.4242.1)

socket–socket()、bind()、listen()、connect()、accept()、recv()、send()、select()、close()、shutdown() - 未闻花开 - 博客园 (cnblogs.com)

Python实现网络聊天室的示例代码(支持多人聊天与私聊)_python_脚本之家 (jb51.net)

tkinter模块常用参数(python3) - 覆手为云p - 博客园 (cnblogs.com)

(1条消息) 什么是socket?socket详解_刘德鹏的博客-CSDN博客_socket.socket

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/877631.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号