叶贞希的实验报告

代码


# 一.爬取pdf下载地址
import time
import pandas as pd
import csv

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from bs4 import BeautifulSoup
from urllib.parse import urljoin  # 用于拼接 URL

browser = webdriver.Edge()
browser.get('https://www.szse.cn/disclosure/listed/fixed/index.html')

# 报告类型选择
# 选择年度报告类型
time.sleep(10)
element = browser.find_element(By.CSS_SELECTOR, "#select_gonggao .glyphicon").click()
time.sleep(10)
element = browser.find_element(By.LINK_TEXT, "年度报告").click()
time.sleep(5)

firm = [
    ['000068', '华控赛格'],
    ['000710', '贝瑞基因'],
    ['000779', '甘咨询'],
    ['002178', '延华智能'],
    ['002776', 'ST柏龙'],
    ['002883', '中设股份'],
    ['002949', '华阳国际'],
    ['002967', '广电计量'],
    ['003008', '开普检测'],
    ['003013', '地铁设计'],
]

# 自动控制浏览器选择所取的公司
# 手动一个一个获取
for i in range(len(firm)):
    name = firm[i][1]
    code = firm[i][0]
    f = open('inner_HTML_%s.html' % name, 'w', encoding='utf-8')
    element = browser.find_element(By.ID, "input_code").click()
    time.sleep(5)
    element = browser.find_element(By.ID, 'input_code').send_keys('%s' % code)
    time.sleep(5)
    element = browser.find_element(By.ID, "input_code").send_keys(Keys.ENTER)
    element = browser.find_element(By.ID, 'disclosure-table')
    time.sleep(5)
    innerHTML = element.get_attribute('innerHTML')
    f.write(innerHTML)
    time.sleep(5)
    f.close()
    element = browser.find_element(By.CSS_SELECTOR, ".selected-item:nth-child(2) > .icon-remove").click()
    time.sleep(5)

browser.quit()

time.sleep(10)
# 将获取的公司年报地址存入csv文件中
for i in range(len(firm)):
    name = firm[i][1]
    f = open('inner_HTML_%s.html' % name, encoding='utf-8')
    t = f.read()
    soup = BeautifulSoup(t, 'html.parser')
    # print(type(t))
    comments = soup.find_all('div', {'class': 'text-title-box'})
    data_list = []
    for item in comments:
        content = item.find('span', {'class': 'pull-left title-text ellipsis'})
        # print(content.text)
        if content.text[-5:] != f"年年度报告":
            continue
        print(content.text)
        # 找到报告的下载地址和名称
        link = item.find("a", {"attachformat": "pdf"})
        url = urljoin("https://www.szse.cn", link.get("href"))
        name = link.find("span", {"class": "title-text"}).get("title")

        # 将报告名和下载地址追加到 CSV 文件中
        with open(f"{firm[i][1]}.csv", "a", newline="", encoding="utf-8") as f:
            writer = csv.writer(f)
            writer.writerow([name, url])
    f.close()


# 二.下载年度报告pdf
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
import time

for i in range(len(firm)):
    name = firm[i][1]
    df = pd.read_csv(f'{name}.csv')
    urls = df.iloc[:, 1].tolist()
    for j in range(len(urls)):
        ann_url = urls[j]
        # 创建 WebDriver 对象
        driver = webdriver.Chrome()

        # 打开深交所网站并进入目标页面
        driver.get(ann_url)

        # 等待下载按钮可单击
        download_btn = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.CSS_SELECTOR, "a#annouceDownloadBtn[href*='info/download']")))

        # 点击 "公告下载"
        download_btn.click()

        # 等待下载并关闭浏览器
        time.sleep(10)
        driver.quit()

# 三.在pdf中获取数据
import PyPDF2
import pandas as pd
import os

firm = [
    ['000068', '华控赛格'],
    ['000710', '贝瑞基因'],
    ['000779', '甘咨询'],
    ['002178', '延华智能'],
    ['002776', 'ST柏龙'],
    ['002883', '中设股份'],
    ['002949', '华阳国际'],
    ['002967', '广电计量'],
    ['003008', '开普检测'],
    ['003013', '地铁设计'],
]
# 打开PDF文件
for i in range(10):
    name = firm[i][1]
    for j in range(2012, 2023):

        file_path = f'{name}:{j}年年度报告.PDF'
        print(file_path)
        if os.path.exists(file_path):
            with open(file_path, 'rb') as pdf_file:
                # 创建文件阅读器
                pdf_reader = PyPDF2.PdfFileReader(pdf_file)

                # 获取PDF中文本内容(一般情况下,表格一般在最后一页)
                # page_text = pdf_reader.getPage(pdf_reader.getNumPages() - 1).extractText()

                for page_num in range(pdf_reader.getNumPages() - 5, 0, -1):
                    try:
                        page_text = pdf_reader.getPage(page_num).extractText()
                        # 成功提取到文本,跳出循环
                        break
                    except:
                        print(f'第{page_num}页文本提取失败,尝试上一页')
                        continue

                # 把文本内容分割成行
                lines = page_text.split('\n')

                # 提取表格数据
                data = []
                for line in lines:
                    # 通过判断年份来确定新的一行开始
                    if line.strip().isdigit():
                        year = line.strip()
                        continue
                    # 判断行是否包含股票代码,以此判断是否属于表格数据
                    # if 'SH' in line or 'SZ' in line or '营业收入' or line or '基本每股收益' in line:
                    if 'SH' in line or 'SZ' in line or '营业收入' in line or '基本每股收益' in line:
                        # 分割行中的数据,并在末尾添加年份
                        row_data = line.split()
                        year = j
                        year = year if year else j
                        row_data.append(year)
                        data.append(row_data)

                # 创建DataFrame,并设置列名
                df = pd.DataFrame(data, columns=['股票代码', '股票简称', '办公地址', '公司网址', '营业收入', '基本每股收益', '年份'])
                # df = pd.DataFrame(data)
                # 将DataFrame数据写入CSV文件
                df.to_csv('公司.csv', index=False, encoding='utf-8')

        else:
            print(f'{file_path} 不存在,跳过')
            continue



