中基协-基金管理人名录数据
中国证券投资基金业协会,aka 中基协,提供了大量基金行业的数据。其服务大厅提供了有关机构、产品和人员数据的查询服务。这篇文章介绍如何爬取公募基金管理人名录数据。
| 序号 | 公司名称 | 注册地 | 辖区 | 官方网址 | 客服电话 |
|---|---|---|---|---|---|
| 1 | 国泰基金管理有限公司 | 上海 | 上海 | www.gtfund.com | 4008888688/ 021-31089000 |
| 2 | 南方基金管理股份有限公司 | 深圳 | 深圳 | www.nffund.com | 4008898899 |
| 3 | 华夏基金管理有限公司 | 北京 | 北京 | www.chinaamc.com | 4008186666 |
| ... | ... | ... | ... | ... | ... |
数据接口
我们先尝试获取数据接口, 从服务大厅的机构查询入口可以找到公募基金管理人名录查询。在我撰写这篇文章时共有158条记录,共16页,数据量不大。
Warning
在该页面打开浏览器开发者工具可能会自动进入了调试模式,阻止我们对页面元素进行审查。在调试工具中可以看到是执行了assets目录下0b0c58b7_chunk.js这段代码导致的,我们右键点击这个文件,选择Add script to ignore list就可以正常审查页面元素了。
接着将开发者工具切换到Network标签,选择Fetch/XHR类型,刷新页面,可以看到两条记录,其中有pageNo=1&pageSize=10字样的就是数据接口。点击该记录查看Headers,可以看到数据接口为https://www.amac.org.cn//portal/front/mutualFund/findMutualFundHousePage? ,query为pageNo=1&pageSize=10.
请求数据
使用urllib库构造URL,我们刚刚看到总共有158条记录,所以尝试将query中的pageSize改为200,使得一次请求就可以将所有数据提取出来。
import urllib
api = "http://www.amac.org.cn//portal/front/mutualFund/findMutualFundHousePage?"
query = {"pageNo": 1, "pageSize": 200}
query = urllib.parse.urlencode(query)
url = api + query
url
# output
# 'http://www.amac.org.cn//portal/front/mutualFund/findMutualFundHousePage?pageNo=1&pageSize=200'
尝试请求该链接,会报SSLError错误:UNSAFE_LEGACY_RENEGOTIATION_DISABLED
import requests
requests.get(url)
# output
# ... SSLError: [SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED] ...
这是因为网站使用了旧版本的协议,与requests产生了冲突,stack overflow的帖子提供了解决方法:
import requests
import urllib3
import ssl
class CustomHttpAdapter (requests.adapters.HTTPAdapter):
# "Transport adapter" that allows us to use custom ssl_context.
def __init__(self, ssl_context=None, **kwargs):
self.ssl_context = ssl_context
super().__init__(**kwargs)
def init_poolmanager(self, connections, maxsize, block=False):
self.poolmanager = urllib3.poolmanager.PoolManager(
num_pools=connections, maxsize=maxsize,
block=block, ssl_context=self.ssl_context)
def get_legacy_session():
ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
ctx.options |= 0x4 # OP_LEGACY_SERVER_CONNECT
session = requests.session()
session.mount('https://', CustomHttpAdapter(ctx))
return session
通过上述get_legacy_session函数就可以成功请求到数据,我们将传回的数据转换为json
import json
r = get_legacy_session().get(url)
data = json.loads(r.text)
data
# output
# {'path': '//portal/front/mutualFund/findMutualFundHousePage',
# 'code': 200,
# 'data': {'errcode': 0,
# 'msg': '查询成功',
# 'data': {'dataList': [{'lineId': '1',
# 'houseName': '国泰基金管理有限公司',
# 'registerAddr': '上海',
# 'officeAddr': '上海',
# 'website': 'www.gtfund.com',
# 'phone': '4008888688/\n021-31089000'},
# ...
json中data-data-dataList下就是我们需要的数据。最后,我们可以将其转换成DataFrame:
import pandas as pd
df = pd.DataFrame(data["data"]["data"]["dataList"])
df
# output
# lineId houseName registerAddr officeAddr website \
# 0 1 国泰基金管理有限公司 上海 上海 www.gtfund.com
# 1 2 南方基金管理股份有限公司 深圳 深圳 www.nffund.com
# 2 3 华夏基金管理有限公司 北京 北京 www.chinaamc.com
# 3 4 华安基金管理有限公司 上海 上海 www.huaan.com.cn
# 4 5 博时基金管理有限公司 深圳 深圳 www.bosera.com
# .. ... ... ... ... ...