企查查批量导出后数据整理——以股东信息为例,并上传至数据库。(附完整代码python)

关于企查查处理数据的问题都可以私信我哦。 还可以整理分支机构、主要人员、投资信息、附属子公司等。

1、批量提取数据

由于需要区分工商登记数据还是最新公示数据,所以选择将这两部分数据分开存放,当然也可以放在一起。(本文认为最新公示的企业属于上市企业,但是也存在一些未上市却即将上市的企业,工商登记属于未上市企业)。

源数据截图示例:

代码:

import os
import re
import pandas as pd
folder_path = r"C:\股东信息解压"
latest_announcement_data = []
business_registration_data = []
for filename in os.listdir(folder_path):
    if filename.endswith(".csv"):
        file_path = os.path.join(folder_path, filename)
        df = pd.read_csv(file_path, sep='\t', engine='python', skip_blank_lines=True)
        df=df.astype(str)
        df = df.applymap(lambda x: x.replace('=', '') if isinstance(x, str) else x)
        df = df.applymap(lambda x: x.replace(',', '') if isinstance(x, str) else x) 
        df = df.applymap(lambda x: x.replace('""', '"') if isinstance(x, str) else x) 
        df = df.applymap(lambda x: x.strip() if isinstance(x, str) else x)
        df = df[df['查企业  上企查查 , 联系电话:400-928-2212,'] != '" "']    
        current_state = None
        current_company = None
                for index, row in df.iterrows():
            line = row[df.columns[0]]
            
            company_match = re.match(r'"(.*)(公司|厂|大学|研究)(.*)', line)
            if company_match:
                current_company = company_match.group(1)+company_match.group(2)
            
            if line.startswith('"股东信息-最新公示'):
                current_state = "latest_announcement"
                continue
            elif line.startswith('"股东信息-工商登记'):
                current_state = "business_registration"
                continue
            
            if current_state == "latest_announcement":
                if line.startswith('"股东信息-工商登记'):
                    current_state = None
                    continue
                latest_announcement_data.append([current_company] + row.tolist())
            elif current_state == "business_registration":
                if line.startswith('"(.*)(公司|厂|大学|研究)(.*)') or pd.isnull(line):
                    current_state = None
                    continue
                business_registration_data.append([current_company] + row.tolist())

latest_announcement_df = pd.DataFrame(latest_announcement_data, columns=["企业名称"] + df.columns.tolist())
business_registration_df = pd.DataFrame(business_registration_data, columns=["企业名称"] + df.columns.tolist())

latest_announcement_df.to_csv("ods钛材上市公司股东表.csv", index=False, encoding='utf-8')
business_registration_df.to_csv("ods钛材未上市公司股东表.csv", index=False, encoding='utf-8')

由于企查查上的企业数据时间线较长,关于最新公示部分的数据列有两种形式,本文选择提取年代较新的部分列,列开头为:序号 股东名称 持股比例 XXX。另一个数据信息较久远的列开头为:序号 股东名称 股份类型XXX,弃用。

import pandas as pd

df1 = pd.read_csv("ods钛材上市公司股东表.csv")

current_state = None
filtered_data = []
preserve_data = False

for index, row in df1.iterrows():
    line = row[df1.columns[1]]

    if line.startswith('"序号"股东名称"持股比例"'):
        current_state = "持股比例"
        preserve_data = True
        filtered_data.append(row)
    elif line.startswith('"序号"股东名称"股份类型"'):
        current_state = "股份类型"
        preserve_data = False
    elif not line:  
        preserve_data = False
    
    if preserve_data:
        filtered_data.append(row)

df_filtered = pd.DataFrame(filtered_data, columns=df1.columns)
df_filtered.to_csv("ods钛材上市公司股东表1.csv", index=False)

2、数据处理部分

这部分主要是对列进行拆除,并统一数据格式。提醒:企查查导出的数据列名随时都存在变化的可能,可能会新增列也可能改变列名,需要对导出的数据进行一个检查。

import pandas as pd

# 读取两个CSV文件为DataFrame
df1 = pd.read_csv("ods储能上市公司股东表1.csv")
df2 = pd.read_csv("ods储能未上市公司股东表.csv")

df1 = df1.applymap(lambda x: x.replace('"', '##') if isinstance(x, str) else x) 
df2 = df2.applymap(lambda x: x.replace('"', '##') if isinstance(x, str) else x) 

for i in range(1, len(df1)):
    if df1.loc[i, '企业名称'][0].isdigit():
        df1.loc[i, '企业名称'] = df1.loc[i - 1, '企业名称']

for i in range(1, len(df2)):
    if df2.loc[i, '企业名称'][0].isdigit():
        df2.loc[i, '企业名称'] = df2.loc[i - 1, '企业名称']

pattern = r'^##\d+'
df1 = df1[df1['查企业  上企查查 , 联系电话:400-928-2212,'].str.match(pattern)]
df2 = df2[df2['查企业  上企查查 , 联系电话:400-928-2212,'].str.match(pattern)]

