当前位置:   article > 正文

股票交易所爬虫流程记录和避坑_爬取深交所数据

爬取深交所数据

本文以sse、szse、bse三家股票交易所的年报爬取为例,简单总结一个朋友使用过的爬虫技术。

本文只总结通用流程和避坑,不涉及爬虫代码

零、默认已经安装好python和相关库

import re # 正则表达式
import requests # 获取网页内容
import json # 解析json数据
from pathlib import Path # 处理文件路径
import datetime # (非必须)用于sse设置时间范围参数
import xlrd # (非必须) 解析xls文件
import openpyxl #(非必须)解析xlsx文件
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

一,F12 打开 开发者工具

网络(network)页,清除日志,点击和自己想要的数据相关的内容,比如说查询、下一页等。在日志里找到包含返回数据的请求,复制cookie、请求URL地址、get/post、Referer,User-Agent,这几个值比较重要。

二、构造url地址

一般是请求URL加上负载里的参数

  • 如果是&分隔的参数,可以在负载里点击查看源,将其复制和URL拼接即可
  • 如果是Json格式的参数,比如szse的参数长这样
{"seDate":["",""],"channelCode":["listedNotice_disc"],"bigCategoryId":["010301"],"pageSize":50,"pageNum":1}
  • 1

则需要构造一个json,并进行编码

requestParam = {
    'channelCode': ['listedNotice_disc'],  # 不清楚这个参数是什么,应该是固定的
    'pageNum': 1,  # 其他交易所也有这个参数,且bse的页面从0开始,sse和szse从1开始
    'pageSize': 50,  # 根据需要修改,建议不改
    'seDate': ["2024-03-04", "2024-04-14"],  # 起止时间,格式yyyy-MM-dd,建议先到网站看看这个时间是否被网站允许
    'searchKey': ["2024"],  # 代码/简称/拼音/标题关键字
    # 'bigIndustryCode': '',  # 行业编号A、B、C、D、E
    # 'plateCode': '',  # 板块,主板11,中小板12,创业板16
    'bigCategoryId': ['010305']  # 公告类别,选好类别后可以在负载里看到
            }
data = bytes(json.dumps(requestParam), encoding='utf-8') # 编码
resp = requests.post(url, headers=headers, data=data) # 放到data里
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

构造成功后别急着拿去直接验证访问,网站会拒绝这个请求。我的理解是直接访问会缺少cookie等信息,所以还是得拿去代码中验证。

我们需要把这个URL改造成动态的,方法有很多,可以字符串拼接,也可以format快速拼接参数

url = 'page={page}'
for pageNo in range(10):
	url = base.format(page=pageNo)
  • 1
  • 2
  • 3

以上都是举例,目前这位朋友的方法还是从网页上分析请求的request和response,只有网页上合法的请求才有可能被代码顺利访问

三、根据构造的分页请求获取到response,分析数据发现三家交易所都是json格式的数据

四、可以先将json里的url地址存储用作后续低速爬取,也可以直接根据url地址进行请求,下载PDF

其他需求:

1.分离出带有关键字的PDF

以“数据资源”为例,使用PyPDF2提取PDF中的文本,如果其中包含关键字,则用shutil库将PDF移动到目标文件夹下。不做赘述

2.分离出PDF中的表格中的连锁关键字

如果PDF的一个表格中,左边索引是数据资源,且右边值是数字,也就是该PDF既包含了某个关键字,也包含了这个关键字在表格中对应的值,那么就将PDF移动出来,或者获取其中的值皆可。

因为代码使用了dataframe格式,可能会遇到很多空值。解决方法是先获取每一行前两个非空值,如果第一个值包含关键字,且第二个值包含数字,则满足要求。

这个方法的bug是会将第二个值为0.00的PDF一并获取,这不满足需求,不过应该也能解决

# 需要安装额外的库
import pandas as pd
import pdfplumber # 可以用来提取PDF中的表格,比较准确和方便
  • 1
  • 2
  • 3

坑:

各种坑其实仔细观察是可以发现的,但为了避免像我一样下载很多遍还发现文件少了抓耳挠腮,这里分享一些

1.bse的年报如果有更正,是单独设置了一个值disclosurePostTitle,所以如果更正前和更正后的文件都想下载的话,可以把原本文件名的disclosureTitledisclosurePostTitle拼接一下,防止文件覆盖

2.szse在url里有一个random参数,推测是一个小于1的随机值,所以这部分在每次请求的时候带上一个保留到小数点后16-17位的随机数即可

https://www.szse.cn/api/disc/announcement/annList?random=0.6983879461230162
  • 1

3.sse其实最麻烦,有些公司的年报不在年报类别里,所以我选择根据文件的名称来判断

我现在是在选择这些分类的前提下,只要文件名称出现在probableNameList里面,且不含illegalNameList里面任意一个词,则认为其是年报

probableNameList= ['2023年度报告','2023年年度报告','2023年_年度报告','2023年年报','2023 年年度报告',
				   '年报全文','2023年年年度报告','2023年报']
illegalNameList = ['摘要', '公告', '说明', '通知', '公示', '督导', '意见', '英文', '审计报告', '保荐书', '工作函',
                   '回复', '问询函', '纪要', '财务报表']
  • 1
  • 2
  • 3
  • 4

可以自己搜一搜这些名字就知道为什么要搞得这么复杂了,不过应该有更好的方式完成这个需求。

最后的效果是所有的公司至少获取了一份正确的文件,除了那种命名错误的(把年报命名成“年报摘要”,这种确实根据标题筛不出来)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/957253
推荐阅读
相关标签
  

闽ICP备14008679号