Python获取上市公司报告,AI分析助力投资决策

news2025/1/12 18:04:31

折腾了几天,通过从巨潮信息网上获取上市公司的报告,然后实现调用大语言模型的API去分析报告内容,下面把相应的代码和过程分享给对这个感兴趣的兄弟姐妹们,希望能帮到大家。

1,首先去巨潮信息网首页,右上角有个查询,输入相应的关键字就能获取上市公司的公告,比如我这里输入“变更会计师事务所

可以看到下面的内容

这些链接打开后,就是一个个的pdf报告

如何批量下载这些报告呢,可以用python去实现,

可以先找到这个pdf文件的data-id值,

然后在idm下载地址中发现下载地址都是下面的格式,最后就是data-id加pdf命名

找到这个规律后,写出python代码如下:

import os
import requests
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
from bs4 import BeautifulSoup
import time

from selenium.webdriver.chrome.options import Options  # 导入Options类

def download_pdfs_after_n_pages(start_click, max_clicks, url, save_dir, temp_dir):
    # 设置Selenium选项,以无头模式运行Chrome
    options = Options()
    options.headless = True
    options.add_argument("--window-size=1920,1080")

    # 创建WebDriver实例
    driver = webdriver.Chrome(options=options)

    # 打开网页
    driver.get(url)

    # 用于存储所有页面的链接
    all_links = []

    # 设置翻页计数器
    click_counter = 0

    # 循环直到达到最大翻页次数
    while click_counter < max_clicks:
        # 如果当前点击次数大于或等于指定的开始点击次数,则开始收集链接
        if click_counter >= start_click:
            soup = BeautifulSoup(driver.page_source, 'html.parser')
            a_tags = soup.select("#fulltext-search > div:nth-child(2) > div > div > div:nth-child(3) > div.tab-content > div.el-table-box > div > div.el-table__body-wrapper.is-scrolling-none > table > tbody > tr > td.el-table_1_column_2 > div > a")
            for a in a_tags:
                href_parts = a['href'].split('&')
                announcement_id = href_parts[1].split('=')[1]
                announcement_time = href_parts[2].split('=')[1]
                pdf_url = f"http://static.cninfo.com.cn/finalpage/{announcement_time}/{announcement_id}.PDF"
                sec_name_span = a.select_one("span > span > span.secNameSuper")
                if sec_name_span:
                    file_name = sec_name_span.get('title').replace(":", "")
                    pdf_file_name = f"{file_name}.PDF"
                else:
                    pdf_file_name = f"{announcement_id}.PDF"
                all_links.append((pdf_url, pdf_file_name))

        # 检查是否存在下一页按钮
        try:
            next_button = WebDriverWait(driver, 10).until(
                EC.element_to_be_clickable((By.CLASS_NAME, 'btn-next'))
            )
        except TimeoutException:
            break

        # 如果下一页按钮存在,模拟点击,并增加点击计数器
        if next_button:
            next_button.click()
            click_counter += 1
            time.sleep(5)
        else:
            break

    # 关闭WebDriver
    driver.quit()

    # 创建新的保存目录
    new_save_dir = os.path.join(save_dir, 'new')
    os.makedirs(new_save_dir, exist_ok=True)

    # 下载PDF文件
    for link, pdf_file_name in all_links:
        # 清理文件名,移除特殊字符和大写字母A或B
        clean_file_name = "".join(char for char in pdf_file_name if char.isalnum() or char in ('.', '_'))
        clean_file_name = clean_file_name.replace('A', '').replace('B', '')
        pdf_file_path = os.path.join(new_save_dir, clean_file_name)

        # 检查临时目录中是否已存在该文件
        temp_file_path = os.path.join(temp_dir, clean_file_name)
        if not os.path.exists(temp_file_path):
            print(f"Downloading {link}")
            try:
                response = requests.get(link, stream=True)
                if response.status_code == 200:
                    with open(pdf_file_path, 'wb') as f:
                        for chunk in response.iter_content(chunk_size=8192):
                            f.write(chunk)
                    # 等待1秒钟再继续下载
                    time.sleep(1)

            except requests.exceptions.RequestException as e:
                print(f"An error occurred: {e}")

    print("Download completed.")

