财联社实时监控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  乘风王先生  阅读(0)  评论(0)    收藏  举报