1.引言
笔者之前已经写过一篇相关的文章,但代码尚不完善,这段时间也一直有读者咨询一些问题,因此专门再发一篇更加详细的帖子,欢迎大家互相交流学习。 《1.爬取A股上市公司年报链接并存入Excel》 本文更新了爬虫程序的调用接口对现有问题进行修正,主要更新如下:
更加全面的年报数据,突破了旧接口的2000页限制 内存占用更小,运行速度更快 封装函数,提供方便的参数修改 更详细的功能说明,便于二次开发 ⭐️更完整的免费成品资源,含2022年最新年报(2003-2022年报Excel表格)
代码目前存在的问题:
进度显示功能存在溢出 若公司发布修正后的年报,代码无法去重,需手动处理 若干不影响主功能的小缺陷…
2.具体步骤
2.1 网页分析
图为巨潮资讯网公告发布页面,在右侧可以选择要查询的相关参数。 包括板块分类、公告类型分类、行业分类、时间范围等。 我们选择沪深两市,公告选择年报进行查询,并按公司代码进行排列,如下图所示。 不难发现,基本已经得到了我们需要的内容,但是网站中多出了一行我们并不需要的年报摘要内容,我们在之后可以用正则表达式去除。
2.2 网络抓包
对网站内容分析完成后,就可以开始抓包。按F12打开开发者工具,切换到网络选项卡。 我们切换一下页面,发现多出了一个query请求,这就是我们需要的访问接口。 根据信息显示,这是一个POST请求,负载的参数为查询时的相关参数,我们解析一下,结果如下图所示。 这个请求最后返回了一个json文件,包含30条公司数据,当然也包括我们需要的年报链接。 到这里基本的抓包和分析就已经完成,我们可以直接开始这部分代码的编写。
'''
@Project :PycharmProjects
@File :巨潮资讯年报2.0.py
@IDE :PyCharm
@Author :lingxiaotian
@Date :2023/5/20 12:38
'''
#首先引入第三方库
import requests
import re
import openpyxl
import time
#定义一个访问接口的函数
def get_report(page_num,date):
url = "http://www.cninfo.com.cn/new/hisAnnouncement/query"
headers = {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"Content-Length": "195",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Host": "www.cninfo.com.cn",
"Origin": "http://www.cninfo.com.cn",
"Proxy-Connection": "keep-alive",
"Referer": "http://www.cninfo.com.cn/new/commonUrl/pageOfSearch?url=disclosure/list/search&checkedCategory=category_ndbg_szsh",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.42",
"X-Requested-With": "XMLHttpRequest"
}
'''
参数信息
plate: sz;sh, 表示沪深两市
seDate:查询时间
'''
data = {
"pageNum": page_num,
"pageSize": 30,
"column": "szse",
"tabName": "fulltext",
"plate": "sz;sh",
"searchkey": "",
"secid": "",
"category": "category_ndbg_szsh",
"trade": "",
"seDate": date,
"sortName": "code",
"sortType": "asc",
"isHLtitle": "false"
}
response = requests.post(url, data=data, headers=headers)
return response
这个函数包含两个参数page_num和date,我们可以控制当前页码来遍历整个json文件,并用date来控制需要查询的时间范围。
2.3 数据获取
这部分主要就是为了实现本文的主要目的:获取指定年份的上市公司报告链接 首先我们需要循环遍历整个所有页面,那么如何确定遍历次数呢? 仔细研究返回的json文件我们发现文件最后会包含一个totalpapges的参数,即总页数。 那么,有了这个数字,我们便可以先请求一次获取总页数,从而设定好循环次数进行获取。 ⚠️然而,笔者最后生成的excel表格中存在数千条重复项,对于这个问题,笔者在研究后发现该接口每次获取的页数上限最多为100页!超过这个页数后返回的内容完全一致。 从网页上看结果也是如此,最大显示范围为100页,之后便无法获取。 针对这一问题,笔者通过划分时间范围进行处理,稍后进行介绍,此处先给出循环访问获取数据函数的完整代码,代码中的重试机制此前已经介绍,本文不再赘述。
def downlaod_report(date):
global counter
all_results = []
page_num = 1
response_test = get_report(page_num,date)
data_test = response_test.json()
total_pages = data_test["totalpages"]
max_retries = 3 #最大重试次数
retry_count = 0 #当前重试次数
while page_num |