# 调用函数,指定不需要点击翻页就开始下载链接,且只点击一次翻页按钮(实际上不点击)
download_pdfs_after_n_pages(0, 1, 'http://www.cninfo.com.cn/new/fulltextSearch?notautosubmit=&keyWord=%E5%8F%98%E6%9B%B4%E4%BC%9A%E8%AE%A1%E5%B8%88%E4%BA%8B%E5%8A%A1%E6%89%80', r'C:\temp\123\pdf\', r'C:\temp\123\pdf\old\')

运行效果如下,自动翻页去获取dom:

将pdf下载到设定的文件夹下

2,开始将pdf转换成txt文件,代码如下:

import os
import PyPDF2

def process_pdfs_in_folder(pdf_folder_path, output_folder_path):
    # 确保输出文件夹存在
    if not os.path.exists(output_folder_path):
        os.makedirs(output_folder_path)

    # 遍历文件夹中的所有PDF文件
    for file_name in os.listdir(pdf_folder_path):
        if file_name.lower().endswith('.pdf'):
            pdf_file_path = os.path.join(pdf_folder_path, file_name)
            # 获取PDF文件名(不带扩展名)
            pdf_file_name = os.path.splitext(file_name)[0]

            try:
                # 打开PDF文件
                with open(pdf_file_path, 'rb') as file:
                    reader = PyPDF2.PdfReader(file)
                    text = ""

                    # 遍历PDF中的每一页
                    for page in reader.pages:
                        text += page.extract_text()

                # 去掉空格和回车
                text = text.replace(" ", "").replace("\n", "")

                # 将提取的文本保存到文本文件
                output_file_path = os.path.join(output_folder_path, f"{pdf_file_name}.txt")
                with open(output_file_path, 'w', encoding='utf-8') as file:
                    file.write(text)
            except PyPDF2.errors.PdfReadError as e:
                print(f"Error processing file {pdf_file_path}: {e}")

# 调用方法
pdf_folder = r'C:\temp\123\pdf\'  # 替换为PDF文件所在的文件夹路径
output_text_folder = r'C:\temp\123\txt'  # 输出文本文件的文件夹路径
process_pdfs_in_folder(pdf_folder, output_text_folder)

运行后将相应的pdf文件变成了txt文件:

3,利用python读取txt文本的内容,将文本内容发送给大语言模型,让大语言模型分析文字内容,输出相应的json格式的数据,将json数据写入到excel中,代码如下:

我这里用的是零一万物的api,目前开发者申请送60元调用额度,这个调用方法和chatgpt一样的代码,只需要换 key和模型名称就行了,然后,prompt可以要求大模型按照需求输出json格式的数据,我的prompt是这样的。

“请你根据我提供给你的文字,不用其他废话,只需要从我给的文字中提取4个字段,1,这个公告的证券代码,2这个公告的证券名称,3,这个公告聘任的2024年的会计师事务所的名称。,4,2024年聘任的会计师事务所的审计费用。将这4个字段生成json格式给我。回答只需要json格式的数据,如果没找到值就为null,其他不用废话。严格按照这下面4个字段返回数据,'证券代码', '证券名称','会计师事务所名称','审计费用'。”

import pandas as pd
import os
import json
import time
from openai import OpenAI

# 设置延迟时间,单位为秒
delay_time = 2  # 等待3秒

def chat_with_kimi(user_input):
    client = OpenAI(
        api_key="api key",
        base_url="https://api.lingyiwanwu.com/v1",
    )
    try:
        completion = client.chat.completions.create(
            model="yi-34b-chat-0205", #模型名称
            messages=[
                {"role": "system", "content": "请你根据我提供给你的文字,不用其他废话,只需要从我给的文字中提取4个字段,1,这个公告的证券代码,2这个公告的证券名称,3,这个公告聘任的2024年的会计师事务所的名称。,4,2024年聘任的会计师事务所的审计费用。将这4个字段生成json格式给我。回答只需要json格式的数据,如果没找到值就为null,其他不用废话。严格按照这下面4个字段返回数据,'证券代码', '证券名称','会计师事务所名称','审计费用'。"},
                {"role": "user", "content": user_input}
            ],
            temperature=0.3,
        )
        response = completion.choices[0].message.content
        print(f"Received response: {response}")
        time.sleep(delay_time)
        return response
    except Exception as e:
        if "Rate limit reached" in str(e):
            print("Rate limit reached. Waiting for 30 seconds before retrying.")
            time.sleep(30)  # 增加等待时间以避免频繁的API调用
            return chat_with_kimi(user_input)
        else:
            print(f"Error during API call: {e}")
            return None

# 遍历指定文件夹下的txt文件
for filename in os.listdir('C:/temp/123/txt'):
    if os.path.splitext(filename)[1].lower() == '.txt':
        try:
            with open(os.path.join('C:/temp/123/txt', filename), 'r', encoding='utf-8') as file:
                user_input = file.read()
            print(f"Processing file: {filename}")

            # 运行聊天函数获取JSON数据
            response = chat_with_kimi(user_input)
            if response is None:
                continue  # 如果API调用失败,则跳过当前文件

            # 尝试解析JSON数据
            try:
                # 移除响应中的反引号
                response_cleaned = response.replace('```json', '').replace('```', '')
                json_data = json.loads(response_cleaned)
                print(f"JSON data extracted: {json_data}")
                # 将JSON数据转换为DataFrame
                df = pd.DataFrame([json_data])

                # 检查文件是否存在
                if os.path.exists('b.xlsx'):
                    # 如果文件存在,读取现有数据
                    existing_df = pd.read_excel('b.xlsx')
                    # 将新数据追加到现有数据
                    df = pd.concat([existing_df, df], ignore_index=True)

                # 将DataFrame写入Excel文件
                df.to_excel('b.xlsx', sheet_name='sheet1', index=False)
                print(f"Data saved to b.xlsx")
            except json.JSONDecodeError:
                print("Error decoding JSON from response. Skipping this file.")

            # 删除已处理的txt文件
            os.remove(os.path.join('C:/temp/123/txt', filename))
            print(f"File {filename} has been deleted.")
        except Exception as e:  # 捕获所有可能的文件处理错误
            print(f"Error processing file {filename}: {e}")

print("Processing complete.")

运行后,就在运行的目录下生成了一个b.xlsx文件,打开文件就可以看到如下数据

我感觉用这个方法,可以分析上市公司公布的减持或者预增公告,然后让大语言模型去分析这些公告,给出一些投资建议,今天分享就是这些,希望能帮到有需要的朋友们。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1609429.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ProgressFlowmon的confluence接口存在任意命令执行漏洞(CVE-2024-2389)

声明&#xff1a; 本文仅用于技术交流&#xff0c;请勿用于非法用途 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任。 简介 ProgressFlowmon是一整套用于网络映射、应用程序性能…

2024年学浪的缓存怎么导出来

在自我成长的道路上&#xff0c;越来越多的朋友选择通过精选课程来提升自己。然而&#xff0c;面对那些服务期限有限的课程&#xff0c;怎样才能把握住知识的光芒&#xff0c;让它照亮未来的每一个角落&#xff1f;本文就教大家如何利用工具下载学浪app平台的课程 工具我已经打…

Java对象克隆-浅拷贝与深拷贝

目录 1、对象的克隆 1.1 对象的浅拷贝 1.2 对象深拷贝 1、对象的克隆 1.1 对象的浅拷贝 在实际编程过程中&#xff0c;我们常常要遇到这种情况&#xff1a;有一个对象A&#xff0c;在某一时刻A中已经包含了一些有效值&#xff0c;此时可能会需要一个和A完全相同新对象B&am…

PHP定时任务框架taskPHP3.0学习记录4宝塔面板bash定时任务(轮询指定json文件字段后确定是否执行、环境部署、执行日志、文件权限)

一 需求说明 宝塔面板中,读取指定 /www/wwwroot/lockdata/cron/webapp.json文件&#xff1b;配置定时任务脚本task.sh&#xff1b;当读取webapp.json中&#xff0c;如果cron_task1&#xff0c;则执行任务php start.php start命令行&#xff1b;完成命令后&#xff0c;执行cron…

AJAX——图书管理案例

1.渲染列表 自己的图书数据&#xff1a;给自己起个外号&#xff0c;并告诉服务器&#xff0c;默认会有三本书&#xff0c;基于这三本书做数据的增删改查。 // 目标1&#xff1a;渲染图书列表 // 1.1 获取数据 // 1.2 渲染数据const creator 哈哈 // 封装-获取并渲染图书列表函…

使用共振峰提取元音因素/从声音生成口型动画

视频效果 我前段时间研究了下从声音提取共振峰的方法。今天测试了下实际效果。 我使用一段33秒的女声视频&#xff0c;提取原因后使用静态视位图序列生成了一个视频&#xff0c;效果如下&#xff1a; b站视频&#xff1a;https://www.bilibili.com/video/BV1JD421H7m9/?vd_s…

前端开发与html学习笔记

一、前端开发概述 前端开发&#xff1a;也叫做web前端开发&#xff0c;它指的是基于web的互联网产品的页面(也可叫界面)开发及功能开发互联网产品&#xff1a;指网站为满足用户需求而创建的用于运营的功能及服务&#xff0c;百度搜索、淘宝、QQ、微博、网易邮箱等都是互联网产…

Postman调用OpenApi接口

首先你需要科学上网。。。。。 请求方式&#xff1a;post 请求地址&#xff1a;https://api.openai.com/v1/chat/completions 请求头&#xff1a; Authorization : Bearer key Content-Type : application/json Body : { "messages": [{ "role": &quo…

基于SSM+Jsp+Mysql的房屋租赁系统

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…

【C++打怪之路】-- C++开篇

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;C打怪之路&#xff0c;python从入门到精通&#xff0c;魔法指针&#xff0c;进阶C&#xff0c;C语言&#xff0c;C语言题集&#xff0c;C语言实现游戏&#x1f448; 希望得到您的订阅和支持~ &…

得物sign参数逆向分析与Python算法还原

文章目录 1. 写在前面2. 接口分析3. 断点分析4. Python算法还原 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚…

C++修炼之路之继承<二>

目录 一&#xff1a;子类的六大默认成员函数 二&#xff1a;继承与友元 三&#xff1a;继承与静态成员 四&#xff1a;复杂的继承关系菱形继承菱形虚拟继承 1.单继承 2.多继承 3.菱形继承&#xff1b;一种特殊的多继承 4.菱形虚拟继承 5.虚拟继承解决数据冗余和二…

Spectre-v1 简介以及对应解决措施

文章目录 前言一、Variant 1: Exploiting Conditional Branches.二、 BACKGROUND2.1 Out-of-order Execution2.2 Speculative Execution2.3 Branch Prediction2.4 The Memory Hierarchy2.5 Microarchitectural Side-Channel Attacks2.6 Return-Oriented Programming 三、 ATTAC…

阿里云OSS 存储对象的注册与使用

目录 一、什么是阿里云OSS 二、 点击免费试用 2.1 选择第一个&#xff0c;点击免费试用 ​编辑 2.2 登录管理控制台 2.3 进入Bucket 2.4、在阿里云网站上的个人中心配置Accesskey,查询accessKeyId和accessKeySecret。 2.5、进入AccssKey管理页面应该会出现下图提示&…

前端从零到一搭建脚手架并发布到npm

这里写自定义目录标题 一、为什么需要脚手架&#xff1f;二、前置-第三方工具的使用1. 创建demo并运行-4步新建文件夹 zyfcli&#xff0c;并初始化npm init -y配置入口文件 2.commander-命令行指令3. chalk-命令行美化工具4. inquirer-命令行交互工具5. figlet-艺术字6. ora-lo…

QT跨平台读写Excel

QT跨平台读写Excel 背景Excel工具CMakeLists.txt工程目录 背景 开发框架QT&#xff0c;makefile构建工具CMake&#xff0c;编译器MinGW Excel工具 考虑跨平台则不能使用针对微软COM组件的QAxObject来读写Excel&#xff0c;因此使用开源QtXlsx。 这里是将QXlsx当做源码嵌入使…

门禁管理系统服务器如何内网映射让外网访问?

禁管理系统整体解决方案,可实现请假出入联动、门状态监控、电子地图、非法闯入报警、远程开门、红外防夹、智能统计等功能&#xff0c;应用非常广泛。 如果门禁管理系统部署在没有公网IP的本地服务器上&#xff0c;如何设置&#xff0c;能让外网互联网上也能登录访问内部的管理…

亚马逊云科技AWS CloudUp for Her送亚马逊认证考试50%优惠券活动

最近总有小伙伴问小李哥&#xff0c;有没有送AWS考试50%优惠券的活动&#xff1f;这次送云从业者(cloud practitioner)、助理级架构师(SAA)考试50%优惠券活动就来了&#xff01; 本次活动叫AWS CloudUp for Her&#xff0c;完成免费在线培训课程即可获得AWS证书考试50%折扣券&a…

ZooKeeper设置监听器

ZooKeeper设置监听器&#xff0c;通过getData()/getChildern()/xists()方法。 步骤&#xff1a; 1.创建监听器&#xff1a;创建一个实现Watcher接口的类&#xff0c;实现process()方法。这个方法会在ZooKeeper向客户端发送一个Watcher事件通知的时候被调用。 2.注册监听器&…

Servlet第四篇【request对象常用方法、应用】

什么是HttpServletRequest HttpServletRequest对象代表客户端的请求&#xff0c;当客户端通过HTTP协议访问服务器时&#xff0c;HTTP请求头中的所有信息都封装在这个对象中&#xff0c;开发人员通过这个对象的方法&#xff0c;可以获得客户这些信息。 简单来说&#xff0c;要得…