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

折腾了几天,通过从巨潮信息网上获取上市公司的报告,然后实现调用大语言模型的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文件,打开文件就可以看到如下数据

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vuex和pinia转态管理工具介绍

文章目录 一、介绍二、使用1、pinia使用2、Vuex使用 一、介绍 相同点&#xff1a; 都是Vue.js的状态管理工具 不同点&#xff1a; 区别PiniaVuex支持Vue2和Vue3都支持Vue3写法需要额外配置Mutation只有 state, getter 和 action&#xff0c;无Mutationaction异步、Mutation …

埋点,自己写插件,自己写的按钮埋点,掘金同款投递简历

20分钟掌握 Vite 插件开发 - 掘金 vite的生命周期啥的 1.浏览器的控制台输出有样式的字 // const randomLetterPlugin ()>{ // const letters [wwwwwww,000000000000,888888888888]; // //随机获取一个字符并打印 // const printRandomLetter ()>{ // …

如何更好的管理个人财务?使用极空间部署私有记账系统Firefly III

如何更好的管理个人财务&#xff1f;使用极空间部署私有记账系统Firefly III 哈喽小伙伴们好&#xff0c;我是Stark-C~ 不知道屏幕前的各位“富哥”日常生活中是怎么管理自己巨额财富的&#xff0c;反正对于像我这样年薪过千的摸鱼族来说&#xff0c;请一个专业的理财顾问多多…

电子签名在人力资源中的应用:让HR工作更高效

人力资源&#xff08;HR&#xff09;行业是电子签领域的重要应用之一&#xff0c;它可以在以下场景中使用电子签&#xff1a; 1. 在招聘流程中&#xff0c;HR部门可以利用电子签名工具来完成与招聘候选人之间的任何文件签署操作。例如&#xff0c;维护人才库数据库、简历、面试…

世界读书日 | 开发者必读书单重磅来袭,华为云DTSE专家天团力荐

春色恰如许&#xff0c;读书正当时。 读书&#xff0c;就像解锁一把神秘钥匙&#xff0c;为开发者洞开新世界的大门&#xff0c;赋予他们破译复杂难题的能力、挑战未知领域的勇气。书页翻动间&#xff0c;开发者得以站在巨人的肩膀上&#xff0c;汲取前人经验&#xff0c;积蓄…

RANSAC 配准算法

RANSAC 配准算法 1. 简介2. RANSAC步骤3. RANSAC原理4. RANSAC的优缺点5. 代码实现6. 参考 1. 简介 先讲一下背景吧。 点云配准&#xff08;Point Cloud Registration&#xff09;指的是输入两幅点云 (source 和 target) &#xff0c;输出一个变换使得变换后的source和target…

管理 Python 项目的艺术:在 PyCharm 中使用虚拟环境(以BPnP为例)

在 PyCharm 中使用虚拟环境对于 Python 项目开发具有多方面的重要作用&#xff0c;这些作用体现在提升项目管理的效率、保障代码的可运行性以及维护项目的长期稳定性等方面。以下是使用虚拟环境的几个关键好处&#xff1a; 1. 依赖管理和隔离 虚拟环境允许每个项目拥有…

深度相机(3D相机)

传统的RGB彩色相机称为2D相机&#xff0c; 只能得到2D的图像信息&#xff0c; 无法得到物体与相机的距离信息&#xff0c;也就是深度信息。 顾名思义&#xff0c; 深度相机除了获取2D信息&#xff0c;还能得到深度信息&#xff0c;也叫RGBD相机&#xff0c; 或3D相机。 顺便提…

CSS介绍及三种应用方式[内联,内嵌,外链]元素及实例讲解

css介绍 CSS&#xff08;Cascading Style Sheets&#xff09;是一种用于描述HTML文档外观和格式的样式表语言。CSS允许开发者和设计师将网页的呈现&#xff08;布局、颜色、字体等&#xff09;与内容&#xff08;HTML&#xff09;分离开来&#xff0c;从而使得网页的设计更加灵…

vue2+vxe-table实现表格增删改查+虚拟滚动

vue2vxe-table实现表格增删改查虚拟滚动 使用的vxe-table版本&#xff1a;v3.x (vue 2.6 长期维护版) 完整代码 <template><div><vxe-toolbar ref"xToolbar" export :refresh"{query: findList}"><template #buttons><vxe-b…

