财联社实时监控50条

import requests
import json
import time
from requests.adapters import HTTPAdapter

referer_url = "https://www.cls.cn/telegraph"

cookie = ""

headers = {
"Accept": "/",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9",
"Connection": "keep-alive",
# "Cookie": cookie,
"Host": "www.cls.cn",
"Referer": referer_url,
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36"
}

API基础URL

api_base = "https://www.cls.cn/nodeapi/telegraphList"

生成签名

def encrypts(s_url):
"""生成API签名"""
# 第一步:SHA1加密
import hashlib
sha1 = hashlib.sha1()
sha1.update(s_url.encode('utf-8'))
sha1_result = sha1.hexdigest()

第二步:对SHA1结果进行MD5加密

md5 = hashlib.md5()
md5.update(sha1_result.encode('utf-8'))
sign = md5.hexdigest()

return sign

构造带签名的URL

def build_url(last_time=None):
"""构造带签名的API请求URL"""
if last_time is None:
last_time = int(time.time())

构造请求参数

app = 'CailianpressWeb'
os = 'web'
rn = 100 # 每页返回100条新闻
sv = '7.7.5'

生成签名参数字符串(按特定顺序拼接)

s_url = f'app={app}&last_time={last_time}&os={os}&rn={rn}&sv={sv}'

生成签名

sign = encrypts(s_url)

构造完整URL

url = f'{api_base}?{s_url}&sign={sign}'
return url

def get_json_data(headers):
"""安全获取和解析JSON数据,使用正确的API签名"""
try:
# 使用Session进行请求
s = requests.Session()
s.mount('http://', HTTPAdapter(max_retries=3))
s.mount('https://', HTTPAdapter(max_retries=3))

构建带签名的URL

url = build_url()
print(f"请求URL: {url}")

response = s.get(url, timeout=10, headers=headers)
response.raise_for_status() # 检查请求是否成功

确保正确的编码

response.encoding = 'utf-8'

安全解析JSON数据

results = response.json()

检查返回数据结构

if 'data' not in results:
print("⚠️ 响应中没有'data'字段")
print(f"响应内容: {results}")
return []

if 'roll_data' not in results['data']:
print("⚠️ 响应中没有'roll_data'字段")
print(f"data内容: {results['data']}")
return []

data = results['data']['roll_data']
all_list = []
for i in data:
try:
time_tuple_1 = time.localtime(i['ctime'])
bj_time = time.strftime("%Y/%m/%d %H:%M:%S", time_tuple_1)

清理内容,防止乱码

content = i.get('content', '')
if isinstance(content, str):
# 确保字符串编码正确
content = content.encode('utf-8', errors='ignore').decode('utf-8')
else:
content = str(content)

all_list.append([bj_time, content])
except Exception as e:
print(f"⚠️ 处理数据项时出错: {e}")
print(f"数据项: {i}")
continue

return all_list

except requests.exceptions.RequestException as e:
print(f"❌ 请求失败: {e}")
return []
except json.JSONDecodeError as e:
print(f"❌ JSON解析错误: {e}")
print(f"响应文本: {response.text}")
return []
except Exception as e:
print(f"❌ 处理数据时出错: {e}")
import traceback
traceback.print_exc()
return []

def get_all_list():
all_list = get_json_data(headers)
return all_list
print(get_all_list())

PyQt5相关导入

from PyQt5 import QtWidgets
from PyQt5.QtGui import QIcon, QFont
from PyQt5.QtWidgets import (
QApplication, QMessageBox, QTableWidgetItem, QHeaderView, QMainWindow,
QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QStatusBar,
QSplitter
)
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QTimer
import sys

不需要导入Cls7X24相关模块,使用本地的get_all_list函数

不需要导入UI模块,直接在代码中创建界面

创建一个后台线程类,用于异步获取新闻数据

class NewsThread(QThread):
# 定义信号,用于传递新闻数据和状态信息
news_fetched = pyqtSignal(list)
error_occurred = pyqtSignal(str)
status_changed = pyqtSignal(str)

def run(self):
try:
self.status_changed.emit("正在获取新闻数据...")
news_list = get_all_list()
self.news_fetched.emit(news_list)
self.status_changed.emit(f"成功获取到 {len(news_list)} 条新闻")
except Exception as e:
self.error_occurred.emit(f"获取新闻失败: {str(e)}")
self.status_changed.emit("获取新闻失败")

创建主窗口类

class NewsMonitorWindow(QMainWindow):
def init(self):
super().init()
self.initThread()
self.initTimer()
self.initUI()

def initUI(self):
# 设置窗口属性
self.setWindowTitle("实时新闻监控系统")
self.setGeometry(100, 100, 1200, 800)
self.setWindowIcon(QIcon())

创建中心部件

central_widget = QWidget()
self.setCentralWidget(central_widget)

创建主布局

main_layout = QVBoxLayout(central_widget)

创建标题

title_label = QLabel("财联社实时新闻监控")
title_font = QFont("微软雅黑", 18, QFont.Bold)
title_label.setFont(title_font)
title_label.setAlignment(Qt.AlignCenter)
title_label.setStyleSheet("color: #2c3e50; margin: 10px 0;")
main_layout.addWidget(title_label)

创建控制栏

control_layout = QHBoxLayout()

刷新按钮

self.refresh_btn = QPushButton("刷新新闻")
self.refresh_btn.setFont(QFont("微软雅黑", 10))
self.refresh_btn.setStyleSheet("padding: 8px 16px; background-color: #3498db; color: white; border-radius: 4px;")
self.refresh_btn.clicked.connect(self.refreshNews)
control_layout.addWidget(self.refresh_btn)

