大数据分析的前置数据处理部分。
参考了网上的一些爬虫进行了修改,主要是增加了批量下载的功能,通过读取excel来实现批量。
需要在目录文件夹中的excel表中存放需要查询的公司代码及名称,如下图格式。
具体的实现代码:
# 导入pandas工具库
import pandas as pd
#实现系统功能
import os
#读取excel
import xlrd
#写入excel
import xlwt
#解析json
import json
#获取网页内容
import requests
#数学函数
import math
#正则表达
import re
#下载网络文件到本地
from urllib.request import urlretrieve
# 从以下url中提取所需要的上市企业数据源信息
url = "http://www.cninfo.com.cn/new/data/szse_stock.json"
ret = requests.get(url = url)
ret = ret.content
stock_list = json.loads(ret)["stockList"]
len(stock_list)
# 检查数据格式案例
stock_list[:2]
//这一段是参考代码中的,在此处应该没用,懒得删,怕出bug
def export_excel(export):
#将字典列表转换为DataFrame
pf = pd.DataFrame(export)
#指定字段顺序
order = ['orgId','category','code','pinyin','zwjc']
pf = pf[order]
#将列名替换为中文
columns_map = {
'orgId':'orgId(原始ID)',
'category':'category(股市类型)',
'code':'code(代码)',
'pinyin':'pinyin(拼音)',
'zwjc':'zwjc()'
}
pf.rename(columns = columns_map,inplace = True)
#指定生成的Excel表格名称
file_path = pd.ExcelWriter('code_list.xlsx')
#替换空单元格
pf.fillna(' ',inplace = True)
#输出
pf.to_excel(file_path,encoding = 'utf-8',index = False)
#保存表格
file_path.save()
if __name__ == '__main__':
#将分析完成的列表导出为excel表格
export_excel(stock_list)
# 提取stock_list中的code与orgId,遍历生成独立字典
code_dic = {(it['code']):it['orgId'] for it in stock_list}
print(code_dic)
len(code_dic)
//一直到这里
# 定义一个读取xls文件数据并转为列表的类
class excel_read:
# 定义一个读取函数,其中excel_path为待爬取企业清单的路径,需自定义路径
def __init__(self, excel_path=r"E:\python\***.xls", encoding='utf-8', index=0):
# 获取文本对象
self.data = xlrd.open_workbook(excel_path)
# 根据index获取某个sheet
self.table = self.data.sheets()[index]
# 获取当前sheet页面的总行数,把每一行数据作为list放到 list
self.rows = self.table.nrows
def get_data(self):
result = []
for i in range(self.rows):
# 获取每一行的数据
col = self.table.row_values(i)
print(col)
result.append(col)
print(result)
return result
# 运用函数生成待爬取企业的code_list
code_list = []
code_list.extend(excel_read().get_data())
# 1、对单个页面进行请求,并返回数据信息——通过data自定义特定企业
def get_and_download_pdf_flie(pageNum, stock, searchkey='', category='', seDate=''):
url = 'http://www.cninfo.com.cn/new/hisAnnouncement/query'
pageNum = int(pageNum)
# 定义表单数据
data = {'pageNum': pageNum,
'pageSize': 30,
'column': 'szse',
'tabName': 'fulltext',
'plate': '',
'stock': stock,
'searchkey': searchkey,
'secid': '',
'category': category,
'trade': '',
'seDate': seDate,
'sortName': '',
'sortType': '',
'isHLtitle': 'true'}
# 定义请求头
headers = {'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Connection': 'keep-alive',
'Content-Length': '181',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Host': 'www.cninfo.com.cn',
'Origin': 'http://www.cninfo.com.cn',
'Referer': 'http://www.cninfo.com.cn/new/commonUrl/pageOfSearch?url=disclosure/list/search',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36',
'X-Requested-With': 'XMLHttpRequest'}
# 提交请求
r = requests.post(url, data=data, headers=headers)
# 获取单页年报的数据,数据格式为json,解析并获取json中的年报信息
result = r.json()['announcements']
# 2.对数据信息进行提取
for i in result:
# 避免下载一些年报摘要等不需要的文件
if re.search('摘要', i['announcementTitle']):
pass
else:
title = i['announcementTitle']
# 获取公告文件名,并在下载前将公告文件名中带*号的去掉,因为文件命名规则不能带*号,否则程序会中断
secName = i['secName']
secName = secName.replace('*', '')
# 获取公司股票代码
secCode = i['secCode']
# 获取adjunctUrl,并组合生成pdf文件下载地址(分析得知巨潮资讯数据库pdf下载地址格式:http://static.cninfo.com.cn/+adjunctUrl)
adjunctUrl = i['adjunctUrl']
down_url = 'http://static.cninfo.com.cn/' + adjunctUrl
# 定义下载之后需要保存到本地的文件名
filename = f'{secCode}{secName}{title}.pdf'
# 定义文件存放地址
filepath = saving_path + '\\' + filename
# 提交下载请求
r = requests.get(down_url)
# 用response.content来写入文件信息
with open(filepath, 'wb') as f:
f.write(r.content)
# 设置进度条
print(f'{secCode}{secName}{title}下载完毕')
# 设置存储年报的文件夹,把路径改成自己的
saving_path = r'E:\python\'
# 根据code_list计算待爬企业数量
Num = len(code_list)
print(Num)
# 从code_list中根据待爬企业数量遍历提取code与orgId
for i in range(0, Num):
code = code_list[i][0]
orgId = code_dic[code]
# 定义stock
stock = '{},{}'.format(code, orgId)
print(stock)
# 定义searchkey
searchkey = ''
# 定义category
category = 'category_ndbg_szsh'
# 定义seDate
seDate = '2021-01-01~2023-11-15'
# 定义pageNum(需要通过观测,确保pageNum能够涵盖每一次遍历请求的结果页数,此处定为2页即可)
for pageNum in range(1, 3):
try:
get_and_download_pdf_flie(pageNum, stock, searchkey, category, seDate, )
except:
# 超出页数后会报错,需要跳过异常以便于继续遍历执行
pass
最终导出如下,也可根据自己的需求下载不同季度年份的报告。
后续将更新pdf文字提取和直接提取网页内数据的博客,尽量把这个项目完整地放上来吧,毕竟当时在网上查了很久删删改改,从0基础到成功地爬取数据,真的很不容易。