新闻项目与虚拟茶话会聊天服务器开发
新闻项目
新闻项目旨在从不同源获取新闻信息,并将其分发到不同的目的地。以下是具体实现步骤:
-
定义新闻源
- BBC 新闻源 :从 BBC 新闻网站获取新闻。
bbc_url = 'http://news.bbc.co.uk/text_only.stm'
bbc_title = r'(?s)a href="[^"]*">\s*<b>\s*(.*?)\s*</b>'
bbc_body = r'(?s)</a>\s*<br />\s*(.*?)\s*<'
bbc = SimpleWebSource(bbc_url, bbc_title, bbc_body)
agent.addSource(bbc)
- **Python 公告新闻组源**:从 `comp.lang.python.announce` 新闻组获取新闻。
clpa_server = 'news.foo.bar' # Insert real server name
clpa_group = 'comp.lang.python.announce'
clpa_window = 1
clpa = NNTPSource(clpa_server, clpa_group, clpa_window)
agent.addSource(clpa)
-
定义新闻目的地
- 纯文本目的地 :将新闻以纯文本形式输出。
-
HTML 目的地
:将新闻以 HTML 形式输出到
news.html文件。
agent.addDestination(PlainDestination())
agent.addDestination(HTMLDestination('news.html'))
- 分发新闻
agent.distribute()
- 主程序入口
if __name__ == '__main__': runDefaultSetup()
进一步探索
该项目具有很强的扩展性,以下是一些进一步探索的方向:
-
创建更强大的 Web 源
:使用屏幕抓取技术。
-
创建 RSS 源
:解析 RSS 数据。
-
改进 HTML 目的地的布局
:提升新闻展示效果。
-
创建页面监控器
:监控网页变化,有变化时提供新闻项。
-
创建 CGI 版本的新闻脚本
:方便在网页上使用。
-
创建邮件目的地
:将新闻通过邮件发送。
-
添加命令行开关
:选择新闻格式。
-
添加配置文件
:设置源和目的地。
-
提供新闻来源信息
:实现更精美的布局。
-
对新闻项进行分类
:通过关键词搜索。
-
创建 XML 目的地
:生成适合网站构建的 XML 文件。
虚拟茶话会聊天服务器项目
在线聊天日益普及,开发自己的聊天服务器有两个好处:学习网络编程和可按需定制。
具体目标
- 接收多个用户的连接。
- 让用户并行操作。
-
解释
say、logout等命令。 - 根据用户状态(连接、登录、注销等)处理每个会话。
- 易于扩展。
有用的工具
本项目主要使用标准库中的
asyncore
和
asynchat
模块。
asyncore
框架基于
select
函数,能让服务器以分段方式服务所有连接的用户,避免一个用户占用全部资源。
准备工作
- 网络连接 :需要一台连接到网络的计算机,用户需知道服务器的地址和端口号(本项目使用 5005)。
-
测试客户端
:可以使用
telnet或专门的聊天客户端(如 TinyFugue)进行测试。
第一次实现
需要创建两个主要类:
ChatServer
和
ChatSession
。
-
ChatServer 类
- 最小服务器程序
from asyncore import dispatcher
import asyncore
class ChatServer(dispatcher): pass
s = ChatServer()
asyncore.loop()
- **接受连接的服务器程序**
from asyncore import dispatcher
import socket, asyncore
class ChatServer(dispatcher):
def handle_accept(self):
conn, addr = self.accept()
print 'Connection attempt from', addr[0]
s = ChatServer()
s.create_socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 5005))
s.listen(5)
asyncore.loop()
- **带有清理功能的基本服务器程序**
from asyncore import dispatcher
import socket, asyncore
PORT = 5005
class ChatServer(dispatcher):
def __init__(self, port):
dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind(('', port))
self.listen(5)
def handle_accept(self):
conn, addr = self.accept()
print 'Connection attempt from', addr[0]
if __name__ == '__main__':
s = ChatServer(PORT)
try: asyncore.loop()
except KeyboardInterrupt: pass
-
ChatSession 类
ChatSession类负责处理服务器与单个用户之间的连接,使用asynchat模块简化了基本的套接字读写操作。
from asyncore import dispatcher
from asynchat import async_chat
import socket, asyncore
PORT = 5005
class ChatSession(async_chat):
def __init__(self, sock):
async_chat.__init__(self, sock)
self.set_terminator("\r\n")
self.data = []
def collect_incoming_data(self, data):
self.data.append(data)
def found_terminator(self):
line = ''.join(self.data)
self.data = []
# Do something with the line...
print line
class ChatServer(dispatcher):
def __init__(self, port):
dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind(('', port))
self.listen(5)
self.sessions = []
def handle_accept(self):
conn, addr = self.accept()
self.sessions.append(ChatSession(conn))
if __name__ == '__main__':
s = ChatServer(PORT)
try: asyncore.loop()
except KeyboardInterrupt: print
这个服务器现在能够处理多个并发连接,但还缺少广播功能。
完善聊天服务器
在将原型视为一个功能齐全的聊天服务器之前,还需要实现广播功能,并确保在客户端断开连接时从列表中移除连接。
from asyncore import dispatcher
from asynchat import async_chat
import socket, asyncore
PORT = 5005
NAME = 'TestChat'
class ChatSession(async_chat):
"""
A class that takes care of a connection between the server
and a single user.
"""
def __init__(self, server, sock):
# Standard setup tasks:
async_chat.__init__(self, sock)
self.server = server
self.set_terminator("\r\n")
self.data = []
# Greet the user:
self.push('Welcome to %s\r\n' % self.server.name)
def collect_incoming_data(self, data):
self.data.append(data)
def found_terminator(self):
"""
If a terminator is found, that means that a full
line has been read. Broadcast it to everyone.
"""
line = ''.join(self.data)
self.data = []
self.server.broadcast(line)
def handle_close(self):
async_chat.handle_close(self)
self.server.disconnect(self)
class ChatServer(dispatcher):
"""
A class that receives connections and spawns individual
sessions. It also handles broadcasts to these sessions.
"""
def __init__(self, port, name):
# Standard setup tasks
dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
通过以上步骤,我们完成了新闻项目和虚拟茶话会聊天服务器项目的开发,并且了解了它们的扩展方向。
下面是虚拟茶话会聊天服务器项目的流程图:
graph TD;
A[启动服务器] --> B[等待连接];
B --> C{有新连接?};
C -- 是 --> D[创建 ChatSession];
D --> E[接收数据];
E --> F{找到终止符?};
F -- 是 --> G[广播消息];
G --> E;
F -- 否 --> E;
C -- 否 --> B;
总结来说,新闻项目和虚拟茶话会聊天服务器项目都具有一定的实用性和扩展性,通过学习和实践这些项目,我们可以提升自己的编程能力和解决问题的能力。在实际应用中,我们可以根据需求对项目进行进一步的优化和扩展。例如,在新闻项目中,可以增加更多的新闻源和目的地;在聊天服务器项目中,可以添加更多的命令和功能,如私聊、群组聊天等。
新闻项目与虚拟茶话会聊天服务器开发(续)
新闻项目的操作要点总结
为了更清晰地展示新闻项目的操作流程,以下用表格形式总结:
| 步骤 | 操作内容 | 代码示例 |
| ---- | ---- | ---- |
| 定义新闻源 | 从 BBC 新闻网站和 Python 公告新闻组获取新闻 |
python<br>bbc_url = 'http://news.bbc.co.uk/text_only.stm'<br>bbc_title = r'(?s)a href="[^"]*">\s*<b>\s*(.*?)\s*</b>'<br>bbc_body = r'(?s)</a>\s*<br />\s*(.*?)\s*<'<br>bbc = SimpleWebSource(bbc_url, bbc_title, bbc_body)<br>agent.addSource(bbc)<br>clpa_server = 'news.foo.bar' # Insert real server name<br>clpa_group = 'comp.lang.python.announce'<br>clpa_window = 1<br>clpa = NNTPSource(clpa_server, clpa_group, clpa_window)<br>agent.addSource(clpa)<br>
|
| 定义新闻目的地 | 纯文本和 HTML 两种形式输出新闻 |
python<br>agent.addDestination(PlainDestination())<br>agent.addDestination(HTMLDestination('news.html'))<br>
|
| 分发新闻 | 执行新闻分发操作 |
python<br>agent.distribute()<br>
|
| 主程序入口 | 启动程序 |
python<br>if __name__ == '__main__': runDefaultSetup()<br>
|
虚拟茶话会聊天服务器项目的深入分析
广播功能的实现原理
在聊天服务器中,广播功能是核心。当一个用户输入内容并按下回车键(即找到终止符)后,
ChatSession
类的
found_terminator
方法会被调用。该方法将用户输入的内容拼接成完整的一行,然后调用
ChatServer
的
broadcast
方法,将这行内容发送给所有连接的用户。以下是简化的实现逻辑:
class ChatServer(dispatcher):
# ... 已有代码 ...
def broadcast(self, line):
for session in self.sessions:
session.push(line + '\r\n')
客户端断开连接处理
为了确保服务器的稳定性,需要处理客户端断开连接的情况。当客户端断开连接时,
ChatSession
类的
handle_close
方法会被调用,该方法会调用
ChatServer
的
disconnect
方法,将该会话从
sessions
列表中移除。以下是实现代码:
class ChatServer(dispatcher):
# ... 已有代码 ...
def disconnect(self, session):
self.sessions.remove(session)
项目的扩展方向
新闻项目扩展
-
创建更强大的 Web 源
:使用屏幕抓取技术,首先要确定目标网站的 HTML 结构,然后使用正则表达式或 HTML 解析库(如
BeautifulSoup)提取所需信息。 -
创建 RSS 源
:使用
feedparser库解析 RSS 数据。以下是简单示例:
import feedparser
rss_url = 'https://example.com/rss.xml'
feed = feedparser.parse(rss_url)
for entry in feed.entries:
print(entry.title)
- 改进 HTML 目的地的布局 :可以使用 CSS 样式表来美化新闻展示效果,将生成的 HTML 文件与 CSS 文件关联。
聊天服务器项目扩展
-
添加更多命令
:如
whisper实现私聊功能。在ChatSession类的found_terminator方法中解析命令:
class ChatSession(async_chat):
# ... 已有代码 ...
def found_terminator(self):
line = ''.join(self.data)
self.data = []
if line.startswith('/whisper '):
parts = line.split(' ', 2)
target_name = parts[1]
message = parts[2]
# 查找目标用户并发送消息
for session in self.server.sessions:
if session.user_name == target_name:
session.push(f'[私聊] {self.user_name}: {message}\r\n')
else:
self.server.broadcast(line)
- 实现群组聊天 :可以创建群组类,每个群组维护一个成员列表,在发送消息时根据群组信息进行广播。
总结
通过对新闻项目和虚拟茶话会聊天服务器项目的开发和扩展,我们不仅学习了如何从不同源获取和分发新闻,还掌握了网络编程中多用户并发处理的技巧。以下是整个开发过程的流程图:
graph LR;
A[选择项目类型] --> B{新闻项目};
B -- 是 --> C[定义新闻源];
C --> D[定义新闻目的地];
D --> E[分发新闻];
B -- 否 --> F{聊天服务器项目};
F -- 是 --> G[创建 ChatServer];
G --> H[等待连接];
H --> I[创建 ChatSession];
I --> J[接收数据];
J --> K{是否有命令};
K -- 是 --> L[处理命令];
K -- 否 --> M[广播消息];
L --> J;
M --> J;
在实际应用中,我们可以根据具体需求对这些项目进行灵活调整和扩展,不断提升项目的功能和性能。无论是新闻项目的新闻获取和展示,还是聊天服务器项目的用户交互和并发处理,都为我们提供了丰富的学习和实践机会。
超级会员免费看
38

被折叠的 条评论
为什么被折叠?



