温馨提示: 定期 清理浏览器缓存,可以获得最佳浏览体验。
作者: 秦利宾 (厦门大学)
邮箱: qlb150@163.com
目录
目前,上市公司公告主要从巨潮网、上交所以及深交所等网站获取。爬取的步骤分为以下两步,一是获取公告地址,二是通过公告地址下载 PDF
文件。通常来说,获取公告地址比较麻烦。本文将根据 Wind
和 CSMAR
数据库的公告信息简化获取公告地址过程,并下载 PDF
文件,这里以年报为例。
首先,打开 Wind 终端,按照公司公告
->年度报告
->高级检索
的步骤检索上市公司年报信息。
其次,点击导出列表,将检索到的年报信息导出到 Excel
文件。需要注意的是,Wind
最多导出 9999
条记录。实际操作中,可以通过在检索中设置时间区间分批导出。
最后,公告标题在 Excel
中是以超链接形式存在,通过 Excel 中的函数 FORMULATEXT()
可以将超链接分解成链接和文本两部分。进一步,可以通过调用 Python
进行拆分,提取公告地址链接。
def address(str): #定义提取公告地址函数
return str.split('"')[1]
data["公告地址"] = data["公告地址"].apply(address)
打开年报地址,可以看到年报页面是由年报 PDF
超链接和年报内容两部分组成。其中,PDF
超链接可以通过 Xpath
或 正则表达式
获取。
#利用Xpath提取年报PDF链接
def pdf_url(url):
html = requests.get(url).text #获取网页源代码
tree = etree.HTML(html) #解析网页
url = tree.xpath("//div[2]/a/@href") #获取PDF链接
return "http://news.windin.com/ns/" + url[0]
data["PDF地址"] = data["公告地址"].apply(pdf_url)
#利用正则表达式提取年报PDF链接
def pdf_url(url):
html = requests.get(url).text
url = re.findall("(?<=href=).*(?=class)", html) #?<= 正则肯定式向后看 ?= 正则肯定式向前看
return "http://news.windin.com/ns/" + url[0]
data["PDF地址"] = data["公告地址"].apply(pdf_url)
根据提取到的年报 PDF 链接下载文件。
for index, row in data.iterrows():
name = row["证券代码"][:6] + "_" + row["公告日期"] + ".pdf" #文件名称
url = row["PDF地址"] #pdf地址
times = 1 #失败后,重新获取次数
while times <= 3: #3次都失败后跳出循环
try:
urlretrieve(url, filename = r"./PDF/" + name) #下载pdf
print(f"成功下载{name}!")
break
except:
times += 1
print(f"休息5秒!再试第{times}次!")
time.sleep(5)
print("成功下载所有PDF文件!")
首先,打开 CSMAR
数据库,按照市场咨询系列
->公告
->公告分类关联表和公告证券关联表
步骤,下载上市公司公告信息。其中,年报正文分类编码为 01030101
。
其次,根据公告分类关联表和公告证券关联表共同字段,合并两个表。
data1 = pd.read_excel("ANN_Classify.xlsx")[2:] #剔除前两行中文标题和单位
data2 = pd.read_excel("ANN_Security.xlsx")[2:]
data = pd.merge(data1, data2, on = ["AnnouncementID", "DeclareDate", "FullDeclareDate", "Title"])
最后,生成年报 PDF 链接,并下载。
#巨潮咨询网年报链接形式
#http://static.cninfo.com.cn/finalpage/2020-04-14/1207489969.PDF
#生成年报PDF链接
data["pdf_url"] = "http://static.cninfo.com.cn/finalpage/" + data["DeclareDate"] + "/" + data["AnnouncementID"] + ".PDF"
#根据PDF链接下载
for index, row in data.iterrows():
name = row["Symbol"] + "_" + row["DeclareDate"] + ".pdf" #文件名称
print(name)
url = row["pdf_url"] #pdf地址
times = 1 #失败后,重新获取次数
while times <= 3: #3次都失败后跳出循环
try:
urlretrieve(url, filename = r"./PDF/" + name)
print(f"成功下载{name}!")
break
except:
times += 1
print(f"休息5秒!再试第{times}次!")
time.sleep(5)
print("成功下载所有PDF文件!")
通过数据库提供的公告信息,可以大大简化爬取公告难度。同时,相较于 CSMAR
而言,Wind
提供的公告信息更加详尽。
当然,爬取公告只是文本分析的开始,后续还有很多工作要做,如提取文本、分词、词频统计、关键词提取、情感分析、以及文本相似度计算等。
其中,从 PDF
中提取信息就是一项繁杂的工作。我们应该尽力去找那些以 网页形式
展示公告内容的网站,如 Wind、网易财经等,其次可以考虑用专门的 PDF转换软件
或 API
接口将 PDF
转换为TXT
,
最后,可考虑 Python
的 pdfminer3k
和 pdfplumber
等包,并且 pdfplumber
可以很好提取表格数据。
关于图片文字识别,可以参考 百度AI
提供的文字识别 API
接口。
完整 .py
文件,可以到百度云盘下载:
https://pan.baidu.com/s/1Vr_-YCSJAmyoKvfayTQqpw
u7ku
如下是文中使用的主要代码:
#导入相应的包
import os
import pandas as pd
import requests
import re
from lxml import etree #解析网页
from urllib.request import urlretrieve #下载网络文件到本地
import time
#设置地址
os.chdir(r"D:\爬取上市公告") #修改为自己文件路径
os.getcwd()
#爬取上市公司年报_Wind
data = pd.read_excel("公司公告.xlsx")[:-1] #读入数据,并删除最后一行(最后一行为空值)
def address(str): #定义提取公告地址函数
return str.split('"')[1]
data["公告地址"] = data["公告地址"].apply(address)
def pdf_url(url): #利用Xpath提取年报PDF链接
html = requests.get(url).text
tree = etree.HTML(html) #解析网页
url = tree.xpath("//div[2]/a/@href") #获取PDF链接
return "http://news.windin.com/ns/" + url[0]
data["PDF地址"] = data["公告地址"].apply(pdf_url)
for index, row in data.iterrows(): #下载年报
name = row["证券代码"][:6] + "_" + row["公告日期"] + ".pdf" #文件名称
url = row["PDF地址"] #pdf地址
times = 1 #失败后,重新获取次数
while times <= 3: #3次都失败后跳出循环
try:
urlretrieve(url, filename = r"./PDF/" + name)
print(f"成功下载{name}!")
break
except:
times += 1
print(f"休息5秒!再试第{times}次!")
time.sleep(5)
print("成功下载所有PDF文件!")
#爬取上市公司年报_CSMAR
data1 = pd.read_excel("ANN_Classify.xlsx")[2:] #剔除前两行中文标题和单位
data2 = pd.read_excel("ANN_Security.xlsx")[2:]
data = pd.merge(data1, data2, on = ["AnnouncementID", "DeclareDate", "FullDeclareDate", "Title"])
data["pdf_url"] = "http://static.cninfo.com.cn/finalpage/" + data["DeclareDate"] + "/" + data["AnnouncementID"] + ".PDF" #根据巨潮资讯网年报链接形式,生产PDF年报链接
for index, row in data.iterrows(): #下载前年报
name = row["Symbol"] + "_" + row["DeclareDate"] + ".pdf" #文件名称
print(name)
url = row["pdf_url"] #pdf地址
times = 1 #失败后,重新获取次数
while times <= 3: #3次都失败后跳出循环
try:
urlretrieve(url, filename = r"./PDF/" + name)
print(f"成功下载{name}!")
break
except:
times += 1
print(f"休息5秒!再试第{times}次!")
time.sleep(5)
print("成功下载所有PDF文件!")
连享会-直播课 上线了!
http://lianxh.duanshu.com
免费公开课:
直击面板数据模型 - 连玉君,时长:1小时40分钟 Stata 33 讲 - 连玉君, 每讲 15 分钟. 部分直播课 课程资料下载 (PPT,dofiles等)
支持回看,所有课程可以随时购买观看。
专题 | 嘉宾 | 直播/回看视频 |
---|---|---|
⭐ Stata暑期班 | 连玉君 江艇 |
线上直播 9 天 2020.7.28-8.7 |
效率分析-专题 | 连玉君 鲁晓东 张 宁 |
视频-TFP-SFA-DEA 已上线,3天 |
文本分析/爬虫 | 游万海 司继春 |
视频-文本分析与爬虫 已上线,4天 |
空间计量系列 | 范巧 | 空间全局模型, 空间权重矩阵 空间动态面板, 空间DID |
研究设计 | 连玉君 | 我的特斯拉-实证研究设计,-幻灯片- |
面板模型 | 连玉君 | 动态面板模型,-幻灯片- |
直击面板数据模型 [免费公开课,2小时] |
Note: 部分课程的资料,PPT 等可以前往 连享会-直播课 主页查看,下载。
关于我们
课程, 直播, 视频, 客服, 模型设定, 研究设计, 暑期班
stata, plus,Profile, 手册, SJ, 外部命令, profile, mata, 绘图, 编程, 数据, 可视化
DID,RDD, PSM,IV,DID, DDD, 合成控制法,内生性, 事件研究
, 交乘, 平方项, 缺失值, 离群值, 缩尾, R2, 乱码, 结果
Probit, Logit, tobit, MLE, GMM, DEA, Bootstrap, bs, MC, TFP
, 面板, 直击面板数据, 动态面板, VAR, 生存分析, 分位数
空间, 空间计量, 连老师, 直播, 爬虫, 文本, 正则, python
Markdown, Markdown幻灯片, marp, 工具, 软件, Sai2, gInk, Annotator, 手写批注
, 盈余管理, 特斯拉, 甲壳虫, 论文重现
, 易懂教程, 码云, 教程, 知乎
连享会小程序:扫一扫,看推文,看视频……
扫码加入连享会微信群,提问交流更方便
✏ 连享会学习群-常见问题解答汇总:
✨ https://gitee.com/arlionn/WD