split_columns1 = df1['查企业  上企查查 , 联系电话:400-928-2212,'].str.split('##', expand=True)
df1 = pd.concat([df1, split_columns1], axis=1)
df1.rename(columns={0: '空值', 1: '序号', 2: '股东名称', 3: '持股比例', 4: '认缴出资额', 5: '认缴出资日期', 6: '实缴出资额', 7: '实缴出资日期', 8: '最终受益股份',9:'关联产品/机构'}, inplace=True)
df1.drop('查企业  上企查查 , 联系电话:400-928-2212,', axis=1, inplace=True)
df1['持股比例'] = df1['持股比例'].str.replace(r'^(0%)$', '-', regex=True)
df1['最终受益股份'] = df1['最终受益股份'].str.replace(r'^0%$', '-', regex=True)
df1 = df1[['企业名称', '股东名称', '持股比例', '最终受益股份', '关联产品/机构']]
df1 = df1.dropna(subset=['股东名称'])
df1.drop_duplicates()
df1.reset_index(drop=True, inplace=True)


split_columns = df2['查企业  上企查查 , 联系电话:400-928-2212,'].str.split('##',expand=True)
df2 = pd.concat([df2, split_columns], axis=1)
df2.rename(columns={0: '空值', 1: '序号', 2: '股东名称', 3: '持股比例', 4: '认缴出资额', 5: '认缴出资日期', 6: '实缴出资额', 7: '实缴出资日期', 8: '最终受益股份',9:'首次持股日期',10:'关联产品/机构'}, inplace=True)
df2.drop('查企业  上企查查 , 联系电话:400-928-2212,', axis=1, inplace=True)
df2['认缴出资日期'] = df2['认缴出资日期'].str.replace('最新:', '')
df2['实缴出资日期'] = df2['实缴出资日期'].str.replace('最新:', '')
df2['持股比例'] = df2['持股比例'].str.replace(r'^(0%)$', '-', regex=True)
df2['最终受益股份'] = df2['最终受益股份'].str.replace(r'^(0%)$', '-', regex=True)
df2 = df2[['企业名称', '股东名称', '持股比例', '认缴出资额', '认缴出资日期', '实缴出资额', '实缴出资日期', '最终受益股份', '首次持股日期', '关联产品/机构']]
df2 = df2[(df2['股东名称'].notna()) & ~df2['股东名称'].str.match(r'\d{4}年\d{1,2}月\d{1,2}日')]

df2.drop_duplicates()
df2.reset_index(drop=True, inplace=True)

df1.to_csv("ods储能上市公司股东表2.csv", index=False,encoding='utf-8')
df2.to_csv("ods储能未上市公司股东表2.csv", index=False,encoding='utf-8')

3、上传mysql数据库

功能:删除数据库中的原有数据,再进行导入。并加上导入进度条,打印上传时间。提醒:我的数据库中有一个自增列,列名为:id。但是若多次导入数据不设置自增列,导入的数据可能id不为1开始。这里选择脚本控制。

import pandas as pd
from sqlalchemy import create_engine
import time
from tqdm import tqdm

csv_file_path = r"D:\ods未上市公司股东表.csv"
df = pd.read_csv(csv_file_path)

column_mapping = {
    '企业名称': 'enterprise_name',
    '股东名称': 'shareholder', 
    '持股比例': 'shareholding_ratio', 
    '认缴出资额':'subscribed_capital_contribution',
    '认缴出资日期': 'subscribed_date',
    '实缴出资额':'paid_in_capital_contribution',
    '实缴出资日期': 'paid_in_date',
    '最终受益股份':'ultimate_beneficiary_shares',
    '首次持股日期': 'initial_shareholding_in_date', 
    '关联产品/机构': 'Related_products_or_institutions'
}

df_mapped = df.rename(columns=column_mapping)

engine = create_engine(
    "mysql+mysqlconnector://username:password@host/数据库名"
)

start_time = time.time()

try:
    table_name = "数据库中的表名"
    total_rows = len(df_mapped)
    
    with engine.connect() as connection:
        # 设置自增起始值 increment
        set_auto_increment_query = f"ALTER TABLE {table_name} AUTO_INCREMENT = 1"
        connection.execute(set_auto_increment_query)
        
        # 删除旧数据
        delete_query = f"DELETE FROM {table_name}"
        connection.execute(delete_query)

    with tqdm(total=total_rows, desc="Uploading data") as pbar:
        df_mapped.to_sql(table_name, con=engine, if_exists="append", index=False, chunksize=10000)
        
        pbar.update(len(df_mapped))
        
    print("Data uploaded successfully.")
except Exception as e:
    print("Error uploading data:", str(e))
finally:
    engine.dispose()

end_time = time.time()
elapsed_time = end_time - start_time
print(f"Total time elapsed: {elapsed_time:.2f} seconds")

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值