# 可视化
# 1.各个公司分开
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties

font = FontProperties(fname=r"HYPengPengCheW.ttf", size=14)

plt.rcParams["font.family"] = "sans-serif"
plt.rcParams["axes.unicode_minus"] = False

df = pd.read_csv('公司.csv', usecols=['年份', '营业收入', '基本每股收益'])

plt.figure()
plt.plot(df['年份'], df['营业收入'], 'o-', label='营业收入', linewidth=2)
plt.xticks(rotation=45, fontproperties=font)
plt.xlabel('年份', fontproperties=font)
plt.ylabel('营业收入', fontproperties=font)
plt.title('地铁设计近十年营业收入变化趋势图', fontproperties=font)
plt.legend(prop=font)
plt.show()

plt.figure()
plt.plot(df['年份'], df['基本每股收益'], 'x-', label='基本每股收益', linewidth=2)
plt.xticks(rotation=45)
plt.xlabel('年份', fontproperties=font)
plt.ylabel('基本每股收益', fontproperties=font)
plt.title('地铁设计近十年基本每股收益变化趋势图', fontproperties=font)
plt.legend(prop=font)
plt.show()


2.各个公司同一年对比
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties

font = FontProperties(fname=r"HYPengPengCheW.ttf", size=14)

plt.rcParams["font.family"] = "sans-serif"
plt.rcParams["axes.unicode_minus"] = False

df = pd.read_csv('公司.csv', usecols=['年份', '股票简称', '股票代码', '办公地址', '公司网址', '营业收入', '基本每股收益'])
# 1. 按年份制图
grouped = df.groupby(['年份'])

for name, group in grouped:
    plt.figure(figsize=(12, 6))
    plt.suptitle(f"{name}年营业收入和基本每股收益柱状图", fontproperties=font)
    plt.subplot(211)
    plt.bar(group['股票简称'], group['营业收入'], width=0.3, label='营业收入')
    plt.xticks(rotation=45, fontproperties=font)
    plt.xlabel('股票简称(股票代码)', fontproperties=font)
    plt.ylabel('营业收入', fontproperties=font)
    plt.legend(prop=font)
    plt.subplot(212)
    plt.bar(group['股票简称'], group['基本每股收益'], width=0.3, label='基本每股收益')
    plt.xticks(rotation=45, fontproperties=font)
    plt.xlabel('股票简称(股票代码)', fontproperties=font)
    plt.ylabel('基本每股收益', fontproperties=font)
    plt.legend(prop=font)
    plt.show()



# 3.所有公司所以年份绘制在同一张图-折线
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties

font = FontProperties(fname=r"HYPengPengCheW.ttf", size=14)

plt.rcParams["font.family"] = "sans-serif"
plt.rcParams["axes.unicode_minus"] = False
data = pd.read_csv('公司.csv')

# 转换为string类型
data['营业收入'] = data['营业收入'].astype(str)

# 使用.str方法去除','
data['营业收入'] = data['营业收入'].str.replace(',', '')
# 转换为string类型
data['基本每股收益'] = data['基本每股收益'].astype(str)

# 使用.str方法去除','
data['基本每股收益'] = data['基本每股收益'].str.replace(',', '')

#按年份从小到大排序
data = data.sort_values('年份')

#获取全部的股票信息
stocks = data['股票简称'].unique()
#按年份从小到大排序
data = data.sort_values('年份')

#获取全部的股票信息
stocks = data['股票简称'].unique()

fig, ax1 = plt.subplots(figsize=(12, 6))

# 绘制每个公司的营业收入
for stock in stocks:
    stock_data = data[data['股票简称'] == stock]
    # 将字符串中的逗号替换为空格,并将列类型转换为浮点数

    stock_data['营业收入'] = stock_data['营业收入'].str.replace(',', '')
    stock_data['营业收入'] = stock_data['营业收入'].str.replace(' ', '').astype(float)
    ax1.plot(stock_data['年份'], stock_data['营业收入'], label=stock)

