@[toc]
这篇博文主要介绍通过数据挖掘技术批量下载菊草资讯网的上市公司理财公告PDF文件,并通过PDF文本解析技术分析获取到的理财公告PDF文件,从中识别潜在的机构投资者。
1. PDF文件批量下载
在金融网站数据挖掘实战这篇博文中,我们介绍了在巨潮资讯网爬取公告信息的方法,该方法可以作文本文工作的基础,并在爬取多页内容、自动筛选所需内容,爬取某段时间的数据,理财公告PDF文件自动下载等功能方面进行扩展。
1.1 爬取多页内容
之前介绍过,我们可以通过修改网页参数的方式爬取多页内容,但是这在巨潮资讯网不适用,因为进行翻页操作时,网址并没有发生变化。此时可以利用Selenium库模拟鼠标单击下图所示的“下一页”按钮,并根据公告数量来确定模拟单击的次数,每单击一次就获取一下改业的源代码,最后把获取到的各页的源代码存储到一个列表里。
模拟翻页的代码如下:
browser = webdriver.Chrome()
url = 'http://www.cninfo.com.cn/new/fulltextSearch?notautosubmit=&keyWord=理财'
browser.get(url)
time.sleep(3)
browser.find_element_by_xpath('//*[@id="fulltext-search"]/div/div[1]/div[2]/div[4]/div[2]/div/button[2]').click()
上面的代码可以实现自动翻页功能,下面需要实现控制翻页的次数,也就是获取总页数,每页显示10条公告,所以公告总数除以10可得到总
页数。
data = browser.page_source
page_pattern = '<span class="total-box" style="">约\s*(.*?)\s*条 当前显示.*?条</span>'
count = re.findall(page_pattern, data)[0]
pages = int(int(count)/10)
findall()函数返回的是一个列表,因此要想获取列表中的元素,需要使用索引。
将上面两项功能结合起来,实现每次翻页时都获取当前页面的源码,并把每一页的源码存储到data_list列表中,代码如下:
# 每次翻页时都获取当前页面的源码,并把每一页的源码存储到data_list列表中
data_list = []
data_list.append(data)
# for i in range(pages):
for i in range(3):
browser.find_element_by_xpath('//*[@id="fulltext-search"]/div/div[1]/div[2]/div[4]/div[2]/div/button[2]').click()
time.sleep(2)
data = browser.page_source
data_list.append(data)
time.sleep(1)
# 将所有源码转换成一个字符串,方便进行正则化处理
alldata = ''.join(data_list)
browser.quit()
# 提取标题、链接及日期数据
'<td rowspan="1" colspan="1" class="el-table_1_column_2 ">'
title_pattern = '<span title="" class="r-title">(.*?)</span>'
href_pattern = '<td rowspan="1" colspan="1" class="el-table_1_column_2 ">.*?href="(.*?)" data-id='
date_pattern = '<td rowspan="1" colspan="1" class="el-table_1_column_3.*?<span class="time">\s*(.*?)\s*</span>'
title = re.findall(title_pattern, alldata)
href = re.findall(href_pattern, alldata)
date = re.findall(date_pattern, alldata)
# 数据清洗
for i in range(len(title)):
title[i] = re.sub('<.*?>', '', title[i])
title[i] = title[i].strip()
date[i] = date[i].strip()
href[i] = 'http://www.cninfo.com.cn' + href[i]
href[i] = re.sub('amp;', '', href[i])
print(str(i + 1) + '.' + title[i] + ' - ' + date[i])
print(href[i])
执行结果如下:
1.焦点科技:国信证券股份有限公司关于公司使用部分超额募集资金购买理财产品的保荐意见 - 2020-02-08
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900009170&announcementId=1207297926&announcementTime=2020-02-08
2.焦点科技:关于授权使用部分超募资金购买理财产品的公告 - 2020-02-08
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900009170&announcementId=1207297929&announcementTime=2020-02-08
3.东尼电子:关于使用暂时闲置募集资金购买理财产品到期赎回的公告 - 2020-02-08
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900032656&announcementId=1207297962&announcementTime=2020-02-08
4.创源文化:关于全资子公司使用闲置募集资金购买理财产品到期赎回的公告 - 2020-02-07 17:59
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900031820&announcementId=1207298260&announcementTime=2020-02-07 17:59
5.仙乐健康:关于收回到期理财产品本金及收益的公告 - 2020-02-07 15:44
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900032360&announcementId=1207297837&announcementTime=2020-02-07 15:44
6.信诚理财28日盈:信诚理财28日盈债券型证券投资基金更新招募说明书摘要 - 2020-02-07
http://www.cninfo.com.cn/new/disclosure/detail?orgId=jjjl0000099&announcementId=1207297739&announcementTime=2020-02-07
7.信诚理财28日盈:信诚理财28日盈债券型证券投资基金基金合同 - 2020-02-07
http://www.cninfo.com.cn/new/disclosure/detail?orgId=jjjl0000099&announcementId=1207297776&announcementTime=2020-02-07
8.晨丰科技:关于使用部分闲置募集资金购买理财产品到期赎回的公告 - 2020-02-07
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900034224&announcementId=1207296602&announcementTime=2020-02-07
9.索通发展:关于使用暂时闲置募集资金进行委托理财的进展公告 - 2020-02-07
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900023754&announcementId=1207296192&announcementTime=2020-02-07
10.通达电气:关于部分理财产品到期赎回及继续使用部分闲置募集资金进行现金管理的进展公告 - 2020-02-07
http://www.cninfo.com.cn/new/disclosure/detail?orgId=gfbj0870399&announcementId=1207296227&announcementTime=2020-02-07
11.海信家电:H股公告-认购理财产品 - 2020-02-07
http://www.cninfo.com.cn/new/disclosure/detail?orgId=gssz0000921&announcementId=1207296321&announcementTime=2020-02-07
12.信诚理财28日盈:信诚理财28日盈债券型证券投资基金托管协议 - 2020-02-07
http://www.cninfo.com.cn/new/disclosure/detail?orgId=jjjl0000099&announcementId=1207297770&announcementTime=2020-02-07
13.信诚理财28日盈:信诚理财28日盈债券型证券投资基金更新招募说明书 - 2020-02-07
http://www.cninfo.com.cn/new/disclosure/detail?orgId=jjjl0000099&announcementId=1207297780&announcementTime=2020-02-07
14.ST罗顿:委托理财进展公告 - 2020-02-07
http://www.cninfo.com.cn/new/disclosure/detail?orgId=gssh0600209&announcementId=1207296091&announcementTime=2020-02-07
15.丽江旅游:收回理财产品本金及收益的公告 - 2020-02-07
http://www.cninfo.com.cn/new/disclosure/detail?orgId=gssz0002033&announcementId=1207296416&announcementTime=2020-02-07
16.海信家电:须予披露交易-认购理财产品 - 2020-02-06 23:59
http://www.cninfo.com.cn/new/disclosure/detail?orgId=gssz0000921&announcementId=1207297283&announcementTime=2020-02-06 23:59
17.唐源电气:关于使用部分闲置募集资金购买理财产品的进展公告 - 2020-02-06 16:28
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900036234&announcementId=1207296204&announcementTime=2020-02-06 16:28
18.博云新材:关于使用闲置募集资金购买理财产品到期收回的公告 - 2020-02-06 11:38
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900008207&announcementId=1207295925&announcementTime=2020-02-06 11:38
19.桃李面包:关于使用闲置自有资金购买理财产品的进展公告 - 2020-02-06
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900024533&announcementId=1207294566&announcementTime=2020-02-06
20.山东威达:关于使用闲置自有资金进行委托理财的进展公告 - 2020-02-06
http://www.cninfo.com.cn/new/disclosure/detail?orgId=gssz0002026&announcementId=1207294638&announcementTime=2020-02-06
21.卫信康:关于使用暂时闲置募集资金购买理财产品到期赎回的公告 - 2020-02-06
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900034348&announcementId=1207294749&announcementTime=2020-02-06
22.光大添天盈:关于光大保德信添天盈月度理财债券型证券投资基金实施转型的提示性公告 - 2020-02-06
http://www.cninfo.com.cn/new/disclosure/detail?orgId=jjjl0000081&announcementId=1207295962&announcementTime=2020-02-06
23.光大添天盈:光大保德信添天盈月度理财债券型证券投资基金基金份额持有人大会表决结果暨决议生效公告 - 2020-02-06
http://www.cninfo.com.cn/new/disclosure/detail?orgId=jjjl0000081&announcementId=1207296019&announcementTime=2020-02-06
24.烽火通信:关于使用部分可转换公司债券闲置募集资金进行委托理财的实施公告 - 2020-02-06
http://www.cninfo.com.cn/new/disclosure/detail?orgId=gssh0600498&announcementId=1207294598&announcementTime=2020-02-06
25.美盈森:关于使用部分暂时闲置资金购买理财产品的进展公告 - 2020-02-06
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900008616&announcementId=1207295008&announcementTime=2020-02-06
26.振华科技:关于购买银行保本理财产品(第十九次)到期的公告 - 2020-02-06
http://www.cninfo.com.cn/new/disclosure/detail?orgId=gssz0000733&announcementId=1207294992&announcementTime=2020-02-06
27.平潭发展:关于使用闲置自有资金购买理财产品的进展公告 - 2020-02-06
http://www.cninfo.com.cn/new/disclosure/detail?orgId=gssz0000592&announcementId=1207294505&announcementTime=2020-02-06
28.北京科锐:关于使用闲置自有资金进行投资理财的进展公告 - 2020-02-06
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900010388&announcementId=1207294553&announcementTime=2020-02-06
29.大元泵业:关于使用闲置募集资金购买理财产品到期回收的公告 - 2020-02-06
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900031903&announcementId=1207294569&announcementTime=2020-02-06
30.天喻信息:关于使用自有资金购买保本型理财产品的进展公告 - 2020-02-05 16:40
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900017107&announcementId=1207294663&announcementTime=2020-02-05 16:40
31.海能实业:关于使用闲置自有资金进行委托理财的进展公告 - 2020-02-05 16:03
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900030659&announcementId=1207294560&announcementTime=2020-02-05 16:03
32.移为通信:关于理财产品到期赎回及继续使用闲置募集资金和自有资金进行现金管理的公告 - 2020-02-05 15:47
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900030831&announcementId=1207294540&announcementTime=2020-02-05 15:47
33.雅化集团:关于使用部分闲置募集资金购买银行理财产品的进展公告 - 2020-02-05
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900015673&announcementId=1207292358&announcementTime=2020-02-05
34.祁连山:关于使用闲置自有资金购买保本型银行理财产品到期赎回的公告 - 2020-02-05
http://www.cninfo.com.cn/new/disclosure/detail?orgId=gssh0600720&announcementId=1207292396&announcementTime=2020-02-05
35.ST狮头:关于使用部分闲置自有资金购买理财产品的实施进展公告 - 2020-02-05
http://www.cninfo.com.cn/new/disclosure/detail?orgId=gssh0600539&announcementId=1207292400&announcementTime=2020-02-05
36.桃李面包:关于使用闲置自有资金购买理财产品到期赎回的公告 - 2020-02-05
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900024533&announcementId=1207292453&announcementTime=2020-02-05
37.绿康生化:关于使用部分闲置募集资金购买理财产品到期赎回的公告 - 2020-02-05
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900030698&announcementId=1207292508&announcementTime=2020-02-05
38.晨丰科技:关于使用部分闲置募集资金购买理财产品到期赎回的公告 - 2020-02-05
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900034224&announcementId=1207292568&announcementTime=2020-02-05
39.索通发展:关于使用暂时闲置募集资金进行委托理财的公告 - 2020-02-05
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900023754&announcementId=1207292570&announcementTime=2020-02-05
40.索通发展:独立董事关于使用暂时闲置募集资金购买保本型理财产品的独立意见 - 2020-02-05
http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900023754&announcementId=1207292573&announcementTime=2020-02-05
1.2 筛选所需内容
这里只进行简单的数据清洗,选出一定日期范围内的数据。
for i in range(len(title)):
if '2020' not in date[i]:
title[i] = ''
href[i] = ''
date[i] = ''
while '' in title:
title.remove('')
while '' in href:
href.remove('')
while '' in date:
date.remove('')
1.3 理财公告PDF文件的自动批量下载
打开刚刚获取到的公告网址,可以看到需要下载的PDF文件,如果需要实现自动现在,需要使用Selenium库模拟点击页面中的“下载”按钮。
browser = webdriver.Chrome()
url = 'http://www.cninfo.com.cn/new/disclosure/detail?orgId=9900009170&announcementId=1207297926&announcementTime=2020-02-08'
browser.get(url)
browser.find_element_by_xpath('/html/body/div[1]/div[1]/div[2]/div[1]/a[3]').click()
time.sleep(3)
通过以上代码可以实现公告的自动下载,这里要实现批量下载,只需要循环访问我们存入href中的网址即可。
for i in range(len(href)):
browser = webdriver.Chrome()
browser.get(href[i])
try:
browser.find_element_by_xpath('/html/body/div[1]/div[1]/div[2]/div[1]/a[3]').click()
time.sleep(3) # 下载需要时间,这里的sleep必不可少
print(str(i+1) + '.' + title[i] + '下载完毕')
browser.quit()
except:
print(title[i] + '不是PDF')
2. PDF文本解析
我们从网上得到的公告信息多为PDF文件,如果要更深层次的分析公告内容,需要对PDF文件进行解析,这里采用pdfplumber库(pip安装),其不仅能解析文字,还能方便地解析表格。
2.1 用pdfplumber库提取文本内容
通过pdfplumber库的exact_text()函数解析PDF文件的文本内容。
path = os.path.join('bulletin', '东尼电子:关于使用暂时闲置募集资金购买理财产品到期赎回的公告.PDF') # pdf文件路径
pdf = pdfplumber.open(path)
pages = pdf.pages # 通过pages属性获取所有页的信息,此时pages是一个列表
text_all = []
for page in pages:
text = page.extract_text()
text_all.append(text)
text_all = ''.join(text_all) # 把列表转换成字符串
print(text_all)
pdf.close()
我们可以通过extract_tables()函数获取表格信息。
path = os.path.join('bulletin', '东尼电子:关于使用暂时闲置募集资金购买理财产品到期赎回的公告.PDF') # pdf文件路径
pdf = pdfplumber.open(path)
pages = pdf.pages # 通过pages属性获取所有页的信息,此时pages是一个列表
page = pages[3] # 表格在第4页
tables = page.extract_tables() # 提取表格
table = tables[0]
获取得到的table是一个嵌套列表结构,大列表里包含多个小列表,每个小列表的内容即表格中每一行的内容,我们可以通过pandas库使显示效果更佳美观。
import pandas as pd
df = pd.DataFrame(table[1:], columns=table[0])
第一行内容为表头信息。table[1:]为表格第2行及其以下的内容。
3. PDF文本解析实战——寻找合适的理财公告
3.1 遍历文件夹里所有PDF文件
# 遍历文件夹中的素有PDF文件
file_dir = r'bulletin'
for files in os.walk(file_dir):
print(files[2]) # files[0]表示母文件夹信息,files[1]表示各个子文件夹信息,files[2]表示母文件夹和子文件夹里的各个文件信息。
获取文件名后,判断文件后缀名是否为“.PDF”,这里使用os.path.splitext()函数将文件名与扩展名分离。
file_list = []
for files in os.walk(file_dir):
for file in files[2]: # files[0]表示母文件夹信息,files[1]表示各个子文件夹信息,files[2]表示母文件夹和子文件夹里的各个文件信息。
if os.path.splitext(file)[1] == '.pdf' or os.path.splitext(file)[1] == '.PDF':
file_list.append(file_dir + '\\' + file)
3.2 批量解析每一个PDF文件
# 遍历文件夹中的素有PDF文件
file_dir = r'bulletin'
file_list = []
for files in os.walk(file_dir):
for file in files[2]: # files[0]表示母文件夹信息,files[1]表示各个子文件夹信息,files[2]表示母文件夹和子文件夹里的各个文件信息。
if os.path.splitext(file)[1] == '.pdf' or os.path.splitext(file)[1] == '.PDF':
file_list.append(file_dir + '\\' + file)
print(file_list)
for i in range(len(file_list)):
pdf = pdfplumber.open(file_list[i])
pages = pdf.pages # 通过pages属性获取所有页的信息,此时pages是一个列表
text_all = []
for page in pages:
text = page.extract_text()
text_all.append(text)
text_all = ''.join(text_all) # 把列表转换成字符串
print(text_all)
pdf.close()
3.3 将合格的PDF文件自动归档
遍历并解析完PDF文件后,便能尽心高一些深度分析了。这里以关键词筛选为例进行演示:只有当PDF文件正文里含有“自有”,“议案”,“理财”,“现金管理”这些关键词,才把这个PDF文件筛选出来并存储到一个列表里。
# 遍历文件夹中的素有PDF文件
file_dir = r'bulletin'
file_list = []
for files in os.walk(file_dir):
for file in files[2]: # files[0]表示母文件夹信息,files[1]表示各个子文件夹信息,files[2]表示母文件夹和子文件夹里的各个文件信息。
if os.path.splitext(file)[1] == '.pdf' or os.path.splitext(file)[1] == '.PDF':
file_list.append(file_dir + '\\' + file)
print(file_list)
pdfs = []
for i in range(len(file_list)):
pdf = pdfplumber.open(file_list[i])
pages = pdf.pages # 通过pages属性获取所有页的信息,此时pages是一个列表
text_all = []
for page in pages:
text = page.extract_text()
text_all.append(text)
text_all = ''.join(text_all) # 把列表转换成字符串
if ('自有' in text_all) or ('议案' in text_all) or ('理财' in text_all) or ('现金管理' in text_all):
pdfs.append(file_list[i])
print(pdfs)
# 将筛选后的pdf文件存放到新的文件夹中
for pdf_i in pdfs:
newpath = 'new_bulletin\\' + pdf_i.split('\\')[-1]
os.rename(pdf_i, newpath) # 执行文件移动操作
这里只是提供了解析pdf文本的方法,具体如何解析,以及解析的策略还需要大家自己来提供。