爬取年报数据、解析PDF提取数据、分析代码(巨潮Python)
利⽤Python爬取巨潮⽹页上的年报等数据,通过解析下载的PDF⽂件,提取其中有⽤的数据,并写⼊到本地⽂件中。
主要分为⼏个模块:
1、从Excel或者列表或者TXT读取股票代码
2、根据股票代码和年份等信息爬取特定⽹页中的信息,获得年报数据所在的⽹络地址
3、根据年报数据的⽹络地址,下载对应的到本地
4、解析本地的PDF⽂件,通过关键词检索到对应的value
gridview控件格式5、添加多线程,⼀边对股票代码进⾏解析,⼀边进⾏⽂件的下载,⼀边进⾏⽂件的解析,三者同时进⾏,节省时间
GitHub:
最终的效果:
(1)Excel⽂件中部分的股票代码,读取后返回⼀个股票代码的列表
(2)下载的部分年报PDF⽂件,这⾥设定为2002年到2007年的中⽂年报数据(后续会边解析边删除⽂件,不⽤担⼼⽂件过多)
(3)从PDF⽂件解析得到的value,通过设置关键词为想要咨询或者中介费⽤,最终得到对应的值,并写⼊⽂件保存,最后⼀列为该条数据所在的页数。
开发过程说明
1、打开Fiddler软件,通过该软件可以更为清晰的捕捉并看到客户端与服务器之间的响应,功能和⽹页中的network⼀样。(可以下载在:)
2、⾸先在浏览器界⾯打开⽹址
3、当打开⽹址时,Fiddler就会捕捉到这⼀事件,此时在Fiddler界⾯会看到⼀个对应的链接如图,其中 1 表⽰从服务器读取数据,双击可以看到,服务器返回的数据可以被解析为 json 数据如 3 所⽰,从json数据可以很容易的对数据进⾏字符字典操作,并且 2 中可以看到我们向服务器请求的时候我们发送的都有哪些字符,和字符所代表的含义,这些都可以和程序中我们是设置的关键字对应上。
当点击公告搜索的时候会出现以下界⾯:
此时再次双击对应的请求,对应的Fiddler界⾯变为:可以看到body变了,body就相当于我们的请求参数,其中设置pagenum为2,就可以获得第⼆页的数据了,实现翻页的功能。下⾯返回的json数据也变了,并且下⾯还有多个⽂件的地址,地址可以取出来放在列表中,下⾯的地址再加上原始⽹址就是最终该PDF⽂档所在的地址。
最终的PDF地址: ,得到了最后的⽂件地址,我们就可以进⾏下载了,对应的代码就好理解了。
对应的代码为:⽂件已经上传到GitHub上了
# 前⾯的⼀些参数PLATE CATEGORY等是向服务器请求时要发送过去的参数。
OUTPUT_FILENAME = 'report'
# 板块类型:沪市:shmb;深市:szse;深主板:szmb;中⼩板:szzx;创业板:szcy;
PLATE = 'szzx;'
# 公告类型:category_scgkfx_szsh(⾸次公开发⾏及上市)、category_ndbg_szsh(年度报告)、category_bndbg_szsh(半年度报告)CATEGORY = 'category_ndbg_szsh;'
URL = 'wwwinfo/new/hisAnnouncement/query'
# 使⽤浏览器代理,否则⽹站检测到是Python爬⾍时会⾃动屏蔽
HEADER = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
'X-Requested-With': 'XMLHttpRequest'
}
MAX_PAGESIZE = 50
制作好的网页怎么变成网站MAX_RELOAD_TIMES = 5
python请求并解析json数据RESPONSE_TIMEOUT = 10
def standardize_dir(dir_str):
assert (ists(dir_str)), 'Such directory \"' + str(dir_str) + '\" does not exists!'
if dir_str[len(dir_str) - 1] != '/':
return dir_str + '/'
else:
return dir_str
# 参数:页⾯id(每页条⽬个数由MAX_PAGESIZE控制),是否返回总条⽬数(bool)
def get_response(page_num,stack_code,return_total_count=False,START_DATE = '2013-01-01',END_DATE = '2018-01-01'):
# 这⾥就是 body 信息
query = {
'stock': stack_code,
'searchkey': '',
'plate': '',
'category': CATEGORY,
'trade': '',
'column': '', #注意沪市为sse
# 'columnTitle': '历史公告查询',
'pageNum': page_num,
'pageSize': MAX_PAGESIZE,
'tabName': 'fulltext',
'sortName': '',
'sortType': '',
'limit': '',
'showTitle': '',
'seDate': START_DATE + '~' + END_DATE,
}
result_list = []
result_list = []
reloading = 0
while True:
try:
r = requests.post(URL, query, HEADER, timeout=RESPONSE_TIMEOUT)
except Exception as e:
print(e)
continue
if r.status_code == des.ok != '':
scan扫描软件break
# 以下就是开始解析 json 数据,和解析字典类似
my_query = r.json()
try:
countif函数参数说明r.close()
except Exception as e:
print(e)
if return_total_count:
return my_query['totalRecordNum']
else:
for each in my_query['announcements']:
java能做爬虫吗file_link = 'staticinfo/' + str(each['adjunctUrl'])
file_name = __filter_illegal_filename(
str(each['secCode']) + str(each['secName']) + str(each['announcementTitle']) + '.' + '(' + str(each['adjunctSize']) + 'k)' +
file_link[-file_link[::-1].find('.') - 1:] # 最后⼀项是获取⽂件类型后缀名
)
if dswith('.PDF') or dswith('.pdf'):
if '取消' not in file_name and '摘要' not in file_name and '年度' in file_name:
result_list.append([file_name, file_link])
return result_list
最终的result_list:
eg:
000002万科A2012年年度报告.(1848k).PDF
接下来就是通过该⽹址进⾏⽂件的下载
然后通过Python的pdfplunber模块进⾏PDF的解析,提取其中我们想要的数据(这⾥提取的是审计、咨询费⽤⼀项)
代码见
调试经验:
1、try-excep如果发⽣异常,可在except中捕捉,但是⼀定要处理该异常,不能简单的pass,可能会造成后续没有参数被赋值等问题,导致后续还会有bug。⽐如try⾥⾯放了⼀个
pdf_file=),如果发⽣异常,except中必须对该异常进⾏处理,否则后续中出现的pdf_file就是⼀个没有被赋值的参数,调⽤adlines()等⽅法肯定会再次报错。可以在except之后⾄⼀个标志位(if 语句),表⽰此时不再继续向下运⾏代码。
2、当使⽤多线程进⾏编程时,⼀定要考虑到加锁后,锁是否能正常的被释放
3、当频繁的访问某⼀个⽹站时,有可能会被⽹站当成⽹络攻击⽽屏蔽掉,发⽣以下的error:
ConnectionResetError: [WinError 10054] 远程主机强迫关闭了⼀个现有的连接。这时候这个error也是可以处理的,可以再次新建⼀个线程或者回调函数进⾏再次的⽹络访问,或者在每次访问之间设置⼀个sleep 1 s,不访问的太频繁,或者可以建⽴⼀个IP池,每次我们使⽤不同的IP进⾏访问,这样就抓不到我们了。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论