vulhub weblogic全系列靶场

目录 简介 需要使用的工具 CVE-2017-10271 0x00 漏洞产生原因 0x01 影响范围 0x02 漏洞地址 0x03 环境 0x04 漏洞复现 1. 手工 2. 漏洞利用工具 CVE-2018-2628 0x00 漏洞产生原因 0x01 影响范围 0x02 环境 0x03 漏洞复现 1.nmap扫是否是T3协议 2.漏洞检测&…

【C++】详解初始化列表,隐式类型转化,类静态成员,友元

前言 初始化列表是对构造函数内容的补充&#xff0c;小编会详细的讲解初始化列表的概念&#xff0c;特性&#xff0c;注意点。这是本篇内容的重头戏&#xff0c;小编会先提一个问题来抛砖引玉。 隐式类型转换顾名思义&#xff0c;首先它不需要主动转换&#xff0c;类似于把浮点…

抖音运营全攻略 沈阳新媒体运营培训

抖音发展趋势 数据显示&#xff0c;2023年&#xff0c;抖音日活量突破10亿。是目前最火的短视频软件。 抖音的总用户数量已超过12亿&#xff0c;日活10亿&#xff0c;人均单日使用时长超过2小时&#xff0c;这只是平均数据&#xff0c;其实大部分人刷抖音时间会超过3个小时&am…

Hive数据类型

1.基本数据类型 示例&#xff1a; -- 创建表并定义列的数据类型 CREATE TABLE data_types_example (tinyint_column TINYINT,smallint_column SMALLINT,int_column INT,bigint_column BIGINT,boolean_column BOOLEAN,float_column FLOAT,double_column DOUBLE,string_column S…

HSB矩形调色板设计和计算方法

HSB矩形调色板设计和计算方法 RGB调色板绘制较容易&#xff0c;HSB调色板较难绘制&#xff0c;前些天发文介绍了几个矩形样例的绘制方法&#xff0c;今介绍矩形的HSB调色板的设计方法和H,S,B值的计算方法&#xff0c;好东西必须与大家分享。 此文介绍HSB调色板和选色条的绘制方…

jdbc操作数据库 and 一个商品管理页面

文章目录 1. 介绍1.1 应用知识介绍1.2 项目介绍 2. 文件目录2.1 目录2.2 介绍以下&#xff08;从上到下&#xff09; 3. 相关代码3.1 DBConnection.java3.2 MysqlUtil.java3.3 AddServlet.java3.4 CommodityServlet.java3.5 DelectServlet.java3.6 SelectByIdServlet.java3.7 S…

Springboot 结合PDF上传到OSS

目录 一、首先注册阿里云OSS&#xff08;新用户免费使用3个月&#xff09; 二、步骤 2.1 将pdf模板上传到oos 2.2 这里有pdf地址,将读写权限设置为共工读 ​编辑 三、代码 3.1 pom.xml 3.2 配置文件 3.3 oss model 3.4 配置类(不需要修改) 3.5 将配置类放入ioc容器 3.…

【C++】:构造函数和析构函数

目录 前言一&#xff0c;构造函数**1.1 什么是构造函数****1.2 构造函数的特性**1.3 总结 二&#xff0c;析构函数**2.1 什么是析构函数****2.2 析构函数的特性****2.3 总结** 前言 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并…

JetBrains PhpStorm v2024.1 安装教程 (PHP集成开发IDE)

前言 PhpStorm是由JetBrains推出的一款轻量级集成开发环境&#xff0c;专为PHP开发者而设计。该软件融合了智能的HTML/CSS/JavaScript/PHP编辑器、代码质量分析工具、版本控制系统集成&#xff08;包括SVN和GIT&#xff09;、调试和测试等功能。除此之外&#xff0c;PhpStorm还…

画图的神器及必备的调色和选图工具

大学生研究生论文写作及画图的神器 前言常用的工具集合画图工具配色参考画图神器词云 最后下篇 前言 好久没有更博&#xff0c;来更一下吧。最近刚好被问到平常是用什么来画图的&#xff0c;包括会议论文&#xff0c;各种类型的PPT汇报以及项目报告等等里面的图怎么画好。所以…