自动刷新复选框

self.auto_refresh_check = QtWidgets.QCheckBox("自动刷新")
self.auto_refresh_check.setFont(QFont("微软雅黑", 10))
self.auto_refresh_check.setChecked(False)
self.auto_refresh_check.stateChanged.connect(self.toggleAutoRefresh)
control_layout.addWidget(self.auto_refresh_check)

自动刷新间隔

self.interval_label = QLabel("间隔:")
self.interval_label.setFont(QFont("微软雅黑", 10))
control_layout.addWidget(self.interval_label)

self.interval_combo = QtWidgets.QComboBox()
self.interval_combo.addItems(["1秒", "3秒", "5秒", "10秒", "30秒", "1分钟", "5分钟", "10分钟"])
self.interval_combo.setFont(QFont("微软雅黑", 10))
self.interval_combo.currentIndexChanged.connect(self.changeInterval)
control_layout.addWidget(self.interval_combo)

状态栏信息

self.status_label = QLabel("就绪")
self.status_label.setFont(QFont("微软雅黑", 10))
self.status_label.setStyleSheet("color: #7f8c8d;")
control_layout.addStretch()
control_layout.addWidget(self.status_label)

main_layout.addLayout(control_layout)

创建新闻表格

self.news_table = QtWidgets.QTableWidget()
self.news_table.setColumnCount(2)
self.news_table.setHorizontalHeaderLabels(["时间", "新闻内容"])

设置表格属性

self.news_table.setAlternatingRowColors(True)
self.news_table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.news_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.news_table.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)

设置表头

header = self.news_table.horizontalHeader()
header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
header.setSectionResizeMode(1, QHeaderView.Stretch)
header.setFont(QFont("微软雅黑", 11, QFont.Bold))

设置表格字体

self.news_table.setFont(QFont("微软雅黑", 10))

main_layout.addWidget(self.news_table)

创建状态栏

self.statusBar = QStatusBar()
self.setStatusBar(self.statusBar)
self.statusBar.showMessage("就绪")

初始加载新闻

self.refreshNews()

def initThread(self):
# 创建新闻获取线程
self.news_thread = NewsThread()
self.news_thread.news_fetched.connect(self.displayNews)
self.news_thread.error_occurred.connect(self.showError)
self.news_thread.status_changed.connect(self.updateStatus)

def initTimer(self):
# 创建自动刷新计时器
self.auto_refresh_timer = QTimer()
self.auto_refresh_timer.timeout.connect(self.refreshNews)
self.auto_refresh_timer.setInterval(30000) # 默认30秒

def refreshNews(self):
# 禁用刷新按钮
self.refresh_btn.setEnabled(False)
self.refresh_btn.setText("刷新中...")

启动新闻获取线程

if not self.news_thread.isRunning():
self.news_thread.start()

def displayNews(self, news_list):
# 清空表格
self.news_table.setRowCount(0)

设置行数

self.news_table.setRowCount(len(news_list))

填充数据

for row, (news_time, content) in enumerate(news_list):
# 时间列
time_item = QTableWidgetItem(news_time)
time_item.setFont(QFont("微软雅黑", 10))
time_item.setTextAlignment(Qt.AlignCenter | Qt.AlignVCenter)
self.news_table.setItem(row, 0, time_item)

内容列

content_item = QTableWidgetItem(content)
content_item.setFont(QFont("微软雅黑", 10))
content_item.setTextAlignment(Qt.AlignLeft | Qt.AlignVCenter)
self.news_table.setItem(row, 1, content_item)

设置行高

self.news_table.resizeRowToContents(row)

恢复刷新按钮

self.refresh_btn.setEnabled(True)
self.refresh_btn.setText("刷新新闻")

def showError(self, error_msg):
# 显示错误消息
QMessageBox.critical(self, "错误", error_msg)

恢复刷新按钮

self.refresh_btn.setEnabled(True)
self.refresh_btn.setText("刷新新闻")

def updateStatus(self, status_msg):
# 更新状态栏
self.statusBar.showMessage(status_msg)
self.status_label.setText(status_msg)

def toggleAutoRefresh(self, state):
# 切换自动刷新
if state == Qt.Checked:
self.auto_refresh_timer.start()
self.updateStatus(f"自动刷新已开启,间隔:{self.interval_combo.currentText()}")
else:
self.auto_refresh_timer.stop()
self.updateStatus("自动刷新已关闭")

def changeInterval(self):
# 改变自动刷新间隔
interval_text = self.interval_combo.currentText()
if interval_text == "1秒":
interval = 1000
elif interval_text == "3秒":
interval = 3000
elif interval_text == "5秒":
interval = 5000
elif interval_text == "10秒":
interval = 10000
elif interval_text == "30秒":
interval = 30000
elif interval_text == "1分钟":
interval = 60000
elif interval_text == "5分钟":
interval = 300000
elif interval_text == "10分钟":
interval = 600000
else:
interval = 30000 # 默认30秒

self.auto_refresh_timer.setInterval(interval)

如果自动刷新已开启,更新状态

if self.auto_refresh_check.isChecked():
self.updateStatus(f"自动刷新已开启,间隔:{interval_text}")

GUI入口

if name == 'main':
app = QApplication(sys.argv)
window = NewsMonitorWindow()
window.show()
sys.exit(app.exec_())

posted @ 2026-01-18 22:50  乘风王先生  阅读(623)  评论(0)    收藏  举报