{"id":13672482,"url":"https://github.com/jackluson/chinese-fund-crawler","last_synced_at":"2025-04-27T22:32:22.650Z","repository":{"id":41308663,"uuid":"340676347","full_name":"jackluson/chinese-fund-crawler","owner":"jackluson","description":"中国场外基金数据爬取\u0026汇总分析","archived":false,"fork":false,"pushed_at":"2023-11-18T13:51:44.000Z","size":12260,"stargazers_count":333,"open_issues_count":4,"forks_count":152,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-25T07:04:04.213Z","etag":null,"topics":["crawler","fund","morningstar"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jackluson.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2021-02-20T14:39:39.000Z","updated_at":"2025-04-11T03:59:46.000Z","dependencies_parsed_at":"2023-11-18T15:19:20.760Z","dependency_job_id":null,"html_url":"https://github.com/jackluson/chinese-fund-crawler","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackluson%2Fchinese-fund-crawler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackluson%2Fchinese-fund-crawler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackluson%2Fchinese-fund-crawler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackluson%2Fchinese-fund-crawler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jackluson","download_url":"https://codeload.github.com/jackluson/chinese-fund-crawler/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251219601,"owners_count":21554444,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["crawler","fund","morningstar"],"created_at":"2024-08-02T09:01:36.876Z","updated_at":"2025-04-27T22:32:19.297Z","avatar_url":"https://github.com/jackluson.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# 国内场外基金数据爬取\n\n# Table of Contents\n\n- [前言](#前言)\n- [数据爬取](#数据爬取)\n  - [基金列表数据](#基金列表数据)\n  - [基金详情页数据--不变数据](#基金详情页数据--不变数据)\n  - [基金详情页数据--季度变动数据](#基金详情页数据--季度变动数据)\n  - [基金详情页数据--十大持仓股票信息](#基金详情页数据--十大持仓股票信息)\n  - [基金经理](#基金经理)\n- [技术点](#技术点)\n- [爬虫流程](#爬虫流程)\n- [本地运行](#本地运行)\n  - [本地运行前置条件](#本地运行前置条件)\n  - [文件目录介绍](#文件目录介绍)\n- [其他](#其他)\n- [数据汇总\u0026分析](#数据汇总\u0026分析)\n  - [性价比高的名单统计](#性价比高的名单统计)\n  - [基金重仓股](#基金重仓股)\n  - [个股基金持仓明细](#个股基金持仓明细)\n\n## 前言\n\n纯粹做爬虫技术分享交流,关于各位github朋友用此仓库涉及到的技术爬取数据的用处,本人不负任何责任,请各位朋友自行判断.\n\nPS: 大家感兴趣可转债数据的话欢迎跳到[convertible-bond-crawler](https://github.com/jackluson/convertible-bond-crawler)\n## 数据爬取\n\n### 基金列表数据\n\n\u003e 爬取基金筛选列表，包括基金代码，基金专属代码，基金分类，三年评级，五年评级这些维度等，有了这些基本数据，为了爬取基金详情页，基金筛选等铺好数据基础。\n\n列表爬取数据截图：\n\n\u003cimg src=\"./screenshot/fund_list.png\" style=\"zoom:50%;\" /\u003e\n\n\n### 基金详情页数据--固定数据\n\n\u003e 爬取基金详情页的数据， 根据`列表数据`，遍历爬取单支基金的详情页数据（包括名称，代码，分类，成立时间，基金公司）等维度，后续还有根据这些数据爬取基金的持仓信息，为后面筛选股票做好进一步铺垫\n\n\u003cimg src=\"./screenshot/fund_base.png\" style=\"zoom:50%;\" /\u003e\n\n### 基金详情页数据--季度变动数据\n\n\u003e 爬取基金详情页的数据， 根据第二部分`基础数据`，过滤掉货币，纯债基金等不是标的的基金，爬取目标基金的详情页数据（包括总资产，投资风格，各种风险信息，评级，股票，债券持仓比例等）等维度\n\n\u003cimg src=\"./screenshot/fund_season.png\" style=\"zoom:50%;\" /\u003e\n\n### 基金详情页数据--十大持仓股票信息\n\n\u003e 爬取基金详情页的数据， 根据第二部分`基础数据`，过滤掉没有持有股票的基金，爬取单支基金的十大持仓股票信息（包括每只股票的代码，名称，占比）等维度\n\n\u003cimg src=\"./screenshot/fund_stock.png\" style=\"zoom:50%;\" /\u003e\n\n### 基金经理\n\n\u003e 爬取基金详情页的数据，据此爬取基金经理数据\n\u003e \u003cimg src=\"./screenshot/fund_manager.png\" style=\"zoom:50%;\" /\u003e\n\n## 技术点\n\n- `selenium` 模拟登录， 切换分页, 获取html, 最终获取数据\n- 部分页面用了`BeautifulSoup` 解析 HTML\n- `pandas` 处理数据\n- 数据库mymysql + `sqlalchemy`(部分数据用, 部分写原生sql语句)\n- 工具:\n\n  1. 通过图片比较获得某一个评级数据 -- 用了`get_star_count_with_np`,还提供了备用图片相似度比较`get_star_count_with_sewar`\n  2. 验证码识别使用了`pytesseract`(现在已经不用了)\n- 多线程爬取\n- 其他 -- 一部分数据维度需要其他站点的数据补充,比如检查某一个基金是否已经清算退市, 同类基金的总资产信息等, 直接用request库调用api获取\n\n## 爬虫流程\n\n1. `selenium` 模拟登录：\n   - 直接在env文件设置好账号, 密码\u003cdel\u003e可采用验证码识别方式\u003c/del\u003e\n   - 复制已经登录好的账号cookies,设置在env的login_cookie变量中\n2. 利用`BeautifulSoup` 解析 html，提取当前页的基金列表信息，存入到 mysql 中，或者追加到 csv 中 （目前仅 acquire_fund_snapshot.py 支持导出 csv）\n3. `selenium` 模拟切换分页，重复第二，第三步\n4. 所有的页数据爬取完，退出浏览器\n\n## 本地运行\n\n### 安装\n```bash\npip install -r requirements.txt\n```\n\n### 本地运行前置条件：\n\n1. 安装好 chromedriver 驱动（版本需要和你本地电脑 Chrome 浏览器版本一致）， \n2. \u003cdel\u003e安装 tesseract(识别二维码需要，如果是用 cookies 方式则不需要) 并将 tesseract 加到环境变量下，运行报错的话可能没有安装训练库，可参考[https://stackoverflow.com/questions/14800730/tesseract-running-error](https://stackoverflow.com/questions/14800730/tesseract-running-error)，如果是需要连接数据库的话，还要配置好表结构\u003c/del\u003e\n3. 如果需要存数据到数据库，需要建好对应表结构，(运行`acquire_fund_snapshot.py`可以存在 Excel，其他目前都是存在数据库中)\n\n4.  从环境参数模板（.env.example）中复制一份文件（.env）,修改本地环境变量\n\n    \u003e `cp .env.example .env`\n\n    根据自己情况改环境变量值，例如网站用户名，密码，执行特定的爬虫脚本\n\n5.  运行 --执行`python main.py`\n\n```python\ninput_value = input(\"请输入下列序号执行操作:\\n \\\n        1.“快照” \\n \\\n        2.“新基入库”\\n \\\n        3.“快照同步新基”\\n \\\n        4.“补充基金基础数据”\\n \\\n        5.“基金状态归档”\\n \\\n        6.“季度信息”\\n \\\n        7.“基金持仓股排名”\\n \\\n        8.“基金重仓股Top100”\\n \\\n        9.“股票持仓基金明细”\\n \\\n        10.“股票持仓基金汇总”\\n \\\n        11.“高分基金”\\n \\\n        12.“组合持仓明细”\\n \\\n    输入：\")\n```\n爬取数据的种子是从**快照**数据开始的(也就是所有基金列表数据), 有了种子数据之后,再爬取基金基础数据到基金基础表中. 然后根据基金基础表去爬取基金季度一些信息. 获取到数据之后就可以更加自己的需求进行分析和统计了\n### 文件目录介绍\n\n```bash\n.\n├── .env                         #本地环境配置参数\n├── .env.example                 #环境配置参数模板实例\n├── .gitignore\n├── README.md\n├── requirements.txt\n└── src\n    ├── acquire_fund_base.py     # 爬取基金基础数据-- 一些不变动的数据，例如成立时间\n    ├── acquire_fund_quarter.py  # 爬取基金季度变动 -- 例如持仓数据\n    ├── acquire_fund_snapshot.py # 基金列表快照数据 —— 列表数据\n    ├── fund_info_supplement.py  # 执行补充维度清算，总资产信息\n    ├── fund_statistic.py        # 基金重仓股分析\n    ├── fund_strategy.py         # 高性价比基金筛选\n    ├── sync_fund_base.py         # 将快照爬取和基础数据合到一起了\n    ├── assets                   # 一些静态资源,例如星级图片\n    │   └── star\n    │       ├── star0.gif\n    │       ├── star1.gif\n    │       ├── star2.gif\n    │       ├── star3.gif\n    │       ├── star4.gif\n    │       ├── star5.gif\n    │       └── tmp.gif\n    ├── fund_statistic.py        # 统计数据\n    ├── config\n    │   └── env.py               # 读取.env配置\n    ├── db\n    │   └── connect.py           # 连接数据库\n    ├── fund_info\n    │   ├── api.py               # api 基金信息爬取，主要是补充crawler不到一些信息\n    │   ├── crawler.py           # 基金页面爬取\n    │   ├── statistic.py         # 基金统计\n    │   ├── csv.py               # 基金存为csv\n    │   └── supplement.py        # 补充或者更新基金清算，总资产维度信息\n    ├── crud                     # 利用sqlachemly 进行crud\n    ├── models                   # sqlachemly 表model\n    ├── lib\n    │   └── mysnowflake.py       # 雪花id生成\n    ├── outcome                      # 数据成果整理子项目\n    └── utils.py                 # 一些工具函数，比如登录，设置cookies等\n        ├── __init__.py\n        ├── cookies.py\n        ├── file_op.py\n        ├── index.py\n        └── login.py\n\n```\n## 其他\n\n涉及到一些细节有：\n\n1. \u003cdel\u003e验证码识别错误的话，怎么处理\u003c/del\u003e\n2. 切换分页如果是最后一页时，怎么处理下一页点击\n3. 基金评级是用图片表示，如果转化成数字表示\n4. 如何保证循环当前页与浏览器当前页一致\n5. 多线程爬取时，线程锁\n6. 同名不同类型基金爬取处理\n7. ...\n\n以上问题，我都做了相对应的处理。\n\n## 数据汇总\u0026分析\n\n基于上面的数据，简单做了如下数据汇总\n\n### 性价比高的名单统计\n\n根据基金评级，基金成立时间，基金夏普比例，基金经理从业时间等指标，从几千只股票中选出几十只性比价高的基金，如图所示：\n\n\u003cimg src=\"./screenshot/high-score-funds.png\" /\u003e\n\n至于”性比价“的定义，大家可以看下面这篇文章\n[精心整理，给大家汇总一批性价比高的基金名单](https://mp.weixin.qq.com/s?__biz=MzkyMzI0Njc1Ng==\u0026mid=2247483971\u0026idx=1\u0026sn=a3fd6c71bb42f20d9e17e3f9034a128b\u0026chksm=c1e94b88f69ec29e77cfb2605bef58a158b96150bd1e7615d1f2d4ddfad7cf25b296cd55d941\u0026token=893404419\u0026lang=zh_CN#rd)\n\n### 基金重仓股\n\n统计股票在这些基金中出现的频率,筛选出 top 50，可用于投资理财辅助，如图：\n\n\u003cimg src=\"./screenshot/fund_statistic.png\" /\u003e\n\n在基于上面的汇总数据，做出如下分析结果，得到 2021-Q1 与 2020-Q4 的基金重仓股 Top50 持仓结果对比，可以分两个维度排序，一个是基金持有个数，一个是持有总市值：\n\n\u003cimg src=\"./screenshot/top_50_2021_q1_vs_2020_q4.png\" /\u003e\n\n### 个股基金持仓明细\n\n上面我们知道了基金重仓股排名，我们当然也可以统计某一只股票的基金持仓明细，如图所示，中国平安基金持仓明细：\n\u003cimg src=\"./screenshot/certain_stock_holder_detail.png\" /\u003e\n\n中国平安的基金持仓明细，按基金持有市值排序，其部分数据截图如上\n\n在此过程中,如果遇到什么问题,欢迎扫描下方微信二维码（anchor_data）,欢迎交流\n\n\u003cimg width=480  src=\"./screenshot/qrcode_merge.png\" /\u003e\n\n如果有问题，有兴趣的话，欢迎提 issue，私聊，star。\n[![Page Views Count](https://badges.toozhao.com/badges/01FYTB9DBYFE4G1408VKKT7H4G/green.svg)](https://badges.toozhao.com/stats/01FYTB9DBYFE4G1408VKKT7H4G \"Get your own page views count badge on badges.toozhao.com\")\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjackluson%2Fchinese-fund-crawler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjackluson%2Fchinese-fund-crawler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjackluson%2Fchinese-fund-crawler/lists"}