# 添加y轴标签、图例和标题
ax1.set_xlabel('年份', fontproperties=font)
ax1.set_ylabel('营业收入', color='tab:red', fontproperties=font)
ax1.tick_params(axis='y', labelcolor='tab:red')
ax1.legend(loc='upper left', bbox_to_anchor=(1.02, 1), borderaxespad=0, prop=font)
ax1.set_title('营业收入随时间的变化趋势图', fontproperties=font)
# 显示图形
plt.show()


# 绘制每个公司的营业收入
for stock in stocks:
    stock_data = data[data['股票简称'] == stock]
    # 将字符串中的逗号替换为空格,并将列类型转换为浮点数

    stock_data['基本每股收益'] = stock_data['基本每股收益'].str.replace(',', '')
    stock_data['基本每股收益'] = stock_data['基本每股收益'].str.replace(' ', '').astype(float)
    ax1.plot(stock_data['年份'], stock_data['基本每股收益'], label=stock)

# 添加y轴标签、图例和标题
ax1.set_xlabel('年份', fontproperties=font)
ax1.set_ylabel('基本每股收益', color='tab:red', fontproperties=font)
ax1.tick_params(axis='y', labelcolor='tab:red')
ax1.legend(loc='upper left', bbox_to_anchor=(1.02, 1), borderaxespad=0, prop=font)
ax1.set_title('基本每股收益随时间的变化趋势图', fontproperties=font)
# 显示图形
plt.show()



# 4. 所有公司所有年份绘制在一张图上-柱形图
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties

font = FontProperties(fname=r"HYPengPengCheW.ttf", size=14)

plt.rcParams["font.family"] = "sans-serif"
plt.rcParams["axes.unicode_minus"] = False

df = pd.read_csv('公司.csv')  # 读取文件

# 转换为string类型
df['营业收入'] = df['营业收入'].astype(str)

# 使用.str方法去除','
df['营业收入'] = df['营业收入'].str.replace(',', '')

# 将字符串中的逗号替换为空格,并将列类型转换为浮点数
df['营业收入'] = df['营业收入'].str.replace(',', '')
df['营业收入'] = df['营业收入'].str.replace(' ', '').astype(float)
df['基本每股收益'] = df['基本每股收益'].astype(float)

# 获取不同年份的营业收入情况
year_revenue = df.pivot_table(index='年份', columns='股票简称', values='营业收入')
year_revenue.plot(kind='bar')
plt.title('营业收入对比图', fontproperties=font)
plt.xlabel('年份', fontproperties=font)
plt.ylabel('营业收入', fontproperties=font)
plt.legend(prop=font)
plt.show()

# 获取不同年份的基本每股收益情况
year_eps = df.pivot_table(index='年份', columns='股票简称', values='基本每股收益')
year_eps.plot(kind='bar')
plt.title('基本每股收益对比图', fontproperties=font)
plt.xlabel('年份', fontproperties=font)
plt.ylabel('基本每股收益', fontproperties=font)
plt.legend(prop=font)
plt.show()


每家公司的趋势图

结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图 结果截图

行业解读

专业技术服务业在国内发展几十年,发展速度一直比较缓慢,且服条企业众多,竞争比较激烈,没有形成具备绝对优势的龙头企业。目前看来,软件和信息技术服务业竞争较为充分而智慧城市的发展空间较大。数字产业化将持续引领软件、信息技术服务业的发展。营业收入分析,从图来看,这十家公司营业收入整体呈现增长趋势,除*ST柏龙公司在 2021及 2022 年营业收入有大幅度的下降。另外,甘咨询和贝瑞基因两家公司近些年营业收入比较稳定,而其他公司的同比变化幅度较大;

每股收益分析,十家公司比较来看,近几年新上市的公司,如中设股份、地铁设计、开普检测的每股收益情况较好。而华控赛格、*ST柏龙、延华智能这三家公司的每股收益连续几年呈现负值,说明公司盈利能力还需要提高。

心得体会

通过这一个学期的学习,我对Python有了更深入全面的了解。虽然之前有接触过Python,但更多停留在语法和API的层面,没有真正理解其内部的工作机制。这门课程让我对Python的运行原理有了系统的认知,老师耐心细致的讲解让我受益匪浅。

尤其是期末的项目报告,让我有机会将所学知识综合应用,虽然一开始手忙脚乱,不停地询问同学和参考前辈的作品,但最终还是制作出了一个初步的成果。在此过程中,我不仅加深了对Python的理解,也学会了如何通过图文并茂的方式展现复杂的代码和概念。我很高兴通过这门课程进一步掌握Python,同时也给我继续学习的动力和信心。

Python的世界广袤无垠,我只是初窥门径,但这精彩的学习之旅已经开始。老师悉心的教导和同学们的切磋将是我进步的阶梯,我会继续努力,在这条学习之路上不断前行。这门课程是我编程生涯的重要一步,我将持之以恒,精益求精。

总之,这是一个学期我收获颇丰,不仅在知识与技能上有所提高,更在学习态度与思维模式上有所成长。我衷心感谢老师和同学们在这个学期对我的帮助,你们是我成长的重要推手,也是我继续努力的动力源泉。这段学习体验将成为我宝贵的财富,在未来的人生旅途中不断启迪和激励我。