├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ └── bug_report.md └── workflows │ └── dependency-review.yml ├── .gitignore ├── HISTORY.md ├── LICENSE ├── MANIFEST.in ├── README.md ├── adata ├── __init__.py ├── __version__.py ├── bond │ ├── __init__.py │ ├── cache │ │ └── __init__.py │ ├── info │ │ ├── __init__.py │ │ └── bond_code.py │ └── market │ │ ├── __init__.py │ │ ├── bond_market.py │ │ ├── bond_market_sina.py │ │ └── bond_market_template.py ├── common │ ├── __init__.py │ ├── base │ │ ├── __init__.py │ │ ├── base_req.py │ │ └── base_ths.py │ ├── exception │ │ ├── __init__.py │ │ ├── exception_msg.py │ │ └── handler.py │ ├── headers │ │ ├── __init__.py │ │ ├── baidu_headers.py │ │ ├── east_headers.py │ │ ├── sina_headers.py │ │ └── ths_headers.py │ ├── js │ │ ├── __init__.py │ │ ├── hexin.js │ │ └── ths.js │ └── utils │ │ ├── __init__.py │ │ ├── code_utils.py │ │ ├── cookie.py │ │ ├── date_utils.py │ │ ├── snowflake.py │ │ ├── sunrequests.py │ │ └── unit_conver.py ├── fund │ ├── __init__.py │ ├── cache │ │ └── __init__.py │ ├── info │ │ ├── __init__.py │ │ └── fund_info.py │ └── market │ │ ├── __init__.py │ │ ├── etf_market.py │ │ ├── etf_market_template.py │ │ └── etf_market_ths.py ├── message │ └── __init__.py ├── sentiment │ ├── __init__.py │ ├── alist.py │ ├── cache │ │ └── __init__.py │ ├── hot.py │ ├── mine_clearance.py │ ├── north_flow.py │ ├── securities_margin.py │ └── stock_lifting.py └── stock │ ├── __init__.py │ ├── cache │ ├── __init__.py │ ├── calendar │ │ ├── 2004.csv │ │ ├── 2005.csv │ │ ├── 2006.csv │ │ ├── 2007.csv │ │ ├── 2008.csv │ │ ├── 2009.csv │ │ ├── 2010.csv │ │ ├── 2011.csv │ │ ├── 2012.csv │ │ ├── 2013.csv │ │ ├── 2014.csv │ │ ├── 2015.csv │ │ ├── 2016.csv │ │ ├── 2017.csv │ │ ├── 2018.csv │ │ ├── 2019.csv │ │ ├── 2020.csv │ │ ├── 2021.csv │ │ ├── 2022.csv │ │ ├── 2023.csv │ │ ├── 2024.csv │ │ ├── 2025.csv │ │ └── __init__.py │ ├── code.csv │ └── index_code_rel_ths.py │ ├── finance │ ├── __init__.py │ ├── balance.py │ ├── cash_flow.py │ ├── core.py │ └── profit.py │ ├── index │ ├── __init__.py │ └── cal_index.py │ ├── info │ ├── __init__.py │ ├── concept │ │ ├── __init__.py │ │ ├── stock_concept.py │ │ ├── stock_concept_baidu.py │ │ ├── stock_concept_east.py │ │ ├── stock_concept_template.py │ │ └── stock_concept_ths.py │ ├── stock_code.py │ ├── stock_index.py │ ├── stock_info.py │ └── trade_calendar.py │ └── market │ ├── __init__.py │ ├── capital_flow │ ├── __init__.py │ ├── stock_capital_flow.py │ ├── stock_capital_flow_baidu.py │ ├── stock_capital_flow_east.py │ └── stock_capital_flow_template.py │ ├── concept_capital_flow │ ├── __init__.py │ ├── capital_flow_east.py │ └── concept_flow.py │ ├── concepth_market │ ├── __init__.py │ ├── concept_market_east.py │ ├── concept_market_template.py │ └── concept_market_ths.py │ ├── index_market │ ├── __init__.py │ ├── market_index.py │ ├── market_index_baidu.py │ ├── market_index_east.py │ ├── market_index_template.py │ └── market_index_ths.py │ ├── stock_dividend.py │ └── stock_market │ ├── __init__.py │ ├── stock_market.py │ ├── stock_market_baidu.py │ ├── stock_market_east.py │ ├── stock_market_qq.py │ ├── stock_market_sina.py │ └── stock_market_template.py ├── config.toml ├── docs ├── AData200x200.png ├── ndh.jpg ├── twine.md ├── web.md ├── wx.jpg └── xyhcl-gzh.png ├── pylintrc ├── pyproject.toml ├── requirements.txt ├── setup.py └── tests ├── adata_test ├── HTMLTestRunner.py ├── __init__.py ├── adata_info_test.py ├── adata_test.py ├── bond │ ├── __init__.py │ └── bond_test.py ├── fund │ ├── __init__.py │ └── fund_test.py ├── sentiment │ ├── __init__.py │ ├── sentiment_hot_test.py │ ├── sentiment_mine_test.py │ ├── sentiment_north_test.py │ └── sentiment_test.py └── stock │ ├── __init__.py │ ├── capital_flow_test.py │ ├── concept_test.py │ ├── dividend_test.py │ ├── finance_test.py │ ├── info_test.py │ ├── makert_test.py │ ├── market_concept_test.py │ ├── market_index_test.py │ └── trade_calendar_test.py ├── other ├── __init__.py ├── bs4_test.py ├── cid_test.py ├── cookie_test.py ├── core_test.py ├── jutest.ipynb └── year_test.py └── utils ├── 2025.csv ├── __init__.py ├── code.csv ├── code_test.py ├── csv_utils.py ├── sh.xlsx ├── sz.xlsx └── zip_test.py /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js linguist-language=python 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/workflows/dependency-review.yml: -------------------------------------------------------------------------------- 1 | # Dependency Review Action 2 | # 3 | # This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging. 4 | # 5 | # Source repository: https://github.com/actions/dependency-review-action 6 | # Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement 7 | name: 'Dependency Review' 8 | on: [pull_request] 9 | 10 | permissions: 11 | contents: read 12 | 13 | jobs: 14 | dependency-review: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: 'Checkout Repository' 18 | uses: actions/checkout@v3 19 | - name: 'Dependency Review' 20 | uses: actions/dependency-review-action@v2 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | ### node js ### 7 | node_modules 8 | .temp 9 | .cache 10 | !.vuepress 11 | docs/.vuepress/dist 12 | 13 | ### STS ### 14 | .apt_generated 15 | .classpath 16 | .factorypath 17 | .project 18 | .settings 19 | .springBeans 20 | .sts4-cache 21 | 22 | ### IntelliJ IDEA ### 23 | .idea 24 | *.iws 25 | *.iml 26 | *.ipr 27 | 28 | ### NetBeans ### 29 | /nbproject/private/ 30 | /nbbuild/ 31 | /dist/ 32 | /nbdist/ 33 | /.nb-gradle/ 34 | build/ 35 | 36 | ### VS Code ### 37 | .vscode/ 38 | 39 | ### python ## 40 | __pycache__ 41 | 42 | #Mac 43 | .DS_Store 44 | 45 | .svn 46 | 47 | *.zip 48 | 49 | /adata.egg-info 50 | /venv 51 | .html -------------------------------------------------------------------------------- /HISTORY.md: -------------------------------------------------------------------------------- 1 | Release History 2 | =============== 3 | 4 | ![logo](https://adata.30006124.xyz/favicon.ico)[AData](https://github.com/1nchaos/adata) 5 | 6 | master 7 | ------ 8 | 开放、纯净、持续 9 | 10 | 专注股票量化数据,为Ai(爱)发电,向阳而生。 11 | 12 | 2.9.0 (2024-04-02) 13 | ------------------ 14 | 1. 又是一年清明节,两年 2k star,感谢各位老铁的支持。 15 | 2. 新增:股票:舆情:通达信股票扫雷数据。 16 | 17 | 2.8.2 (2025-01-13) 18 | ------------------ 19 | 1. 修复:股票:日历:跨年后类型不统一问题。 20 | 2. 优化:py_mini-racer包替换mini-racer,更好的兼容。 21 | 3. 特别感谢这次贡献代码的两位朋友。 22 | 23 | 2.8.0 (2024-12-25) 24 | ------------------ 25 | 1. 新增:股票:行情:东财概念资金流向。 26 | 27 | 2.7.0 (2024-10-16) 28 | ------------------ 29 | 1. 新增:股票:股票所属的板块:行业、地域板块、概念。 30 | 2. 修复:股票:部分文档描述 31 | 32 | 2.6.0 (2024-09-04) 33 | ------------------ 34 | 1. 新增:股票:财务数据-核心财务数据。 35 | 2. 修复:股票:代码市场bug。 36 | 37 | 2.5.0 (2024-07-23) 38 | ------------------ 39 | 1. 新增:股票:单只股票的申万一二级行业信息。 40 | 2. 新增:股票:行情接口增加5min,15min,60min,复权类型参数。 41 | 3. 修复:股票:名称有空格的问题。 42 | 43 | 2.4.0 (2024-07-15) 44 | ------------------ 45 | 1. 新增:股票:单只股票龙虎榜信息接口。 46 | 2. 修复:基金:行情空值等bug。 47 | 48 | 2.3.0 (2024-07-06) 49 | ------------------ 50 | 1. 新增:股票:百度的概念接口。 51 | 2. 新增:股票:龙虎榜单列表接口。 52 | 3. 修复:股票:资金流,成立日期格式等bug。 53 | 54 | 2.2.0 (2024-07-01) 55 | ------------------ 56 | 1. 新增:股票:资金流接口。 57 | 2. 修复:股票:分红数据api。 58 | 59 | 2.1.0 (2024-05-05) 60 | ------------------ 61 | 1. 新增:舆情:人气榜单接口。 62 | 2. 新增:债券:债券行情接口。 63 | 64 | 2.0.0 (2024-04-24) 65 | ------------------ 66 | 1. 新增:基金ETF行情接口。 67 | 2. 新增:股票股东信息接口。 68 | 69 | ...... 70 | ------------------ 71 | 72 | 0.0.1b0 (2023-04-05) 73 | ------------------ 74 | 清明时节雨纷纷 75 | 第一个测试预览版本 76 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include adata/common/js *.js 2 | recursive-include adata/stock/cache/* *.csv 3 | recursive-include adata/stock/cache *.csv -------------------------------------------------------------------------------- /adata/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @desc: adata 4 | @author: 1nchaos 5 | @time: 2023/4/4 6 | """ 7 | # -*- coding: utf-8 -*- 8 | 9 | import logging 10 | 11 | from adata.__version__ import __version__ 12 | from adata.bond import bond 13 | from adata.common.utils.sunrequests import SunProxy 14 | from adata.fund import fund 15 | from adata.sentiment import sentiment 16 | from adata.stock import stock 17 | 18 | 19 | def version(): 20 | return __version__ 21 | 22 | 23 | def proxy(is_proxy=False, ip: str = None, proxy_url: str = None): 24 | """ 25 | 设置请求代理 26 | :param is_proxy: 是否启用代理,默认:否 27 | :param ip: 代理ip地址;格式样例:192.123.123.4:4568 28 | :param proxy_url: 能获取到代理的url,返回格式必须和ip一样 29 | """ 30 | SunProxy.set('is_proxy', is_proxy) 31 | SunProxy.set('ip', ip) 32 | SunProxy.set('proxy_url', proxy_url) 33 | return 34 | 35 | 36 | # set up logging 37 | logger = logging.getLogger("adata") 38 | 39 | 40 | def set_logger(): 41 | format_string = "%(asctime)s - %(levelname)s - %(message)s" 42 | formatter = logging.Formatter(format_string, datefmt="%Y-%m-%dT%H:%M:%S") 43 | handler = logging.StreamHandler() 44 | handler.setFormatter(formatter) 45 | 46 | logger.addHandler(handler) 47 | 48 | 49 | set_logger() 50 | -------------------------------------------------------------------------------- /adata/__version__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | VERSION = (2, 9, 2) 4 | PRERELEASE = None # alpha, beta or rc 5 | REVISION = None 6 | 7 | 8 | def generate_version(version, prerelease=None, revision=None): 9 | version_parts = [".".join(map(str, version))] 10 | if prerelease is not None: 11 | version_parts.append(f"-{prerelease}") 12 | if revision is not None: 13 | version_parts.append(f".{revision}") 14 | return "".join(version_parts) 15 | 16 | 17 | __title__ = "adata" 18 | __description__ = "A Data,A Stock,ETF,Bond,Quant,Stock Market,K Line" 19 | __url__ = "https://github.com/1nchaos/adata" 20 | __version__ = generate_version(VERSION, prerelease=PRERELEASE, revision=REVISION) 21 | __author__ = "1nchaos" 22 | __author_email__ = "9527@1nchaos.com" 23 | __license__ = "Apache License" 24 | -------------------------------------------------------------------------------- /adata/bond/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @desc: 场内债券相关数据 4 | @author: 1nchaos 5 | @time: 2023/3/29 6 | @log: change log 7 | """ 8 | from adata.bond.info import info 9 | from adata.bond.market import market 10 | 11 | 12 | class Bond(object): 13 | 14 | def __init__(self) -> None: 15 | self.info = info 16 | self.market = market 17 | 18 | 19 | bond = Bond() 20 | -------------------------------------------------------------------------------- /adata/bond/cache/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @desc: readme 4 | @author: 1nchaos 5 | @time: 2023/6/2 6 | @log: change log 7 | """ 8 | -------------------------------------------------------------------------------- /adata/bond/info/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @desc: readme 4 | @author: 1nchaos 5 | @time: 2023/5/31 6 | @log: change log 7 | """ 8 | from adata.bond.info.bond_code import BondCode 9 | 10 | 11 | class Info(BondCode): 12 | 13 | def __init__(self) -> None: 14 | super().__init__() 15 | 16 | 17 | info = Info() 18 | -------------------------------------------------------------------------------- /adata/bond/info/bond_code.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @desc: 债券代码 4 | @author: 1nchaos 5 | @time: 2023/5/31 6 | @log: change log 7 | """ 8 | import copy 9 | 10 | import pandas as pd 11 | from adata.common import requests 12 | 13 | from adata.common.headers import ths_headers 14 | 15 | 16 | class BondCode(object): 17 | """ 18 | 债券代码 19 | """ 20 | 21 | def __init__(self) -> None: 22 | super().__init__() 23 | 24 | def all_convert_code(self): 25 | """ 26 | 获取所有的可转换债券代码信息 27 | :return: 所有可转换债券的代码信息: 28 | ['bond_code','bond_name','stock_code','short_name','sub_date','issue_amount','listing_date', 29 | 'expire_date','convert_price'] 30 | """ 31 | return self.__convert_code_ths() 32 | 33 | def __convert_code_ths(self): 34 | """ 35 | 获取同花顺可转换债券列表 36 | web: http://data.10jqka.com.cn/ipo/kzz/ 37 | :return 可转债列表 38 | ['bond_code','bond_name','stock_code','short_name','sub_date','issue_amount','listing_date','expire_date', 39 | 'convert_price'] 40 | """ 41 | COLUMNS = ['bond_code', 'bond_name', 'stock_code', 'short_name', 'sub_date', 'issue_amount', 'listing_date', 42 | 'expire_date', 'convert_price'] 43 | # 1. 请求市场排名的 url 44 | api_url = f"https://data.10jqka.com.cn/ipo/kzz/" 45 | # 2. 设置请求头 46 | headers = copy.deepcopy(ths_headers.text_headers) 47 | headers['Host'] = 'data.10jqka.com.cn' 48 | headers['Referer'] = 'http://data.10jqka.com.cn/ipo/bond/' 49 | res = requests.request(url=api_url, headers=headers, proxies={}) 50 | res_json = res.json() 51 | if res.status_code != 200 or res_json['status_msg'] != 'ok': 52 | return pd.DataFrame(data=[], columns=COLUMNS) 53 | # 3. 解析数据 54 | data = res_json['list'] 55 | # 4. 封装数据 56 | rename = {'price': 'convert_price', 'issue_total': 'issue_amount', 'name': 'short_name', 'code': 'stock_code'} 57 | df = pd.DataFrame(data=data).rename(columns=rename)[COLUMNS] 58 | # 5. 数据清洗 59 | df['issue_amount'] = df['issue_amount'].astype(float) * 100000000 60 | return df 61 | 62 | 63 | if __name__ == '__main__': 64 | print(BondCode().all_convert_code()) 65 | -------------------------------------------------------------------------------- /adata/bond/market/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @desc: readme 4 | @author: 1nchaos 5 | @time: 2023/5/31 6 | @log: change log 7 | """ 8 | from adata.bond.market.bond_market import BondMarket 9 | 10 | 11 | class Market(BondMarket): 12 | 13 | def __init__(self) -> None: 14 | super().__init__() 15 | 16 | 17 | market = Market() 18 | -------------------------------------------------------------------------------- /adata/bond/market/bond_market.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @desc: 4 | http://www.iwencai.com/unifiedwap/result?typed=1&preParams=&ts=1&f=1&qs=1&selfsectsn=&querytype=&searchfilter=&tid=stockpick&w=127093 5 | 6 | @author: 1nchaos 7 | @time:2023/4/5 8 | @log: 9 | """ 10 | from adata.bond.market.bond_market_sina import BondMarketSina 11 | 12 | 13 | class BondMarket(object): 14 | """bond 行情""" 15 | 16 | def __init__(self) -> None: 17 | super().__init__() 18 | self.sina = BondMarketSina() 19 | 20 | def list_market_current(self, code_list=None): 21 | """ 22 | 获取多个可转债的最新行情信息 23 | :param code_list: 可转债代码 24 | :return: 当前最新的行情价格信息 25 | _MARKET_CURRENT_COLUMNS 26 | """ 27 | return self.sina.list_market_current(code_list) 28 | 29 | 30 | if __name__ == '__main__': 31 | print(BondMarket().list_market_current()) 32 | print(BondMarket().list_market_current(code_list=['110044'])) 33 | -------------------------------------------------------------------------------- /adata/bond/market/bond_market_sina.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @desc: 新浪 4 | https://vip.stock.finance.sina.com.cn/mkt/#hskzz_z 5 | 6 | @author: 1nchaos 7 | @time:2023/4/5 8 | @log: 9 | """ 10 | import pandas as pd 11 | 12 | from adata.bond.market.bond_market_template import BondMarketTemplate 13 | from adata.common.utils import requests 14 | 15 | 16 | class BondMarketSina(BondMarketTemplate): 17 | """bond 行情""" 18 | 19 | def __init__(self) -> None: 20 | super().__init__() 21 | 22 | def list_market_current(self, code_list=None): 23 | """ 24 | 获取新浪的最新可转债行情 25 | url : http://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQNodeDataSimple 26 | :param code_list: 可转债代码列表 27 | :return: 最新行情数据 28 | """ 29 | # 0.进行参数拼接处理 30 | api_url = f"http://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQNodeDataSimple" 31 | 32 | # 2.循环请求 33 | data = [] 34 | for i in range(100): 35 | # 1.请求接口 36 | params = {"page": {i+1}, "num": "80", "sort": "symbol", 37 | "asc": "1", "node": "hskzz_z", "_s_r_a": "page"} 38 | res = requests.request('get', api_url, params=params) 39 | res = res.json() 40 | data.extend(res) 41 | if len(res) < 80: 42 | break 43 | # 3. 结果筛选 44 | if code_list is not None: 45 | new_data = [] 46 | for d in data: 47 | if d['code'] in code_list: 48 | new_data.append(d) 49 | data = new_data 50 | # 4. 封装数据 51 | rename = {'code': 'bond_code', 'name': 'bond_name', 'pricechange': 'change', 'changepercent': 'change_pct', 52 | 'settlement': 'pre_close', 'ticktime': 'time', 'trade': 'price'} 53 | result_df = pd.DataFrame(data=data).rename(columns=rename) 54 | columns_to_convert = ['price', 'open', 'high', 'low', 'pre_close', 'change', 'change_pct', 'volume', 'amount'] 55 | result_df[columns_to_convert] = result_df[columns_to_convert].astype(float) 56 | result_df_unique = result_df.drop_duplicates(keep='last', subset=['bond_code']) 57 | return result_df_unique[self._MARKET_CURRENT_COLUMNS] 58 | 59 | 60 | if __name__ == '__main__': 61 | df = BondMarketSina().list_market_current(code_list=['110044', '127103']) 62 | print(df) 63 | -------------------------------------------------------------------------------- /adata/bond/market/bond_market_template.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @desc: readme 4 | @author: 1nchaos 5 | @time: 2024/05/05 6 | @log: change log 7 | """ 8 | 9 | 10 | class BondMarketTemplate(object): 11 | """ 12 | 债券行情 13 | """ 14 | _MARKET_CURRENT_COLUMNS = ['bond_code', 'bond_name', 'price', 'open', 'high', 'low', 'pre_close', 'change', 15 | 'change_pct', 'volume', 'amount', 'time'] 16 | 17 | def list_market_current(self, code_list=None): 18 | """ 19 | 获取多个可转债的最新行情信息 20 | :param code_list: 可转债代码 21 | :return: 当前最新的行情价格信息 22 | _MARKET_CURRENT_COLUMNS 23 | """ 24 | pass 25 | -------------------------------------------------------------------------------- /adata/common/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @desc: readme 4 | @author: 1nchaos 5 | @time: 2023/3/29 6 | @log: change log 7 | """ 8 | from .utils import * 9 | from .headers import * 10 | -------------------------------------------------------------------------------- /adata/common/base/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @desc: 基础类,提高代码的复用性 4 | @author: 1nchaos 5 | @time: 2023/6/5 6 | @log: change log 7 | """ 8 | -------------------------------------------------------------------------------- /adata/common/base/base_req.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @desc: readme 4 | @author: 1nchaos 5 | @time: 2023/8/14 6 | @log: change log 7 | """ 8 | 9 | 10 | class BaseReq(object): 11 | 12 | def __init__(self) -> None: 13 | super().__init__() 14 | -------------------------------------------------------------------------------- /adata/common/base/base_ths.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @desc: 同花顺基础类 4 | @author: 1nchaos 5 | @time: 2023/6/5 6 | @log: change log 7 | """ 8 | import copy 9 | import datetime 10 | import re 11 | import time 12 | 13 | from bs4 import BeautifulSoup 14 | from py_mini_racer import py_mini_racer 15 | 16 | from adata.common import requests 17 | from adata.common.headers import ths_headers 18 | from adata.common.utils import cookie 19 | from adata.common.utils.cookie import get_file_content_ths 20 | 21 | 22 | class BaseThs(object): 23 | """同花顺base类""" 24 | 25 | def __init__(self) -> None: 26 | super().__init__() 27 | 28 | def _get_text(self, api_url, code): 29 | """ 30 | 获取同花顺的请求 text 31 | :param api_url: url 32 | :param code: 代码 33 | :return: 34 | """ 35 | headers = copy.deepcopy(ths_headers.text_headers) 36 | headers['Host'] = 'd.10jqka.com.cn' 37 | headers['Cookie'] = cookie.ths_cookie() 38 | text = '' 39 | for i in range(2): 40 | res = requests.request('get', api_url, headers=headers, proxies={}) 41 | text = res.text 42 | if code in text: 43 | break 44 | time.sleep(2) 45 | return text 46 | 47 | def _get_years_by_start_date(self, start_date): 48 | """ 49 | 根据开始时间获取大于开始时间的所有年份的列表 50 | 例:start_date=2020-10-01 -> years=[2020,2021,2022,2023] 51 | :param start_date: 开始时间 52 | :return: 年份 53 | """ 54 | years = [] 55 | if not start_date: 56 | years.append('last') 57 | else: 58 | current_year = datetime.datetime.now().year 59 | start_year = datetime.datetime.strptime(start_date, "%Y-%m-%d").year 60 | while start_year <= current_year: 61 | years.append(start_year - 1) 62 | start_year += 1 63 | if current_year not in years: 64 | years.append(current_year) 65 | return years 66 | 67 | def get_wencai_server_time(self): 68 | """ 69 | 获取问财服务时间 70 | :return: time 71 | """ 72 | url = 'http://www.iwencai.com/unifiedwap/home/index' 73 | resp = requests.request(method='get', url=url) 74 | resp_text = resp.text 75 | soup = BeautifulSoup(resp_text, 'html.parser') 76 | js_url = "http:" + soup.find('script')['src'] 77 | js_resp = requests.request(method='get', url=js_url) 78 | js_text = js_resp.text 79 | obj = re.compile(r'var TOKEN_SERVER_TIME=(?P