mirror of
https://github.com/1nchaos/adata.git
synced 2024-11-25 16:32:39 +08:00
first
This commit is contained in:
parent
13ace35e73
commit
fa3db5bc71
46
.gitignore
vendored
Normal file
46
.gitignore
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
HELP.md
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**
|
||||
!**/src/test/**
|
||||
.vuepress
|
||||
### node js ###
|
||||
node_modules
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### python ##
|
||||
|
||||
#Mac
|
||||
.DS_Store
|
||||
|
||||
.svn
|
||||
|
||||
*.zip
|
||||
|
||||
/adata.egg-info
|
||||
/venv
|
13
HISTORY.md
Normal file
13
HISTORY.md
Normal file
@ -0,0 +1,13 @@
|
||||
Release History
|
||||
===============
|
||||
|
||||
**A Data**
|
||||
|
||||
master
|
||||
------
|
||||
开放、纯净、持续
|
||||
|
||||
0.0.1b0 (2023-04-05)
|
||||
------------------
|
||||
清明时节雨纷纷
|
||||
第一个测试预览版本
|
1
MANIFEST.in
Normal file
1
MANIFEST.in
Normal file
@ -0,0 +1 @@
|
||||
recursive-include adata/common/js *.js
|
214
README.md
Normal file
214
README.md
Normal file
@ -0,0 +1,214 @@
|
||||
# A Data
|
||||
|
||||
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/adata?color=d)](https://pypi.org/project/adata/)[![Licence](https://img.shields.io/hexpm/l/apa?color=d)](https://gitee.com/inchaos/adata/blob/master/LICENSE)
|
||||
|
||||
|
||||
## 0、介绍
|
||||
免费开源A股数据库;
|
||||
|
||||
专注A股,专注量化,向阳而生;
|
||||
|
||||
开放、纯净、持续、为Ai(爱)发电。
|
||||
|
||||
## 一、快速开始
|
||||
|
||||
### (1)安装sdk
|
||||
|
||||
#### 1. 简单安装
|
||||
|
||||
~~~python
|
||||
# 首次安装
|
||||
pip install adata
|
||||
|
||||
# 升级版本
|
||||
pip install -U adata
|
||||
~~~
|
||||
|
||||
#### 2. 指定镜像源安装
|
||||
|
||||
~~~
|
||||
# 首次安装
|
||||
pip install adata -i http://mirrors.aliyun.com/pypi/simple/
|
||||
|
||||
# 升级版本
|
||||
pip install -U adata -i http://mirrors.aliyun.com/pypi/simple/
|
||||
~~~
|
||||
|
||||
**注:国内镜像可能存在同步延迟,可使用官方镜像源**
|
||||
|
||||
#### 3.推荐镜像源列表
|
||||
|
||||
国内镜像源
|
||||
|
||||
阿里云【推荐】:http://mirrors.aliyun.com/pypi/simple/
|
||||
|
||||
清华大学:https://pypi.tuna.tsinghua.edu.cn/simple
|
||||
|
||||
官方镜像源
|
||||
|
||||
官方:https://pypi.org/simple
|
||||
|
||||
### (2)使用示例
|
||||
|
||||
#### 1. 获取股票代码信息
|
||||
|
||||
所有股票代码
|
||||
|
||||
~~~python
|
||||
import adata
|
||||
|
||||
res_df = adata.stock.info.all_code()
|
||||
print(res_df)
|
||||
~~~
|
||||
|
||||
示例结果:
|
||||
|
||||
~~~python
|
||||
stock_code short_name exchange
|
||||
0 001324 N长青科 SZ
|
||||
1 301361 众智科技 SZ
|
||||
2 300514 友讯达 SZ
|
||||
3 300880 迦南智能 SZ
|
||||
4 301368 丰立智能 SZ
|
||||
... ... ... ...
|
||||
5488 300325 德威退 SZ
|
||||
5489 300362 天翔退 SZ
|
||||
5490 300367 网力退 SZ
|
||||
5491 300372 欣泰退 SZ
|
||||
5492 300431 暴风退 SZ
|
||||
|
||||
[5493 rows x 3 columns]
|
||||
~~~
|
||||
|
||||
|
||||
|
||||
#### 2. 获取股票的行情
|
||||
|
||||
获取到股票代码,传入对应的stock_code,查询对应的股票行情
|
||||
|
||||
```python
|
||||
import adata
|
||||
|
||||
# k_type: k线类型:1.日;2.周;3.月 默认:1 日k
|
||||
res_df = adata.stock.market.get_market(stock_code='000001', k_type=1, start_date='2021-01-01')
|
||||
print(res_df)
|
||||
```
|
||||
|
||||
示例结果:
|
||||
|
||||
~~~
|
||||
trade_time open close ... pre_close stock_code trade_date
|
||||
0 2021-01-04 00:00:00 18.69 18.19 ... 18.93 000001 2021-01-04
|
||||
1 2021-01-05 00:00:00 17.99 17.76 ... 18.19 000001 2021-01-05
|
||||
2 2021-01-06 00:00:00 17.67 19.15 ... 17.76 000001 2021-01-06
|
||||
3 2021-01-07 00:00:00 19.11 19.49 ... 19.15 000001 2021-01-07
|
||||
4 2021-01-08 00:00:00 19.49 19.44 ... 19.49 000001 2021-01-08
|
||||
.. ... ... ... ... ... ... ...
|
||||
571 2023-05-16 00:00:00 12.80 12.62 ... 12.83 000001 2023-05-16
|
||||
572 2023-05-17 00:00:00 12.58 12.49 ... 12.62 000001 2023-05-17
|
||||
573 2023-05-18 00:00:00 12.57 12.49 ... 12.49 000001 2023-05-18
|
||||
574 2023-05-19 00:00:00 12.43 12.34 ... 12.49 000001 2023-05-19
|
||||
575 2023-05-22 00:00:00 12.31 12.38 ... 12.34 000001 2023-05-22
|
||||
|
||||
[576 rows :x 13 columns]
|
||||
~~~
|
||||
|
||||
|
||||
|
||||
#### 3. 其它数据使用
|
||||
|
||||
请参考下面数据列表和相关字典文档,找到对应的函数并查看对应的函数注释,进行正确使用。
|
||||
|
||||
- [字典DIC](./docs/DIC.md)
|
||||
|
||||
## 二、数据列表
|
||||
|
||||
整理了最新版本的数据列表和相关使用Api,详细内容和相关使用参数,请参考数据字典文档。
|
||||
|
||||
### (1)股票-Stock
|
||||
|
||||
#### 1. 基本信息
|
||||
|
||||
| 数据 | API | 说明 | 备注 |
|
||||
| ------------ | ------------------------------------ | ----------------------------- | ------------------------------------------------- |
|
||||
| A股代码 | stock.info.all_code() | 所有A股代码信息 | |
|
||||
| 概念代码 | stock.info.all_concept_code_ths() | 所有A股概念代码信息(同花顺) | 来源:同花顺公开数据 |
|
||||
| 概念成分列表 | stock.info.concept_constituent_ths() | 获取同花顺概念指数的成分股 | 注意:返回结果只有股票代码和股票简称,可根据概念名称查询 |
|
||||
| 股票交易日历 | stock.info.trade_calendar() | 获取股票交易日信息 | 来源:深交所 |
|
||||
|
||||
#### 2. 行情信息
|
||||
|
||||
| 数据 | API | 说明 | 备注 |
|
||||
| -------- | ------------------------------------------- | ------------------------------------- | ------------------------------------------------------------ |
|
||||
| 分红信息 | stock.market.get_dividend() | 获取单只股票的分红信息 | |
|
||||
| 股票行情 | stock.market.get_market() | 获取单只股票的行情信息-日、周、月 k线 | |
|
||||
| | stock.market.get_market_min() | 获取单个股票的今日分时行情 | 只能获取当天 |
|
||||
| | stock.market.list_market_current() | 获取多个股票最新行情信息 | 实时行情 |
|
||||
| 概念行情 | stock.market.get_market_concept_ths() | 获取单个概念的行情信息-日、周、月 k线 | 只有同花顺相关概念行情,<br />获取概念行情时,<br />请注意传入参数是指数代码还是概念代码,<br />指数代码8开头 |
|
||||
| | stock.market.get_market_concept_min_ths() | 获取同花顺概念行情当日分时 | 只能获取当天 |
|
||||
| | stock.market.get_market_concept_today_ths() | 获取同花顺当前的概念行情 | 实时行情 |
|
||||
|
||||
### (2)基金-ETF
|
||||
|
||||
| 项目 | 进度 | 说明 |
|
||||
| ------------------- | ------------ | ------------------------------ |
|
||||
| 主要指场内可交易ETF | 排期中...... | 若您有相关资源可以一起参与贡献 |
|
||||
|
||||
### (3)债券-Bond
|
||||
|
||||
| 项目 | 进度 | 说明 |
|
||||
| -------------------- | ------------ | ------------------------------ |
|
||||
| 主要指场内可转换债券 | 排期中...... | 若您有相关资源可以一起参与贡献 |
|
||||
|
||||
### (4)舆情
|
||||
|
||||
| 项目 | 进度 | 说明 |
|
||||
| ------------------------ | ------------ | ------------------------------ |
|
||||
| 主要指相关新闻和政策消息 | 排期中...... | 若您有相关资源可以一起参与贡献 |
|
||||
|
||||
## 三、数据源
|
||||
|
||||
感谢各位大厂提供的数据
|
||||
|
||||
| 数据源 | 板块 | 描述 |
|
||||
| ---------- | ------------------------------------------------------------ | ---------------- |
|
||||
| 同花顺 | [数据中心](http://data.10jqka.com.cn/),[行情中心](http://q.10jqka.com.cn/),[问财](http://www.iwencai.com/unifiedwap/home/index) | 让投资变的更简单 |
|
||||
| 百度股市通 | [股市通](https://gushitong.baidu.com/) | 科技让投资更简单 |
|
||||
| 东方财富 | [数据中心](https://data.eastmoney.com/center/),[行情中心](http://quote.eastmoney.com/center/) | 财经门户 |
|
||||
|
||||
|
||||
|
||||
## 四、 其它参考
|
||||
|
||||
主要记录查阅过的项目和相关平台,并对此项目产生了深远印象,特此鸣谢。
|
||||
|
||||
| [akshare](https://gitee.com/mirrors/akshare) | [聚宽量化](https://www.joinquant.com/) | [baostock](http://baostock.com/baostock/index.php/Python%E5%BC%80%E5%8F%91%E8%B5%84%E6%BA%90) | [MyData](http://api.mairui.club/hsdata.html) | |
|
||||
| -------------------------------------------- | -------------------------------------- | ------------------------------------------------------------ | -------------------------------------------- | ---- |
|
||||
|
||||
## 五、发布计划
|
||||
|
||||
| 版本号 | 内容 | 发布日期 | 备注 |
|
||||
| ------ | ---- | ------------ | ------------------------------ |
|
||||
| 0.x.x | 股票 | 2023-04-05 ~ | 预览版本 |
|
||||
| 1.x.x | 股票 | 2023-10-01 | 中国Ai股 |
|
||||
| 2.x.x | 基金 | 排期中 | 场内可交易基金:ETF |
|
||||
| 3.x.x | 债券 | 排期中 | 场内可交易债券:可转债 |
|
||||
| 4.x.x | 舆情 | 排期中 | 挖掘新闻、网络文章和政策事件等 |
|
||||
|
||||
|
||||
|
||||
## 参与贡献
|
||||
|
||||
1. Fork 本仓库
|
||||
2. 新建 Feat_xxx 分支
|
||||
3. 提交代码(注意代码风格和本项目一致即可)
|
||||
4. 新建 Pull Request
|
||||
|
||||
|
||||
## 特别鸣谢
|
||||
|
||||
> 对于项目有支持,包括但不仅限:内容贡献,bug提交,思想交流等等,对项目有影响的个人和机构
|
||||
|
||||
| Simon | |
|
||||
| ----- | ---- |
|
||||
|
7
__init__.py
Normal file
7
__init__.py
Normal file
@ -0,0 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: readme
|
||||
@author: 1nchaos
|
||||
@time: 2023/4/4
|
||||
@log: change log
|
||||
"""
|
27
adata/__init__.py
Normal file
27
adata/__init__.py
Normal file
@ -0,0 +1,27 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: adata
|
||||
@author: 1nchaos
|
||||
@time: 2023/4/4
|
||||
"""
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import logging
|
||||
|
||||
from .__version__ import __version__
|
||||
from .stock import stock
|
||||
|
||||
# set up logging
|
||||
logger = logging.getLogger("adata")
|
||||
|
||||
|
||||
def set_logger():
|
||||
format_string = "%(asctime)s - %(levelname)s - %(message)s"
|
||||
formatter = logging.Formatter(format_string, datefmt="%Y-%m-%dT%H:%M:%S")
|
||||
handler = logging.StreamHandler()
|
||||
handler.setFormatter(formatter)
|
||||
|
||||
logger.addHandler(handler)
|
||||
|
||||
|
||||
set_logger()
|
23
adata/__version__.py
Normal file
23
adata/__version__.py
Normal file
@ -0,0 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
VERSION = (0, 0, 17)
|
||||
# PRERELEASE = None # alpha, beta or rc
|
||||
PRERELEASE = 'beta' # alpha, beta or rc
|
||||
REVISION = None
|
||||
|
||||
|
||||
def generate_version(version, prerelease=None, revision=None):
|
||||
version_parts = [".".join(map(str, version))]
|
||||
if prerelease is not None:
|
||||
version_parts.append(f"-{prerelease}")
|
||||
if revision is not None:
|
||||
version_parts.append(f".{revision}")
|
||||
return "".join(version_parts)
|
||||
|
||||
__title__ = "adata"
|
||||
__description__ = "A Data,A Stock,ETF,Bond,Quant"
|
||||
__url__ = "https://gitee.com/inchaos/adata"
|
||||
__version__ = generate_version(VERSION, prerelease=PRERELEASE, revision=REVISION)
|
||||
__author__ = "1nchaos"
|
||||
__author_email__ = "9527@1nchaos.com"
|
||||
__license__ = "Apache License"
|
7
adata/bond/__init__.py
Normal file
7
adata/bond/__init__.py
Normal file
@ -0,0 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: 场内债券相关数据
|
||||
@author: 1nchaos
|
||||
@time: 2023/3/29
|
||||
@log: change log
|
||||
"""
|
14
adata/bond/bond_market.py
Normal file
14
adata/bond/bond_market.py
Normal file
@ -0,0 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc:
|
||||
@author: 1nchaos
|
||||
@time:2023/4/5
|
||||
@log:
|
||||
"""
|
||||
|
||||
|
||||
class BondMarket(object):
|
||||
"""bond 行情"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
9
adata/common/__init__.py
Normal file
9
adata/common/__init__.py
Normal file
@ -0,0 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: readme
|
||||
@author: 1nchaos
|
||||
@time: 2023/3/29
|
||||
@log: change log
|
||||
"""
|
||||
from .utils import *
|
||||
from .headers import *
|
7
adata/common/headers/__init__.py
Normal file
7
adata/common/headers/__init__.py
Normal file
@ -0,0 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: readme
|
||||
@author: 1nchaos
|
||||
@time: 2023/3/29
|
||||
@log: change log
|
||||
"""
|
39
adata/common/headers/baidu_headers.py
Normal file
39
adata/common/headers/baidu_headers.py
Normal file
@ -0,0 +1,39 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: readme
|
||||
@author: 1nchaos
|
||||
@time: 2023/3/29
|
||||
@log: change log
|
||||
"""
|
||||
|
||||
json_headers = {
|
||||
'Host': 'finance.pae.baidu.com',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0',
|
||||
'Accept': 'application/vnd.finance-web.v1+json',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
|
||||
'Accept-Encoding': 'gzip, deflate, br',
|
||||
'Acs-Token': '1680073602136_1680187152773_uZ76rU6tKjd6HavzqUwLS+LsRmCm+fagieEZzD622QiLe/Sfrq5cqVY6phLw7Vm/MGvLdp6eJI1R/Egp6PEB4E6agGNB91g61mfdylADtKBaq4zV4ZC/SOfrjh9TxMb6i6WwY5S1WFg/wPK2fPCoCZMkVSTJ704skNglDoLsPm+9RjCM4PJK68GKE7ZG1p13P5iAMk9ndAJ7HZ3FJAnBQCQeI82Q+fAOAtxrXtGf7eAoblBlgX7OaTJD97PIm9zy1yE37KVyfCngWZNp5VwP3OWGU6jCLeeq2vKpg2hS6TkgbUgqom57ZGSlIezfwQ7vltRiGG3cnpoPSBxrfiEXwz5iulsLGeubIzjOj1yYIBPWVYNBhSn7aM0P/dBq0Ug4cf3xmTvUI/GVMq9PXHGqBss1Px0Yl+hiSc1+vbgz7vQ=',
|
||||
'Origin': 'https://gushitong.baidu.com',
|
||||
'Connection': 'keep-alive',
|
||||
'Referer': 'https://gushitong.baidu.com/',
|
||||
'Cookie': 'BAIDUID=054924A85233268C182D09EC253E676F:SL=0:NR=10:FG=1; BIDUPSID=19DB8A6DEBD5A452CE6A10E90276DE7C; PSTM=1572438578; MCITY=-75%3A; BDUSS=V-UmF5S1pXNVd1Um15S0Y1MXc0S20wZ3FGYzhIVjlUZUFoczVvRlVjUTB1dTVnRVFBQUFBJCQAAAAAAAAAAAEAAADIruQqaV~EwdPjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQtx2A0LcdgS3; __yjs_duid=1_0e624b9d24290650971c8590bcfe96361619270097027; ZFY=KxKVSFoJLIz0l23rNHW:AV1udt6Ern2XM0p4sN7:AJdw8:C; H_PS_PSSID=38185_36546_38409_38470_38439_38468_38289_38380_37931_38382_26350_22157_38282_37881; BDRCVFR[feWj1Vr5u3D]=I67x6TjHwwYf0; delPer=0; PSINO=6; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; ZD_ENTRY=baidu; __bid_n=184332335315a549634207; FPTOKEN=0G8DZh7ruaz1dUnw7eFAGwkkafhUBvTOkCNkScDsJi6ucyCKBDttk2Tv233PFjFcYDQH/nqo0eEZY9g0psSI5FwqsV/lPlXLoPcGR6EQ3I9iV5fhRVGwx/xKTmJ1O7b09GcBwac2qYSO1tDSfR20KFkYKdZihCdiCAHUPhhniaMVTFa/d2JywSFgXh5ksnMGNkQXY0fS8bKzsP/UTJdtSvg8J8WuYoh7g6EDHeXRVlt5t13dTO8A6DMCNOYlxzGLSDomP/3UOsH+T/4iGsNubZL+y3016UY0ehJa8meg2mAq+wS0DdmsJxYao0qTDaAT/5LfNM4j3LoVRAMUYtOzM/9V4ajJfK7atGKQXFSn+VnANgwuvUvfZGCOdF8oMn4N7Jv6jvQ5XocYTAOb7MZJgOocxgPsL5zDGIcXYmUPAxoPn2/9SsgFLR4mxU+D++F9|c5qXUXOqFRs5f/aOsOlP9AY4If8rgdZFdcLJjdaX0Is=|10|3c9b5f41e931d2d8783fbcce14863165; BAIDU_WISE_UID=wapp_1680175629815_954; arialoadData=false; BCLID=8799370053103418941; BCLID_BFESS=8799370053103418941; BDSFRCVID=A1tOJeC62wVF227f5qXouQCuMHnCdsrTH6aoWSjyl4QjjjGKIQ2REG0Pnf8g0KuMn6bMogKKXgOTHw0F_2uxOjjg8UtVJeC6EG0Ptf8g0f5; BDSFRCVID_BFESS=A1tOJeC62wVF227f5qXouQCuMHnCdsrTH6aoWSjyl4QjjjGKIQ2REG0Pnf8g0KuMn6bMogKKXgOTHw0F_2uxOjjg8UtVJeC6EG0Ptf8g0f5; H_BDCLCKID_SF=JnIOoCIMtID3qnFkKJL_-P4DePLD-URZ5mAqot3C3D_KMnLGKq7o5q_d5tc72fJb-5rnaIQqaM36j4T1jhQ8M4I1yPrIJqj43bRTWJLy5KJvfq6kj45YhP-Uyn7MWh37bbRlMKoaMp78jR093JO4y4Ldj4oxJpOJ5JbMonLafJOKHICweMK; H_BDCLCKID_SF_BFESS=JnIOoCIMtID3qnFkKJL_-P4DePLD-URZ5mAqot3C3D_KMnLGKq7o5q_d5tc72fJb-5rnaIQqaM36j4T1jhQ8M4I1yPrIJqj43bRTWJLy5KJvfq6kj45YhP-Uyn7MWh37bbRlMKoaMp78jR093JO4y4Ldj4oxJpOJ5JbMonLafJOKHICweMK',
|
||||
'Sec-Fetch-Dest': 'empty',
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
'Sec-Fetch-Site': 'same-site',
|
||||
'TE': 'trailers',
|
||||
}
|
||||
|
||||
text_headers = {
|
||||
'Host': 'gushitong.baidu.com',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0',
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
|
||||
'Accept-Encoding': 'gzip, deflate, br',
|
||||
'Connection': 'keep-alive',
|
||||
'Cookie': 'BAIDUID=DC08E09E609EB9778F0574D4518A5507:SL=0:NR=10:FG=1; BIDUPSID=72A958B07427F9F9CB3F63FD8B6C6565; PSTM=1677461180; MCITY=-%3A; BDUSS=toZjl2NTY0NFNwQWVyaUpFREJlSS1NWmVranN5YzdMSXpEcTZkNTRaTjA4amhrSVFBQUFBJCQAAAAAAAAAAAEAAADIruQqaV~EwdPjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHRlEWR0ZRFkN0; H_PS_PSSID=38185_36554_38470_38353_38359_38396_38468_38289_36807_38263_37929_38382_26350_38421_38283_37881; BDSFRCVID=5OPOJexroG07v97fK16bU1LKNeKK0PQTDYrEeU9ooveGPK0Vc8uvEG0PtDQMefIb1DMtogKKXgOTHw0F_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF=tJPf_CK5JIL3H48k-4QEbbQH-UnLq-jyBgOZ04n-ah02MI5Y04jBynDv3HQrBM69agQN_hcm3UTdsq76Wh35K5tTQP6rLtJHHG74KKJxbn7EKDjHLP5DDbLehUJiBhvMBan7LKJIXKohJh7FM4tW3J0ZyxomtfQxtNRJ0DnjtpChbC_mjT_hjT3BeU5eetjK2CntsJOOaCv-ht5Oy4oWK441DattaljhMm3P5fKhBpvF8nR_06Jk3M04X-o9-hvT-54e2p3FBUQjq66bQft20b0eMeFD0xJaKJRtWb7jWhviep72ybt2QlRX5q79atTMfNTJ-qcH0KQpsIJM5-DWbT8IjHCHtT-tJRkJ_Dvt-5rDHJTg5DTjhPrMyxCjWMT-MTryKKt5JRTCe4To3JblDfAUX4nQBqDfWHnRhlRNB-3iV-OxDUvnyxAZ-pKLQMQxtNRJWbIEtl5THR_x5tnobUPUWMJ9LUvftgcdot5yBbc8eIna5hjkbfJBQttjQn3hfIkj2CKLtK-WbK_wj6t3-t0_qx5Ka43tHD7yWCvdMU7cOR5Jj65ED5-sbx5hBM3kKaID2pvkbUnDSbIC3MA--t4YKGJeQUJ82TAHhDoD5qcHsq0x0h3We-bQypouQb_H0COMahv95h7xO-0xQlPK5JkgMx6MqpQJQeQ-5KQN3KJmfbL9bT3tjjTXjH8JJ60ttR3MB4bH56rjDnCrjfnmXUI82h5y058fbJKf0qkhJJolhqRoX4ovyT8r0JORXRj45GI8Wb7K5l3mOIJK-T7h5xL1Db3J0pou5CcA3DjgB4boepvoW-Jc3MkWD-jdJJQOBKQB0KnGbUQkeq8CQft20b0EeMtjW6LEK5r2SC_XtKDh3j; Hm_lvt_c8bd3584daa59ca83c2ec1247d343576=1679365029; Hm_lpvt_c8bd3584daa59ca83c2ec1247d343576=1680096200; BDORZ=FFFB88E999055A3F8A630C64834BD6D0; ab_sr=1.0.1_OTVlZTQ5MzFhYTMyY2FjZTY5M2NiYTJjMzUwMTVkNTE0OGM1MzUwMWQzZjk4NTNjMmE5NjJiODM3OGI2MzFlNWFlMDZjOTYzNWIxOTE0MmY2MzI4YjM0OGMwNGFmN2NmNzg1MjA1M2E2ODUwYzFlNmI4NThiZmRlNWJiMmU0NDMwOGI0MDY1ZGRiODNjZWM3ZjY0ZDhlM2VmNjIzYTdlOQ==; BA_HECTOR=24akak252l042g848500208u1i28dic1n; delPer=0; PSINO=7; ZFY=a4MO01qoxt3fSy8GE2fVF3isnJZvFcG4BOxTOLYMkmo:C; BDRCVFR[gltLrB7qNCt]=mk3SLVN4HKm',
|
||||
'Upgrade-Insecure-Requests': '1',
|
||||
'Sec-Fetch-Dest': 'document',
|
||||
'Sec-Fetch-Mode': 'navigate',
|
||||
'Sec-Fetch-Site': 'none',
|
||||
'Sec-Fetch-User': '?1',
|
||||
}
|
19
adata/common/headers/sina_headers.py
Normal file
19
adata/common/headers/sina_headers.py
Normal file
@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: readme
|
||||
@author: 1nchaos
|
||||
@time: 2023/3/29
|
||||
@log: change log
|
||||
"""
|
||||
c_headers = {
|
||||
'Host': 'hq.sinajs.cn',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0',
|
||||
'Accept': '*/*',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
|
||||
'Accept-Encoding': 'gzip, deflate, br',
|
||||
'Referer': 'http://vip.stock.finance.sina.com.cn/',
|
||||
'Connection': 'keep-alive',
|
||||
'Sec-Fetch-Dest': 'script',
|
||||
'Sec-Fetch-Mode': 'no-cors',
|
||||
'Sec-Fetch-Site': 'cross-site',
|
||||
}
|
40
adata/common/headers/ths_headers.py
Normal file
40
adata/common/headers/ths_headers.py
Normal file
@ -0,0 +1,40 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: readme
|
||||
@author: 1nchaos
|
||||
@time: 2023/3/29
|
||||
@log: change log
|
||||
"""
|
||||
c_headers = {
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
|
||||
'Accept-Encoding': 'gzip, deflate',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.9',
|
||||
'Cache-Control': 'max-age=0',
|
||||
'Connection': 'keep-alive',
|
||||
'Cookie': 'SL_G_WPT_TO=eo; SL_GWPT_Show_Hide_tmp=1; SL_wptGlobTipTmp=1',
|
||||
'Host': 'search.10jqka.com.cn',
|
||||
'Upgrade-Insecure-Requests': '1',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
|
||||
}
|
||||
|
||||
json_headers = {
|
||||
'Host': 'q.10jqka.com.cn',
|
||||
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:105.0) Gecko/20100101 Firefox/105.0',
|
||||
'Accept': '*/*',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
|
||||
'Accept-Encoding': 'gzip, deflate',
|
||||
'Connection': 'keep-alive',
|
||||
'Cookie': 'v=AzCSZkisIBam9fwSniGPJndtB_-HeRW6Nl9qaSqB_nJczN4r0onkU4ZtOEN5; __bid_n=18484da3254140db6d4207; Hm_lvt_78c58f01938e4d85eaf619eae71b4ed1=1680163246; FPTOKEN=E5SR2waOvFusCzMCQVA/i0npfLNEl6RajFMppa8aoQmLTnIl68wGldxUBmPM57Q9yOCUCB1aiKbuSjFdBzV5SnHNhe0uSYQIfJ9t5YdBrYTHtRO06p0Kjf3ck0dxo587GXZ/Lln6kY2EoiWCZBlXHLfwWq6d/uLzQfq+BnkeN8y5zWt6kJAzY84fZaTCNQPf4Vae5qHOYpskzus+szaS5Qm2VNc/Q/t/0U7QQADRzNRLfYf6A/407ZMdD6+1sGvCQhh959iGl+DRavRasWH2ISY3G/osl/olB61tXSIxNI+IL+rAu7u5TvknHHwVtcigMY4jsgE8qBkN2HU4wDvH5QMv+0E89L5jACYIF+BoMaBNN6VkPt9Pksg8+K6O4K9rwElcjiWRuyzNy25YO13lYQ==|sPeLn4kqSDrmYnpF7Wn94V4caIa/qNc5YWTtvQFK+ac=|10|2bc6aba78093d71b50d1b70dd20ef09d; Hm_lpvt_78c58f01938e4d85eaf619eae71b4ed1=1680163469',
|
||||
'Upgrade-Insecure-Requests': '1',
|
||||
}
|
||||
|
||||
text_headers = {
|
||||
'Host': 'q.10jqka.com.cn',
|
||||
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:105.0) Gecko/20100101 Firefox/105.0',
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
|
||||
'Accept-Encoding': 'gzip, deflate',
|
||||
'Connection': 'keep-alive',
|
||||
'Cookie': 'v=AzCSZkisIBam9fwSniGPJndtB_-HeRW6Nl9qaSqB_nJczN4r0onkU4ZtOEN5; __bid_n=18484da3254140db6d4207; Hm_lvt_78c58f01938e4d85eaf619eae71b4ed1=1680163246; FPTOKEN=E5SR2waOvFusCzMCQVA/i0npfLNEl6RajFMppa8aoQmLTnIl68wGldxUBmPM57Q9yOCUCB1aiKbuSjFdBzV5SnHNhe0uSYQIfJ9t5YdBrYTHtRO06p0Kjf3ck0dxo587GXZ/Lln6kY2EoiWCZBlXHLfwWq6d/uLzQfq+BnkeN8y5zWt6kJAzY84fZaTCNQPf4Vae5qHOYpskzus+szaS5Qm2VNc/Q/t/0U7QQADRzNRLfYf6A/407ZMdD6+1sGvCQhh959iGl+DRavRasWH2ISY3G/osl/olB61tXSIxNI+IL+rAu7u5TvknHHwVtcigMY4jsgE8qBkN2HU4wDvH5QMv+0E89L5jACYIF+BoMaBNN6VkPt9Pksg8+K6O4K9rwElcjiWRuyzNy25YO13lYQ==|sPeLn4kqSDrmYnpF7Wn94V4caIa/qNc5YWTtvQFK+ac=|10|2bc6aba78093d71b50d1b70dd20ef09d; Hm_lpvt_78c58f01938e4d85eaf619eae71b4ed1=1680163469',
|
||||
'Upgrade-Insecure-Requests': '1',
|
||||
}
|
7
adata/common/js/__init__.py
Normal file
7
adata/common/js/__init__.py
Normal file
@ -0,0 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: js
|
||||
@author: 1nchaos
|
||||
@time: 2023/5/5
|
||||
@log: change log
|
||||
"""
|
6031
adata/common/js/covid.js
Normal file
6031
adata/common/js/covid.js
Normal file
File diff suppressed because it is too large
Load Diff
139
adata/common/js/crypto.js
Normal file
139
adata/common/js/crypto.js
Normal file
@ -0,0 +1,139 @@
|
||||
function Base64() {
|
||||
_keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", this.encode = function(a) {
|
||||
var c, d, e, f, g, h, i, b = "",
|
||||
j = 0;
|
||||
for (a = _utf8_encode(a); j < a.length;) c = a.charCodeAt(j++), d = a.charCodeAt(j++), e = a.charCodeAt(j++), f = c >> 2, g = (3 & c) << 4 | d >> 4, h = (15 & d) << 2 | e >> 6, i = 63 & e, isNaN(d) ? h = i = 64 : isNaN(e) && (i = 64), b = b + _keyStr.charAt(f) + _keyStr.charAt(g) + _keyStr.charAt(h) + _keyStr.charAt(i);
|
||||
return b
|
||||
}, this.decode = function(a) {
|
||||
var c, d, e, f, g, h, i, b = "",
|
||||
j = 0;
|
||||
for (a = a.replace(/[^A-Za-z0-9\+\/\=]/g, ""); j < a.length;) f = _keyStr.indexOf(a.charAt(j++)), g = _keyStr.indexOf(a.charAt(j++)), h = _keyStr.indexOf(a.charAt(j++)), i = _keyStr.indexOf(a.charAt(j++)), c = f << 2 | g >> 4, d = (15 & g) << 4 | h >> 2, e = (3 & h) << 6 | i, b += String.fromCharCode(c), 64 != h && (b += String.fromCharCode(d)), 64 != i && (b += String.fromCharCode(e));
|
||||
return b = _utf8_decode(b)
|
||||
}, _utf8_encode = function(a) {
|
||||
var b, c, d;
|
||||
for (a = a.replace(/\r\n/g, "\n"), b = "", c = 0; c < a.length; c++) d = a.charCodeAt(c), 128 > d ? b += String.fromCharCode(d) : d > 127 && 2048 > d ? (b += String.fromCharCode(192 | d >> 6), b += String.fromCharCode(128 | 63 & d)) : (b += String.fromCharCode(224 | d >> 12), b += String.fromCharCode(128 | 63 & d >> 6), b += String.fromCharCode(128 | 63 & d));
|
||||
return b
|
||||
}, _utf8_decode = function(a) {
|
||||
for (var b = "", c = 0, d = c1 = c2 = 0; c < a.length;) d = a.charCodeAt(c), 128 > d ? (b += String.fromCharCode(d), c++) : d > 191 && 224 > d ? (c2 = a.charCodeAt(c + 1), b += String.fromCharCode((31 & d) << 6 | 63 & c2), c += 2) : (c2 = a.charCodeAt(c + 1), c3 = a.charCodeAt(c + 2), b += String.fromCharCode((15 & d) << 12 | (63 & c2) << 6 | 63 & c3), c += 3);
|
||||
return b
|
||||
}
|
||||
}
|
||||
|
||||
function hex_md5(a) {
|
||||
return binl2hex(core_md5(str2binl(a), a.length * chrsz))
|
||||
}
|
||||
|
||||
function b64_md5(a) {
|
||||
return binl2b64(core_md5(str2binl(a), a.length * chrsz))
|
||||
}
|
||||
|
||||
function str_md5(a) {
|
||||
return binl2str(core_md5(str2binl(a), a.length * chrsz))
|
||||
}
|
||||
|
||||
function hex_hmac_md5(a, b) {
|
||||
return binl2hex(core_hmac_md5(a, b))
|
||||
}
|
||||
|
||||
function b64_hmac_md5(a, b) {
|
||||
return binl2b64(core_hmac_md5(a, b))
|
||||
}
|
||||
|
||||
function str_hmac_md5(a, b) {
|
||||
return binl2str(core_hmac_md5(a, b))
|
||||
}
|
||||
|
||||
function md5_vm_test() {
|
||||
return "900150983cd24fb0d6963f7d28e17f72" == hex_md5("abc")
|
||||
}
|
||||
|
||||
function core_md5(a, b) {
|
||||
var c, d, e, f, g, h, i, j, k;
|
||||
for (a[b >> 5] |= 128 << b % 32, a[(b + 64 >>> 9 << 4) + 14] = b, c = 1732584193, d = -271733879, e = -1732584194, f = 271733878, g = 0; g < a.length; g += 16) h = c, i = d, j = e, k = f, c = md5_ff(c, d, e, f, a[g + 0], 7, -680876936), f = md5_ff(f, c, d, e, a[g + 1], 12, -389564586), e = md5_ff(e, f, c, d, a[g + 2], 17, 606105819), d = md5_ff(d, e, f, c, a[g + 3], 22, -1044525330), c = md5_ff(c, d, e, f, a[g + 4], 7, -176418897), f = md5_ff(f, c, d, e, a[g + 5], 12, 1200080426), e = md5_ff(e, f, c, d, a[g + 6], 17, -1473231341), d = md5_ff(d, e, f, c, a[g + 7], 22, -45705983), c = md5_ff(c, d, e, f, a[g + 8], 7, 1770035416), f = md5_ff(f, c, d, e, a[g + 9], 12, -1958414417), e = md5_ff(e, f, c, d, a[g + 10], 17, -42063), d = md5_ff(d, e, f, c, a[g + 11], 22, -1990404162), c = md5_ff(c, d, e, f, a[g + 12], 7, 1804603682), f = md5_ff(f, c, d, e, a[g + 13], 12, -40341101), e = md5_ff(e, f, c, d, a[g + 14], 17, -1502002290), d = md5_ff(d, e, f, c, a[g + 15], 22, 1236535329), c = md5_gg(c, d, e, f, a[g + 1], 5, -165796510), f = md5_gg(f, c, d, e, a[g + 6], 9, -1069501632), e = md5_gg(e, f, c, d, a[g + 11], 14, 643717713), d = md5_gg(d, e, f, c, a[g + 0], 20, -373897302), c = md5_gg(c, d, e, f, a[g + 5], 5, -701558691), f = md5_gg(f, c, d, e, a[g + 10], 9, 38016083), e = md5_gg(e, f, c, d, a[g + 15], 14, -660478335), d = md5_gg(d, e, f, c, a[g + 4], 20, -405537848), c = md5_gg(c, d, e, f, a[g + 9], 5, 568446438), f = md5_gg(f, c, d, e, a[g + 14], 9, -1019803690), e = md5_gg(e, f, c, d, a[g + 3], 14, -187363961), d = md5_gg(d, e, f, c, a[g + 8], 20, 1163531501), c = md5_gg(c, d, e, f, a[g + 13], 5, -1444681467), f = md5_gg(f, c, d, e, a[g + 2], 9, -51403784), e = md5_gg(e, f, c, d, a[g + 7], 14, 1735328473), d = md5_gg(d, e, f, c, a[g + 12], 20, -1926607734), c = md5_hh(c, d, e, f, a[g + 5], 4, -378558), f = md5_hh(f, c, d, e, a[g + 8], 11, -2022574463), e = md5_hh(e, f, c, d, a[g + 11], 16, 1839030562), d = md5_hh(d, e, f, c, a[g + 14], 23, -35309556), c = md5_hh(c, d, e, f, a[g + 1], 4, -1530992060), f = md5_hh(f, c, d, e, a[g + 4], 11, 1272893353), e = md5_hh(e, f, c, d, a[g + 7], 16, -155497632), d = md5_hh(d, e, f, c, a[g + 10], 23, -1094730640), c = md5_hh(c, d, e, f, a[g + 13], 4, 681279174), f = md5_hh(f, c, d, e, a[g + 0], 11, -358537222), e = md5_hh(e, f, c, d, a[g + 3], 16, -722521979), d = md5_hh(d, e, f, c, a[g + 6], 23, 76029189), c = md5_hh(c, d, e, f, a[g + 9], 4, -640364487), f = md5_hh(f, c, d, e, a[g + 12], 11, -421815835), e = md5_hh(e, f, c, d, a[g + 15], 16, 530742520), d = md5_hh(d, e, f, c, a[g + 2], 23, -995338651), c = md5_ii(c, d, e, f, a[g + 0], 6, -198630844), f = md5_ii(f, c, d, e, a[g + 7], 10, 1126891415), e = md5_ii(e, f, c, d, a[g + 14], 15, -1416354905), d = md5_ii(d, e, f, c, a[g + 5], 21, -57434055), c = md5_ii(c, d, e, f, a[g + 12], 6, 1700485571), f = md5_ii(f, c, d, e, a[g + 3], 10, -1894986606), e = md5_ii(e, f, c, d, a[g + 10], 15, -1051523), d = md5_ii(d, e, f, c, a[g + 1], 21, -2054922799), c = md5_ii(c, d, e, f, a[g + 8], 6, 1873313359), f = md5_ii(f, c, d, e, a[g + 15], 10, -30611744), e = md5_ii(e, f, c, d, a[g + 6], 15, -1560198380), d = md5_ii(d, e, f, c, a[g + 13], 21, 1309151649), c = md5_ii(c, d, e, f, a[g + 4], 6, -145523070), f = md5_ii(f, c, d, e, a[g + 11], 10, -1120210379), e = md5_ii(e, f, c, d, a[g + 2], 15, 718787259), d = md5_ii(d, e, f, c, a[g + 9], 21, -343485551), c = safe_add(c, h), d = safe_add(d, i), e = safe_add(e, j), f = safe_add(f, k);
|
||||
return Array(c, d, e, f)
|
||||
}
|
||||
|
||||
function md5_cmn(a, b, c, d, e, f) {
|
||||
return safe_add(bit_rol(safe_add(safe_add(b, a), safe_add(d, f)), e), c)
|
||||
}
|
||||
|
||||
function md5_ff(a, b, c, d, e, f, g) {
|
||||
return md5_cmn(b & c | ~b & d, a, b, e, f, g)
|
||||
}
|
||||
|
||||
function md5_gg(a, b, c, d, e, f, g) {
|
||||
return md5_cmn(b & d | c & ~d, a, b, e, f, g)
|
||||
}
|
||||
|
||||
function md5_hh(a, b, c, d, e, f, g) {
|
||||
return md5_cmn(b ^ c ^ d, a, b, e, f, g)
|
||||
}
|
||||
|
||||
function md5_ii(a, b, c, d, e, f, g) {
|
||||
return md5_cmn(c ^ (b | ~d), a, b, e, f, g)
|
||||
}
|
||||
|
||||
function core_hmac_md5(a, b) {
|
||||
var d, e, f, g, c = str2binl(a);
|
||||
for (c.length > 16 && (c = core_md5(c, a.length * chrsz)), d = Array(16), e = Array(16), f = 0; 16 > f; f++) d[f] = 909522486 ^ c[f], e[f] = 1549556828 ^ c[f];
|
||||
return g = core_md5(d.concat(str2binl(b)), 512 + b.length * chrsz), core_md5(e.concat(g), 640)
|
||||
}
|
||||
|
||||
function safe_add(a, b) {
|
||||
var c = (65535 & a) + (65535 & b),
|
||||
d = (a >> 16) + (b >> 16) + (c >> 16);
|
||||
return d << 16 | 65535 & c
|
||||
}
|
||||
|
||||
function bit_rol(a, b) {
|
||||
return a << b | a >>> 32 - b
|
||||
}
|
||||
|
||||
function str2binl(a) {
|
||||
var d, b = Array(),
|
||||
c = (1 << chrsz) - 1;
|
||||
for (d = 0; d < a.length * chrsz; d += chrsz) b[d >> 5] |= (a.charCodeAt(d / chrsz) & c) << d % 32;
|
||||
return b
|
||||
}
|
||||
|
||||
function binl2str(a) {
|
||||
var d, b = "",
|
||||
c = (1 << chrsz) - 1;
|
||||
for (d = 0; d < 32 * a.length; d += chrsz) b += String.fromCharCode(a[d >> 5] >>> d % 32 & c);
|
||||
return b
|
||||
}
|
||||
|
||||
function binl2hex(a) {
|
||||
var d, b = hexcase ? "0123456789ABCDEF" : "0123456789abcdef",
|
||||
c = "";
|
||||
for (d = 0; d < 4 * a.length; d++) c += b.charAt(15 & a[d >> 2] >> 8 * (d % 4) + 4) + b.charAt(15 & a[d >> 2] >> 8 * (d % 4));
|
||||
return c
|
||||
}
|
||||
|
||||
function binl2b64(a) {
|
||||
var d, e, f, b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
|
||||
c = "";
|
||||
for (d = 0; d < 4 * a.length; d += 3)
|
||||
for (e = (255 & a[d >> 2] >> 8 * (d % 4)) << 16 | (255 & a[d + 1 >> 2] >> 8 * ((d + 1) % 4)) << 8 | 255 & a[d + 2 >> 2] >> 8 * ((d + 2) % 4), f = 0; 4 > f; f++) c += 8 * d + 6 * f > 32 * a.length ? b64pad : b.charAt(63 & e >> 6 * (3 - f));
|
||||
return c
|
||||
}
|
||||
|
||||
function encode_param(a) {
|
||||
var b = new Base64;
|
||||
return b.encode(a)
|
||||
}
|
||||
|
||||
function encode_secret() {
|
||||
var b, a = appId;
|
||||
for (b = 0; b < arguments.length; b++) a += arguments[b];
|
||||
return a = a.replace(/\s/g, ""), hex_md5(a)
|
||||
}
|
||||
|
||||
function decode_result(a) {
|
||||
var b = new Base64;
|
||||
return b.decode(b.decode(b.decode(a)))
|
||||
}
|
||||
var hexcase = 0,
|
||||
b64pad = "",
|
||||
chrsz = 8,
|
||||
appId = "a01901d3caba1f362d69474674ce477f";
|
4900
adata/common/js/outcrypto.js
Normal file
4900
adata/common/js/outcrypto.js
Normal file
File diff suppressed because it is too large
Load Diff
989
adata/common/js/ths.js
Normal file
989
adata/common/js/ths.js
Normal file
@ -0,0 +1,989 @@
|
||||
var TOKEN_SERVER_TIME = 1572845499.629;
|
||||
function v_cookie (r, n, t, e, a) {
|
||||
var u = n[0],
|
||||
c = n[1],
|
||||
v = a[0],
|
||||
s = t[0],
|
||||
f = t[1],
|
||||
l = r[0],
|
||||
d = hr(a[1], e[0], t[2]),
|
||||
p = t[3],
|
||||
h = e[1],
|
||||
g = yr(a[2], a[3], e[2]),
|
||||
m = yr(a[4], r[1], t[4]),
|
||||
w = r[2],
|
||||
I = a[5],
|
||||
_ = a[6],
|
||||
y = a[7],
|
||||
E = hr(n[2], r[3], r[4]),
|
||||
A = t[5],
|
||||
C = e[3],
|
||||
b = e[4],
|
||||
B = t[6],
|
||||
R = a[8],
|
||||
T = a[9],
|
||||
S = n[3],
|
||||
k = t[7],
|
||||
x = t[8],
|
||||
O = a[10],
|
||||
L = n[4],
|
||||
M = n[5],
|
||||
N = a[11],
|
||||
P = e[5],
|
||||
j = hr(n[6], e[6], t[9], r[5]),
|
||||
D = t[10],
|
||||
W = e[7],
|
||||
$ = r[6],
|
||||
F = yr(r[7], t[11], e[8], n[7]),
|
||||
X = r[8],
|
||||
H = t[12],
|
||||
K = r[9],
|
||||
U = n[8],
|
||||
V = e[9],
|
||||
Y = r[10],
|
||||
J = e[10],
|
||||
q = r[11],
|
||||
Q = a[12],
|
||||
Z = n[9],
|
||||
G = t[13],
|
||||
z = t[14],
|
||||
rr = t[15],
|
||||
nr = n[10],
|
||||
tr = a[13],
|
||||
er = a[14],
|
||||
ar = e[11],
|
||||
or = r[12],
|
||||
ir = yr(t[16], r[13], r[14], r[15]),
|
||||
ur = t[17],
|
||||
cr = t[18];
|
||||
function vr () {
|
||||
var r = arguments[n[11]];
|
||||
return r.split(n[12]).reverse().join(e[12])
|
||||
}
|
||||
var sr = [new e[13](hr(a[15], n[13], a[16])), new e[13](a[17])];
|
||||
function fr () {
|
||||
var n = arguments[a[18]];
|
||||
if (!n) return a[19];
|
||||
for (var o = t[19], i = e[14], u = e[15]; u < n.length; u++)
|
||||
{
|
||||
var c = n.charCodeAt(u),
|
||||
v = c ^ i;
|
||||
i = c,
|
||||
o += r[16].fromCharCode(v)
|
||||
}
|
||||
return o
|
||||
}
|
||||
var lr = '',
|
||||
dr; !
|
||||
function (o) {
|
||||
var i = e[18],
|
||||
c = e[19];
|
||||
o[e[20]] = a[21];
|
||||
function v (t, a, o, i, u) {
|
||||
var c, v, s;
|
||||
c = v = s = r;
|
||||
var f, l, d;
|
||||
f = l = d = n;
|
||||
var p, h, g;
|
||||
p = h = g = e;
|
||||
var m = t + g[21] + a;
|
||||
i && (m += l[15] + i),
|
||||
u && (m += h[22] + u),
|
||||
o && (m += v[17] + o),
|
||||
l[14][g[23]] = m
|
||||
}
|
||||
o[e[24]] = l;
|
||||
function s (t, e, a) {
|
||||
var o = n[16];
|
||||
this.setCookie(t, r[18], i + o + c, e, a)
|
||||
}
|
||||
o[t[22]] = f;
|
||||
function f (o) {
|
||||
var i = vr(e[25], a[22]),
|
||||
c = a[23][n[17]],
|
||||
v = u + i + o + t[23],
|
||||
s = '';
|
||||
if (s == -r[19])
|
||||
{
|
||||
if (v = o + t[23], c.substr(a[24], v.length) != v) return;
|
||||
s = a[24]
|
||||
}
|
||||
var f = s + v[r[20]],
|
||||
l = '';
|
||||
return l == -e[26] && (l = c[t[24]])
|
||||
|
||||
}
|
||||
o[e[27]] = v;
|
||||
function l () {
|
||||
var r, t, a;
|
||||
r = t = a = e;
|
||||
var i, u, c;
|
||||
i = u = c = n;
|
||||
var v = u[18];
|
||||
this.setCookie(v, a[28]),
|
||||
this.getCookie(v) || (o[i[19]] = u[20]),
|
||||
this.delCookie(v)
|
||||
}
|
||||
o[n[21]] = s
|
||||
}(dr || (dr = {}));
|
||||
var pr;
|
||||
function hr () {
|
||||
var r = arguments[a[25]];
|
||||
if (!r) return a[19];
|
||||
for (var e = a[19], o = t[25], i = n[22], u = t[18]; u < r.length; u++)
|
||||
{
|
||||
var c = r.charCodeAt(u);
|
||||
i = (i + t[26]) % o.length,
|
||||
c ^= o.charCodeAt(i),
|
||||
e += String.fromCharCode(c)
|
||||
}
|
||||
return e
|
||||
} !
|
||||
function (o) {
|
||||
var i, u, d;
|
||||
i = u = d = a;
|
||||
var p, h, g;
|
||||
p = h = g = t;
|
||||
var m, w, I;
|
||||
m = w = I = r;
|
||||
var _, y, E;
|
||||
_ = y = E = n;
|
||||
var b, B, R;
|
||||
b = B = R = e;
|
||||
var T = B[29],
|
||||
S = y[23],
|
||||
k = m[22],
|
||||
x = w[0],
|
||||
O = E[24],
|
||||
L = (C, Ar, R[30]),
|
||||
M = b[31],
|
||||
N = T + S,
|
||||
P = p[28],
|
||||
j,
|
||||
W = m[23][y[25]],
|
||||
$,
|
||||
F;
|
||||
function X (r) {
|
||||
return function () {
|
||||
F.appendChild(j),
|
||||
j.addBehavior(u[26]),
|
||||
j.load(N);
|
||||
var n = r();
|
||||
return F.removeChild(j),
|
||||
n
|
||||
}
|
||||
}
|
||||
function H () {
|
||||
var r = A;
|
||||
r = D;
|
||||
try
|
||||
{
|
||||
return !!(N in B[32] && b[32][N])
|
||||
} catch (n)
|
||||
{
|
||||
return void B[15]
|
||||
}
|
||||
}
|
||||
function K (r) {
|
||||
return P ? G(r) : j ? Y(r) : void _[26]
|
||||
}
|
||||
function U () {
|
||||
if (P = H(), P) j = _[27][N];
|
||||
else if (W[k + c][I[24]]) try
|
||||
{
|
||||
$ = new ActiveXObject(vr(I[25], y[28], w[26])),
|
||||
$.open(),
|
||||
$.write(y[29]),
|
||||
$.close(),
|
||||
F = $.w[B[33]][I[27]][_[30]],
|
||||
j = F.createElement(I[28])
|
||||
} catch (r)
|
||||
{
|
||||
j = W.createElement(N),
|
||||
F = W[vr(I[29], d[27])] || W.getElementsByTagName(b[17])[I[27]] || W[m[30]]
|
||||
}
|
||||
}
|
||||
o[w[31]] = U;
|
||||
function V (r, n) {
|
||||
var t = J;
|
||||
if (void 0 === n) return Z(r);
|
||||
if (t = sr, P) z(r, n);
|
||||
else
|
||||
{
|
||||
if (!j) return void B[15];
|
||||
Q(r, n)
|
||||
}
|
||||
}
|
||||
o[v + x] = V;
|
||||
function Y (r) {
|
||||
X(function () {
|
||||
return r = J(r),
|
||||
j.getAttribute(r)
|
||||
})()
|
||||
}
|
||||
function J (r) {
|
||||
var n = z;
|
||||
n = v;
|
||||
var t = vr(Ir, w[32]),
|
||||
e = new y[31](t + O + s + L, b[31]);
|
||||
return r.replace(new B[13](d[28]), b[34]).replace(e, p[29])
|
||||
}
|
||||
function q (r) {
|
||||
try
|
||||
{
|
||||
j.removeItem(r)
|
||||
} catch (n) { }
|
||||
}
|
||||
o[M + f + l] = K;
|
||||
function Q (r, n) {
|
||||
var t = G;
|
||||
t = cr,
|
||||
X(function () {
|
||||
var t = M;
|
||||
r = J(r),
|
||||
t = K;
|
||||
try
|
||||
{
|
||||
j.setAttribute(r, n),
|
||||
j.save(N)
|
||||
} catch (e) { }
|
||||
})()
|
||||
}
|
||||
function Z (r) {
|
||||
var n, t, e;
|
||||
if (n = t = e = g, P) q(r);
|
||||
else
|
||||
{
|
||||
if (!j) return void t[18];
|
||||
rr(r)
|
||||
}
|
||||
}
|
||||
function G (r) {
|
||||
try
|
||||
{
|
||||
return j.getItem(r)
|
||||
} catch (n)
|
||||
{
|
||||
return y[20]
|
||||
}
|
||||
}
|
||||
o[fr(w[33], p[30], R[35])] = Z;
|
||||
function z (r, n) {
|
||||
try
|
||||
{
|
||||
j.setItem(r, n)
|
||||
} catch (t) { }
|
||||
}
|
||||
function rr (r) {
|
||||
X(function () {
|
||||
r = J(r),
|
||||
j.removeAttribute(r),
|
||||
j.save(N)
|
||||
})()
|
||||
}
|
||||
}(pr || (pr = {}));
|
||||
var gr = function () {
|
||||
var o, i, u;
|
||||
o = i = u = e;
|
||||
var c, v, s;
|
||||
c = v = s = a;
|
||||
var f, l, g;
|
||||
f = l = g = n;
|
||||
var m, w, I;
|
||||
m = w = I = t;
|
||||
var _, E, A;
|
||||
_ = E = A = r;
|
||||
var C = yr(Cr, U, _[34]),
|
||||
b = vr(A[35], m[31]),
|
||||
R = hr(g[32], c[29], i[36]),
|
||||
T = hr(l[33], g[34], i[37], tr);
|
||||
function S (r) {
|
||||
this[m[32]] = r;
|
||||
for (var n = o[15], t = r[i[38]]; t > n; n++) this[n] = i[15]
|
||||
}
|
||||
return S[d + p + C][b + h] = function () {
|
||||
for (var r = this[vr(h, E[36], E[37])], n = [], t = -I[26], e = o[15], a = r[A[20]]; a > e; e++) for (var u = this[e], f = r[e], d = t += f; n[d] = u & parseInt(v[30], l[35]), --f != s[24];)--d,
|
||||
u >>= parseInt(i[39], c[31]);
|
||||
return n
|
||||
},
|
||||
S[vr(w[33], v[32])][_[38]] = function (r) {
|
||||
var n = dr,
|
||||
t = this[vr(y, l[36], A[39])],
|
||||
e = f[26];
|
||||
n = B;
|
||||
for (var a = v[24], o = t[l[37]]; o > a; a++)
|
||||
{
|
||||
var i = t[a],
|
||||
u = l[26];
|
||||
do u = (u << parseInt(R + T, g[35])) + r[e++];
|
||||
while (--i > w[18]);
|
||||
this[a] = u >>> w[18]
|
||||
}
|
||||
},
|
||||
S
|
||||
}(),
|
||||
mr; !
|
||||
function (o) {
|
||||
var i, u, c;
|
||||
i = u = c = n;
|
||||
var v, s, f;
|
||||
v = s = f = e;
|
||||
var l, d, p;
|
||||
l = d = p = a;
|
||||
var h, w, I;
|
||||
h = w = I = r;
|
||||
var _, y, E;
|
||||
_ = y = E = t;
|
||||
var A = y[34],
|
||||
C = (nr, U, h[40]),
|
||||
b = p[25];
|
||||
function B (r) {
|
||||
for (var n = y[35], t = f[15], e = r[vr(c[38], I[41], H)], a = []; e > t;)
|
||||
{
|
||||
var o = k[r.charAt(t++)] << parseInt(g + A, d[31]) | k[r.charAt(t++)] << parseInt(n + m, h[42]) | k[r.charAt(t++)] << parseInt(I[43], i[35]) | k[r.charAt(t++)];
|
||||
a.push(o >> parseInt(_[36], h[42]), o >> l[31] & parseInt(u[39], i[40]), o & parseInt(d[30], c[35]))
|
||||
}
|
||||
return a
|
||||
}
|
||||
function T (r) {
|
||||
for (var n = (O, R, p[24]), t = I[27], e = r[E[24]]; e > t; t++) n = (n << E[37]) - n + r[t];
|
||||
return n & parseInt(E[38], p[33])
|
||||
}
|
||||
for (var S = s[40], k = {},
|
||||
x = s[15]; x < parseInt(I[44], l[34]); x++) k[S.charAt(x)] = x;
|
||||
function L (r) {
|
||||
var n = B(r),
|
||||
t = n[u[26]];
|
||||
if (t != b) return error = yr(V, u[41], s[41], v[42]),
|
||||
void 0;
|
||||
var e = n[s[26]],
|
||||
a = [];
|
||||
return P(n, +_[39], a, +_[18], e),
|
||||
T(a) == e ? a : void 0
|
||||
}
|
||||
function M (r) {
|
||||
var n = T(r),
|
||||
t = [b, n];
|
||||
return P(r, +l[24], t, +p[25], n),
|
||||
N(t)
|
||||
}
|
||||
function N (r) {
|
||||
var n, t, e;
|
||||
n = t = e = f;
|
||||
var a, o, u;
|
||||
a = o = u = y;
|
||||
var c, v, s;
|
||||
c = v = s = h;
|
||||
var d, p, g;
|
||||
d = p = g = l;
|
||||
var m, w, I;
|
||||
m = w = I = i;
|
||||
for (var _ = m[42], E = d[24], A = r[c[20]], b = []; A > E;)
|
||||
{
|
||||
var B = r[E++] << parseInt(fr(Z, d[35]), o[39]) | r[E++] << g[31] | r[E++];
|
||||
b.push(S.charAt(B >> parseInt(m[43], t[43])), S.charAt(B >> parseInt(p[36], o[40]) & parseInt(I[44], I[45])), S.charAt(B >> n[44] & parseInt(_ + C, n[42])), S.charAt(B & parseInt(fr(d[37], c[45], or), a[41])))
|
||||
}
|
||||
return b.join(o[19])
|
||||
}
|
||||
function P (r, n, t, e, a) {
|
||||
var o, i, u;
|
||||
o = i = u = w;
|
||||
var c, v, s;
|
||||
c = v = s = E;
|
||||
for (var f = r[v[24]]; f > n;) t[e++] = r[n++] ^ a & parseInt(u[46], s[42]),
|
||||
a = ~(a * parseInt(v[43], v[40]))
|
||||
}
|
||||
o[E[44]] = N,
|
||||
o[_[45]] = B,
|
||||
o[v[45]] = M,
|
||||
o[y[46]] = L
|
||||
}(mr || (mr = {}));
|
||||
var wr; !
|
||||
function (o) {
|
||||
var i = a[38],
|
||||
u = r[47],
|
||||
c = t[47],
|
||||
v = vr(n[46], a[39], a[40]),
|
||||
s = e[46],
|
||||
f = e[47],
|
||||
l = a[41],
|
||||
d = a[42];
|
||||
function p (o) {
|
||||
var i = a[43],
|
||||
u = vr(n[47], e[48], n[48]),
|
||||
c = {},
|
||||
v = function (o, c) {
|
||||
var s, f, l, d;
|
||||
for (c = c.replace(n[49], n[12]), c = c.substring(e[26], c[e[38]] - e[26]), s = c.split(e[49]), l = a[24]; l < s[yr(v, sr, t[48])]; l++) if (f = s[l].split(n[50]), f && !(f[a[44]] < t[39]))
|
||||
{
|
||||
for (d = n[35]; d < f[r[20]]; d++) f[n[11]] = f[n[11]] + r[48] + f[d];
|
||||
f[n[26]] = new a[45](r[49]).test(f[n[26]]) ? f[e[15]].substring(r[19], f[e[15]][a[44]] - n[11]) : f[n[26]],
|
||||
f[n[11]] = new r[50](i + u + w).test(f[n[11]]) ? f[e[26]].substring(t[26], f[r[19]][n[37]] - t[26]) : f[a[18]],
|
||||
o[f[r[27]]] = f[n[11]]
|
||||
}
|
||||
return o
|
||||
};
|
||||
return new a[45](I + _).test(o) && (c = v(c, o)),
|
||||
c
|
||||
}
|
||||
function h (n) {
|
||||
for (var t = [], e = a[24]; e < n[r[20]]; e++) t.push(n.charCodeAt(e));
|
||||
return t
|
||||
}
|
||||
function g (o) {
|
||||
var u = a[46];
|
||||
if (typeof o === vr(O, a[47], or) && o[a[48]]) try
|
||||
{
|
||||
var c = parseInt(o[a[48]]);
|
||||
switch (c)
|
||||
{
|
||||
case parseInt(i + u, t[42]): break;
|
||||
case parseInt(yr(t[49], r[51], e[50]), e[43]): top[t[50]][n[51]] = o[e[51]];
|
||||
break;
|
||||
case parseInt(yr(a[25], j, e[52]), n[52]): top[n[53]][t[51]] = o[t[52]]
|
||||
}
|
||||
} catch (v) { }
|
||||
}
|
||||
function m (r, n, t) {
|
||||
|
||||
}
|
||||
function L () {
|
||||
var e, a, o;
|
||||
e = a = o = r;
|
||||
var i, u, c;
|
||||
i = u = c = n;
|
||||
var v, s, f;
|
||||
v = s = f = t;
|
||||
var l = f[53],
|
||||
d = c[54],
|
||||
p = new e[52];
|
||||
return typeof TOKEN_SERVER_TIME == y + l + d ? s[18] : (time = parseInt(TOKEN_SERVER_TIME), time)
|
||||
}
|
||||
function M () {
|
||||
var o = new t[54];
|
||||
try
|
||||
{
|
||||
return time = n[2].now(),
|
||||
time / parseInt(fr(a[50], a[51], r[53]), t[40]) >>> e[15]
|
||||
} catch (i)
|
||||
{
|
||||
return time = o.getTime(),
|
||||
time / parseInt(e[53], a[25]) >>> r[27]
|
||||
}
|
||||
}
|
||||
function N (r) {
|
||||
for (var a = t[18], o = r[t[24]] - n[11]; o >= e[15]; o--) a = a << e[26] | +r[o];
|
||||
return a
|
||||
}
|
||||
function P (a) {
|
||||
var o = new r[50](n[55]);
|
||||
if (K(a)) return a;
|
||||
var i = o.test(a) ? -e[54] : -t[39],
|
||||
u = a.split(r[54]);
|
||||
return u.slice(i).join(fr(n[56], t[55], E))
|
||||
}
|
||||
function j (t) {
|
||||
for (var o = n[26], i = e[15], u = t[vr(r[55], a[52], D)]; u > i; i++) o = (o << r[56]) - o + t.charCodeAt(i),
|
||||
o >>>= n[26];
|
||||
return o
|
||||
}
|
||||
function W (n, o) {
|
||||
var i = new a[45](t[56], yr(r[57], $, t[57], r[58])),
|
||||
u = new a[45](t[58]);
|
||||
if (n)
|
||||
{
|
||||
var c = n.match(i);
|
||||
if (c)
|
||||
{
|
||||
var v = c[e[26]];
|
||||
return o && u.test(v) && (v = v.split(t[59]).pop().split(r[48])[e[15]]),
|
||||
v
|
||||
}
|
||||
}
|
||||
}
|
||||
function $ (o) {
|
||||
var i = n[57],
|
||||
u = vr(e[55], e[56]),
|
||||
f = e[4];
|
||||
if (!(o > t[60]))
|
||||
{
|
||||
o = o || a[24];
|
||||
var l = parseInt(E + c + A, r[42]),
|
||||
d = n[14].createElement(e[57]);
|
||||
d[r[59]] = n[58] + parseInt((new a[53]).getTime() / l) + r[60],
|
||||
d[r[61]] = function () {
|
||||
var n = a[46];
|
||||
cr = r[19],
|
||||
setTimeout(function () {
|
||||
$(++o)
|
||||
},
|
||||
o * parseInt(C + n, a[33]))
|
||||
},
|
||||
d[t[61]] = d[hr(a[54], a[55], t[62])] = function () {
|
||||
var a = n[59];
|
||||
this[i + v + u + b] && this[e[58]] !== n[60] && this[s + B + a + f] !== e[59] && this[t[63]] !== n[61] || (cr = e[15], d[hr(N, r[62], n[62], e[25])] = d[t[64]] = r[63])
|
||||
},
|
||||
e[60][e[61]].appendChild(d)
|
||||
}
|
||||
}
|
||||
function F () {
|
||||
var r = a[56];
|
||||
return Math.random() * parseInt(R + T + f + r, t[42]) >>> n[26]
|
||||
}
|
||||
function X (r) {
|
||||
var e = new n[31](fr(t[65], t[66], a[57]), yr(c, n[63], t[57]));
|
||||
if (r)
|
||||
{
|
||||
var o = r.match(e);
|
||||
return o
|
||||
}
|
||||
}
|
||||
o[S + k] = p,
|
||||
o[r[64]] = $,
|
||||
o[t[67]] = g,
|
||||
o[t[68]] = h,
|
||||
o[t[69]] = j,
|
||||
o[t[70]] = F,
|
||||
o[r[65]] = K,
|
||||
o[x + l] = P,
|
||||
o[t[71]] = W,
|
||||
o[t[72]] = X,
|
||||
o[hr(r[66], t[73], r[67], C)] = N,
|
||||
o[t[74]] = M,
|
||||
o[d + O] = L;
|
||||
function K (n) {
|
||||
return new r[50](t[75]).test(n)
|
||||
}
|
||||
o[r[68]] = m
|
||||
}(wr || (wr = {}));
|
||||
var Ir; !
|
||||
function (o) {
|
||||
var i = t[76],
|
||||
u = t[77],
|
||||
c = n[65],
|
||||
v = t[78],
|
||||
s = a[24],
|
||||
f = n[26],
|
||||
l = t[18],
|
||||
d = t[18],
|
||||
p = e[15],
|
||||
h = a[24],
|
||||
g = r[69],
|
||||
m = '';
|
||||
wr.eventBind(e[60], n[67], E),
|
||||
wr.eventBind(r[71], t[79], E),
|
||||
wr.eventBind(t[20], hr(e[64], A, a[59]), b),
|
||||
wr.eventBind(e[60], r[72], y);
|
||||
function w () {
|
||||
return f
|
||||
}
|
||||
function I (r) {
|
||||
f++
|
||||
}
|
||||
function _ () {
|
||||
return {
|
||||
x: p,
|
||||
y: h,
|
||||
trusted: g
|
||||
}
|
||||
}
|
||||
function y (r) {
|
||||
d++
|
||||
}
|
||||
function E (r) {
|
||||
s++
|
||||
}
|
||||
function C () {
|
||||
return l
|
||||
}
|
||||
function b (r) {
|
||||
var o, i, u;
|
||||
o = i = u = n;
|
||||
var c, s, f;
|
||||
c = s = f = t;
|
||||
var d, m, w;
|
||||
d = m = w = e;
|
||||
var I, _, y;
|
||||
I = _ = y = a;
|
||||
var E = I[60],
|
||||
A = d[65];
|
||||
l++ ,
|
||||
g = void 0 == r[E + A + v] || r[yr(f[80], s[81], i[68])],
|
||||
p = r[s[82]],
|
||||
h = r[c[83]]
|
||||
}
|
||||
function B () {
|
||||
return d
|
||||
}
|
||||
function R () {
|
||||
return s
|
||||
}
|
||||
o[r[73]] = R,
|
||||
o[a[61]] = w,
|
||||
o[fr(a[62], n[69])] = C,
|
||||
o[n[70]] = B,
|
||||
o[r[74]] = _
|
||||
}(Ir || (Ir = {}));
|
||||
var _r; !
|
||||
function (u) {
|
||||
var v = fr(n[71], t[84]),
|
||||
s = r[75],
|
||||
f = yr(dr, n[72], e[66], $),
|
||||
l = r[76],
|
||||
d = e[67],
|
||||
p = r[77],
|
||||
h = hr(dr, r[78], a[63], n[73]),
|
||||
g = r[79],
|
||||
m = n[74];
|
||||
BROWSER_LIST = {
|
||||
|
||||
};
|
||||
function w () {
|
||||
var t, e, a;
|
||||
t = e = a = r;
|
||||
var o, i, u;
|
||||
o = i = u = n;
|
||||
return wr.booleanToDecimal(c)
|
||||
}
|
||||
function I (t) {
|
||||
for (var o = n[26]; o < y[e[38]]; o++)
|
||||
{
|
||||
var i = y[o][r[94]];
|
||||
if (t.test(i)) return !a[24]
|
||||
}
|
||||
return !a[18]
|
||||
}
|
||||
function E (t) {
|
||||
|
||||
}
|
||||
function A () {
|
||||
return a[73]
|
||||
}
|
||||
|
||||
function B () {
|
||||
return n[20]
|
||||
}
|
||||
|
||||
function T () {
|
||||
return I(new t[93](r[96]))
|
||||
}
|
||||
function S () {
|
||||
return I(new a[45](t[98], r[97]))
|
||||
}
|
||||
function k () {
|
||||
for (var r in BROWSER_LIST) if (BROWSER_LIST.hasOwnProperty(r))
|
||||
{
|
||||
var n = BROWSER_LIST[r];
|
||||
if (n()) return + r.substr(a[18])
|
||||
}
|
||||
return e[15]
|
||||
}
|
||||
function x () {
|
||||
var n, a, o;
|
||||
n = a = o = r;
|
||||
var i, u, c;
|
||||
i = u = c = t;
|
||||
var v, s, f;
|
||||
v = s = f = e;
|
||||
var l = s[75],
|
||||
d = s[76];
|
||||
return I(new u[93](o[98], v[71])) || E(l + F + d + X)
|
||||
}
|
||||
function O () {
|
||||
|
||||
}
|
||||
function L () {
|
||||
var r, n, t;
|
||||
r = n = t = a;
|
||||
var o, i, u;
|
||||
o = i = u = e;
|
||||
var c = l;
|
||||
return c = p
|
||||
}
|
||||
function M () {
|
||||
var r, n, a;
|
||||
r = n = a = t;
|
||||
var o, i, u;
|
||||
o = i = u = e;
|
||||
var c;
|
||||
try
|
||||
{
|
||||
c = i[60].createElement(a[99]).getContext(i[78])
|
||||
} catch (v) { }
|
||||
return !!c
|
||||
}
|
||||
|
||||
|
||||
function J () {
|
||||
var t, e, o;
|
||||
t = e = o = n;
|
||||
var i, u, c;
|
||||
i = u = c = a;
|
||||
var v, s, f;
|
||||
return v = s = f = r,
|
||||
-parseInt(s[100], c[31]) === (new e[2]).getTimezoneOffset()
|
||||
}
|
||||
|
||||
function Q () {
|
||||
try
|
||||
{
|
||||
} catch (e)
|
||||
{
|
||||
return r[101]
|
||||
}
|
||||
}
|
||||
function Z () {
|
||||
var n, a, o;
|
||||
n = a = o = e;
|
||||
var i, u, c;
|
||||
i = u = c = r;
|
||||
var v, s, f;
|
||||
return v = s = f = t,
|
||||
plugin_num = s[18],
|
||||
plugin_num
|
||||
}
|
||||
var z = [R, x, S, T, L, Q, b, V, O, J, M, q, Y, B, tr, A];
|
||||
|
||||
var nr = [new e[13](n[85]), new n[31](e[82]), new r[50](e[83]), new r[50](t[102]), new n[31](e[84]), new a[45](a[78]), new a[45](e[85]), new e[13](t[103]), new a[45](r[103]), new t[93](r[104]), new a[45](r[105])];
|
||||
function tr () {
|
||||
return e[86]
|
||||
}
|
||||
u[e[87]] = rr,
|
||||
u[a[79]] = k,
|
||||
u[yr(c, e[88], r[106])] = Z,
|
||||
u[K + U + m] = w
|
||||
}(_r || (_r = {}));
|
||||
function yr () {
|
||||
var o = arguments[a[25]];
|
||||
if (!o) return t[19];
|
||||
for (var i = a[19], u = e[14], c = r[27]; c < o.length; c++)
|
||||
{
|
||||
var v = o.charCodeAt(c),
|
||||
s = v ^ u;
|
||||
u = u * c % a[80] + e[89],
|
||||
i += n[86].fromCharCode(s)
|
||||
}
|
||||
return i
|
||||
}
|
||||
var Er; !
|
||||
function (o) {
|
||||
var i = a[81],
|
||||
u = t[35],
|
||||
c = r[107],
|
||||
v = vr(S, a[56]),
|
||||
f = r[27],
|
||||
l = r[19],
|
||||
d = a[25],
|
||||
p = n[87],
|
||||
h = parseInt(e[90], r[108]),
|
||||
g = a[82],
|
||||
m = parseInt(vr(s, t[104]), t[39]),
|
||||
w = r[109],
|
||||
I = t[40],
|
||||
_ = parseInt(i + V, n[45]),
|
||||
y = parseInt(u + c, n[52]),
|
||||
E = parseInt(t[105], r[42]),
|
||||
A = e[91],
|
||||
C = parseInt(Y + v, r[42]),
|
||||
b = parseInt(e[92], e[93]),
|
||||
B = t[106],
|
||||
R = parseInt(vr(e[94], e[95]), t[41]),
|
||||
T = parseInt(a[83], e[93]),
|
||||
k;
|
||||
function x () {
|
||||
var r = M();
|
||||
return r
|
||||
}
|
||||
function O () {
|
||||
var r = t[26],
|
||||
a = n[35],
|
||||
o = e[54],
|
||||
i = n[88];
|
||||
k = new gr([i, i, i, i, r, r, r, o, a, a, a, a, a, a, a, i, a, r]),
|
||||
k[l] = wr.serverTimeNow(),
|
||||
L(),
|
||||
k[B] = cr,
|
||||
k[T] = ur,
|
||||
k[R] = e[15],
|
||||
k[C] = _r.getBrowserFeature(),
|
||||
k[g] = _r.getBrowserIndex(),
|
||||
k[m] = _r.getPluginNum()
|
||||
}
|
||||
function L () {
|
||||
var a = dr.getCookie(tr) || pr.get(ar);
|
||||
if (a && a[r[20]] == parseInt(e[96], n[52]))
|
||||
{
|
||||
var o = mr.decode(a);
|
||||
if (o && (k.decodeBuffer(o), k[f] != t[18])) return
|
||||
}
|
||||
k[f] = wr.random()
|
||||
}
|
||||
o[a[84]] = O;
|
||||
function M () {
|
||||
k[R]++ ,
|
||||
k[l] = wr.serverTimeNow(),
|
||||
k[d] = wr.timeNow(),
|
||||
k[B] = cr,
|
||||
k[w] = Ir.getMouseMove(),
|
||||
k[I] = Ir.getMouseClick(),
|
||||
k[_] = Ir.getMouseWhell(),
|
||||
k[y] = Ir.getKeyDown(),
|
||||
k[E] = Ir.getClickPos().x,
|
||||
k[A] = Ir.getClickPos().y;
|
||||
var r = k.toBuffer();
|
||||
return mr.encode(r)
|
||||
}
|
||||
o[yr(r[3], n[89], e[97])] = x
|
||||
}(Er || (Er = {}));
|
||||
var Ar; !
|
||||
function (o) {
|
||||
var i = n[90],
|
||||
u = a[85],
|
||||
v = r[110],
|
||||
s = a[86],
|
||||
f = t[107],
|
||||
p,
|
||||
h,
|
||||
m,
|
||||
w,
|
||||
I,
|
||||
_;
|
||||
function E (r) {
|
||||
return N(r) && dr[a[87]]
|
||||
}
|
||||
function A (o) {
|
||||
var i = wr.getOriginFromUrl(o);
|
||||
return i ? !new n[31](yr(r[42], c, t[110]) + w).test(i[r[108]]) || !new e[13](I).test(i[a[18]]) : t[111]
|
||||
}
|
||||
function C (e) {
|
||||
var o = (_r, g, Er.update());
|
||||
return e + (new r[50](vr(a[88], a[89])).test(e) ? n[91] : vr(P, a[90], t[112])) + er + t[23] + r[111](o)
|
||||
}
|
||||
function b (o, i, u) {
|
||||
if (r[112] in i) return i.apply(o, u);
|
||||
switch (u[n[37]])
|
||||
{
|
||||
case n[26]:
|
||||
return i();
|
||||
case a[18]:
|
||||
return i(u[n[26]]);
|
||||
case r[108]:
|
||||
return i(u[e[15]], u[r[19]]);
|
||||
default:
|
||||
return i(u[n[26]], u[r[108]], u[t[17]])
|
||||
}
|
||||
}
|
||||
function B () {
|
||||
var r = Er.update();
|
||||
return r
|
||||
}
|
||||
function k (r, e, o) {
|
||||
if (!r) return n[20];
|
||||
var i = r[e];
|
||||
if (!i) return t[111];
|
||||
var u = o(i);
|
||||
return d || (u[a[97]] = i + t[19]),
|
||||
u[n[97]] = i,
|
||||
r[e] = u,
|
||||
a[21]
|
||||
}
|
||||
function M (o) {
|
||||
var i, u, c;
|
||||
i = u = c = n;
|
||||
var v, s, l;
|
||||
v = s = l = r;
|
||||
var d, p, h;
|
||||
d = p = h = e;
|
||||
var g, m, w;
|
||||
g = m = w = a;
|
||||
var I, _, y;
|
||||
I = _ = y = t;
|
||||
var R = hr(I[121], w[106], d[109]),
|
||||
T;
|
||||
k(o, _[122],
|
||||
function (r) {
|
||||
var n = w[107];
|
||||
return function () {
|
||||
var t, e, a;
|
||||
t = e = a = _;
|
||||
var o, i, u;
|
||||
o = i = u = l;
|
||||
var c, v, s;
|
||||
c = v = s = w;
|
||||
var f = s[108];
|
||||
try
|
||||
{
|
||||
A(arguments[s[18]]) && !E(arguments[o[19]]) ? arguments[a[26]] = C(arguments[s[18]]) : T = B(),
|
||||
r.apply(this, arguments),
|
||||
A(arguments[i[19]]) || this.setRequestHeader(ar, T)
|
||||
} catch (d)
|
||||
{
|
||||
return n + f
|
||||
}
|
||||
}
|
||||
}),
|
||||
k(o, g[109],
|
||||
function (r) {
|
||||
var n = b;
|
||||
n = M;
|
||||
var t = vr(_[123], u[107]);
|
||||
return function () {
|
||||
var n = fr(f, c[108], I[124]),
|
||||
e = s[122];
|
||||
try
|
||||
{
|
||||
if (parseInt(this.status) === parseInt(h[110], v[123]))
|
||||
{
|
||||
for (var a = r.apply(this, arguments), o = new p[13](i[109], n + R), u, l, d = {}; u = o.exec(a);) d[u[m[18]].toLowerCase()] = u[v[108]];
|
||||
wr.analysisRst(wr.parse(d[ir.toLowerCase()]))
|
||||
}
|
||||
} catch (g)
|
||||
{
|
||||
return e + t
|
||||
}
|
||||
return r.apply(this, arguments)
|
||||
}
|
||||
})
|
||||
}
|
||||
function N (r) {
|
||||
var n = wr.getHostFromUrl(r, e[28]);
|
||||
return n ? _.test(n) : e[28]
|
||||
}
|
||||
function j () {
|
||||
var cookie_v;
|
||||
cookie_v = B()
|
||||
return cookie_v
|
||||
}
|
||||
o[n[111]] = j
|
||||
}(Ar || (Ar = {}));
|
||||
var Cr;
|
||||
var cookie = (function (a) {
|
||||
function _ () {
|
||||
var cookie_v;
|
||||
Er.Init();
|
||||
cookie_v = Ar.Init();
|
||||
return cookie_v
|
||||
}
|
||||
return function y () {
|
||||
try
|
||||
{
|
||||
return _()
|
||||
} catch (r)
|
||||
{
|
||||
return r
|
||||
}
|
||||
}
|
||||
})()
|
||||
return cookie()
|
||||
}
|
||||
function v () {
|
||||
var v;
|
||||
v = v_cookie(
|
||||
["t", 34, '"$', 36, "\fb", 55, "ure", "lJ#K", "Flash", "getBro", "1", "analys", "CHAMELEON_CALLBACK", 30, "\u256f\u0930\u097b\u09ff\u09a4\u0934\u099d\u09c1\u099d\u09d9\u09a7\u09c3\u0995\u09f0\u09d3\u0a62\u0a6f\u09bc\u09ad\u0934", "F,sp-", String, "; expires=", "", 1, "length", "; ", '', '', "addBehavior", ";^l", ">*]+", 0, "div", "&~!", "", "Init", "('&%$#\"![", ">NJ", "\u254e\u096d\u095f", "W$R", "sdelif_esab", "Or)E", "decodeBuffer", 84, "f", "htgnel", 8, "110", "40", "\u2504\u2562", "255", "o", ":", '^".*"$', RegExp, 40, Date, "e9", ".", 19, 5, "t8JOi", "}B", "src", ".js", "onerror", "*q:", null, "getServerTime", "isIPAddr", "8-", "ZX9Y]V8aWs3VQZ7Y", "eventBind", !0, "wheel", '', "keydown", "getMouseMove", "getClickPos", "vent", "me", "MSG", 41, "th", "safari", "ActiveXObject", "maxHeight", "head", "Google Inc.", "vendor", "sgAppName", "opr", 94, "tugw`pj", "chrome", "2345Explorer", "ome", "TheWorld", "name", "\u2553\u253c\u2572\u251d\u2569\u253d\u254f\u252e\u254d\u2526", "Native Client", "i", "Shockwave", "systemLanguage", "740", !1, "plugins", "^ARM", "^iPod", "^BlackBerry", "\u2550\u0978\u094e\u09c1\u09bc\u0928\u0989\u09d8\u099a\u09f3\u09b7\u09dc", "0", 2, 7, "c", encodeURIComponent, "apply", "headers", "8S:+", "\u2560\u2509\u2567\u2503\u256c\u251b", "\u255e\u2530\u2543\u2526\u2554\u2520\u2562\u2507\u2561\u250e\u257c\u2519", "a", 14, ":dB2", "href", "click", "err", 16, "hostname", "`60w", "\fbf", "&X "],
|
||||
[";", "Element", Date, "par", "i", "DOMMous", 21, "xmT", "wserFe", "h", !0, 1, "", Boolean, '', "; domain=", "n 1970 00:", "cookie", "checkcookie", "allow", !1, "delCookie", 2333, "torage", ")*+,/\\\\:;", '', 0, '', "eliflmth", '', "ducument", RegExp, "W", "qsU", 61, 2, "sdelif_esab", "length", "I", "ff", 16, 45, "3", "10010", "77", 8, "6e%d", "DT{e", "$", / /g, ":", "href", 10, "location", "ned", "\\.com\\.cn$|\\.com\\.hk$", 63, "rea", "https://s.thsi.cn/js/chameleon/time.1", "tat", "loaded", "interactive", "WY:ZYS", "E?`a", "addEventListener", "eScroll", "onmousewheel", "mousemove", "\u255e\u096e\u096e\u09e3\u09a5\u092e\u099a\u09d4\u0990", "\u2550\u2535\u2541\u250c\u2563\u2516\u2565\u2500\u2543\u252f\u2546\u2525\u254e", "getKeyDown", "H69<J", "v~g-", "", "ature", "callPhantom", "ActiveXObject", "Uint8Array", "WeakMap", "JX%<", "chrome", "@L:!", "20", "language", "localStorage", "^Win32", String, 3, 4, "=XAE", "hea", "&", "/", "\\R$", '^R"VP', "s", "include", "_raw", "x.", "isRst", "SCRIPT", "ta", "base", "$?", "^_self$", "#", "unload", "ro", "\u2550", "^(.*?):[ \\t]*([^\\r\\n]*)\\r?$", "g", "Init", "t6?x}", "\u2574\u0955\u097b\u09dc\u0995\u0911\u09ab\u09fe\u09ba\u09e2\u098e\u09fe\u09f9\u09f9\u09f3\u0a55", "=d' "],
|
||||
["<=>?@[\\]^", "e", "HE9", "tot", "\u2503", "0", "dyS", "se", "getRoot", "NR", "nd", 60, "ng", "s", "get", "mit", 13, 3, 0, "", '', "\u255f\u253a\u255b\u253f", "getCookie", "=", "length", "V587", 1, String, !0, "___", "\u2553\u2536\u255a", "uBot", "base_fileds", 32, "2", "1", "20", 5, "255", 2, 8, 16, 10, "203", "base64Encode", "base64Decode", "decode", "760", "\u255b\u0978\u0954\u09f6\u09a4\u0935", 70, "location", "href", "redirect_url", "efi", Date, "\u2519", "^\\s*(?:https?:)?\\/{2,}([^\\/\\?\\#\\\\]+)", "\u255e", "[@:]", "@", 7, "onload", 'WY$PYS/FLV"P[_7[_R', "readyState", "onreadystatechange", '"^w', "\u2569\u2535\u2546\u256c\u2544\u257b\u2541\u2569\u2501\u2575\u2501\u2571\u2502\u253d\u2507\u252e\u2507\u2538\u2564\u254b\u2530\u2502\u252e\u2553\u257b\u2520\u257e\u2522\u250d\u2551\u256e\u2532\u2511\u254d\u2511\u254c\u2567\u254e", "analysisRst", "strToBytes", "strhash", "random", "getHostFromUrl", "getOriginFromUrl", 83, "timeNow", "^(\\d+\\.)+\\d+$", "d", "v", "ted", "touchmove", 85, "F(K9i", "clientX", "clientY", "\u257a\u2515\u256f\u253c", "postMessage", '', "ActiveXObject", "Apple Computer, Inc.", "Q", "chr", "\u2558\u2535\u2550", "BIDUBrowser", RegExp, "QQBrowser", "ro", "aef", "msDoNotTrack", "PDF|Acrobat", "canvas", "yE", "\u255b\u253a\u2554\u2533\u2546\u2527\u2540\u2525\u2556", "^Android", "^Linux [ix]\\d+", "011", "13", 15, "sub", "addEventListener", "jsonp_ignore", "\u2569", !1, 'L"', "Sj", "T{_,", "q*", "i", "tagName", "et", "{'K", "Pp<", "#x'", "open", "rS", "KN3", "#", "protocol", "\\.", "DEDAOL_NOELEMAHC"],
|
||||
[83, "ffer", "\u2505", "20", "e", "ngsE", Error, "est", "\u2552\u095b\u0956\u09f0\u09a3\u0935\u09c0\u09e2", "1", "sr", "hexin-v", "", RegExp, 9527, 0, "**l>", "head", "Thu, 01 Ja", "00:00 GMT", "allow", "=", "; path=", "cookie", "Init", 33, 1, "setCookie", !0, "localS", "`{|}~]", "g", '', "frames", "___$&", 56, " ", "\b", "length", "10", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", "\u2552\u096f\u0948\u09fe\u09a2", 16, 2, 6, "encode", "rea", "729", "*.", ",", "\u2506\u092c\u090b\u09a0\u09e1\u096d\u09df\u0981\u09c4\u098c", "redirect_url", "\u2506\u092d\u090a\u09a3", "1111101000", 3, 47, "tat", "script", "readyState", "complete", '', "body", "onwheel", "mousewheel", 37, "rus", "\u2554\u0975", "chr", "ActiveXObject", "WeakMap", "aT1Kg", "i", 24, "\u2554\u253c\u254e\u2521\u254c\u2529", "\u2547\u0971\u094f\u09f6\u09b9\u0933\u099d", "Shockwav", "hockwave", "$cdc_asdjflasutopfhvcZLmcfl_", "webgl2", "2>n|", "plugins", "platform", "^Win64", "^Linux armv|Android", "^iPhone", "^MacIntel", !1, "getPlatform", "6Y,", 2333, "100", 12, "14", 10, 36, "01", "60", "\u2542\u096d\u095e\u09f0\u09a4\u0938", "j", 17, "Request", "prototype", "`z}lc", "error", "s", "r", "target", "\u255e", "A", "U", "193", "host", "$"],
|
||||
["se", "g@g?", Array, "*Y", Number, "^{.", "*}$", "und", "429", "496", "imeNow", "etti", "rg", "v", "hexin-v", Error, "L_%\\T8", ".baidu.", 1, "", Function, !0, " ", '', 0, 2, "#default#userData", "ydob", "^d", 89, "11111111", 8, "epytotorp", 10, 16, "\u2506\u2536\u2506\u2536\u2506", "14", 13, "10", "Syd", 44, "Domain", "serverT", '^"', "length", RegExp, "00", "tcejbo", "status_code", "n", 66, "\u2506\u2531\u2504\u2534", "htgnel", Date, "L%", 67, "5", "?)'", '', "[[?VS", "isT", "getMouseWhell", "}}", "TR", "ActiveXObject", "WE", "python", "Maxthon", 97, "chrome", "Ryp", "UBrowser", 54, !1, "ontouchstart", "\u254d\u0975\u0917\u09f2\u09be", "iso-8859-1", "defaultCharset", "^iPad", "getBrowserIndex", 256, "1", 5, "17", "Init", "XMLHttp", "tar", "allow", "@*", "?\\", "?", "\u2571\u2503\u256a\u2546\u2566\u2556\u2567\u2547\u2501\u2564\u2506\u2526\u2514\u2524\u2511\u2521\u2501\u2531\u2501\u253b\u250b\u253b\u2501\u2531\u2501\u2521\u2566\u252b\u257f", "den", "tia", 94, "ls", "\u2554\u2526\u2543", "_str", 37, "append", "Child", "\u255f", "\u2569\u0975\u094e\u09e5\u09a0\u092e\u09d1\u09ed\u09ce", "srcElement", "parentNode", "\u2543\u2522\u2545\u250b\u256a\u2507\u2562", "}*", "err", "or", "getAllResponseHeaders", "\\.?", "\\."]
|
||||
);
|
||||
return v
|
||||
}
|
13
adata/common/utils/__init__.py
Normal file
13
adata/common/utils/__init__.py
Normal file
@ -0,0 +1,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: readme
|
||||
@author: 1nchaos
|
||||
@time: 2023/3/29
|
||||
@log: change log
|
||||
"""
|
||||
from .snowflake import worker
|
||||
from .sunrequests import SunRequests
|
||||
|
||||
requests = SunRequests()
|
||||
|
||||
|
30
adata/common/utils/cookie.py
Normal file
30
adata/common/utils/cookie.py
Normal file
@ -0,0 +1,30 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: 获取cookie的工具类
|
||||
@author: 1nchaos
|
||||
@time: 2023/5/5
|
||||
@log: change log
|
||||
"""
|
||||
from importlib import resources
|
||||
|
||||
from py_mini_racer import py_mini_racer
|
||||
|
||||
|
||||
def ths_cookie():
|
||||
"""获取同花顺cookie"""
|
||||
js_code = py_mini_racer.MiniRacer()
|
||||
js_content = _get_file_content_ths(file_path="ths.js")
|
||||
js_code.eval(js_content)
|
||||
return 'v='+js_code.call("v")
|
||||
|
||||
|
||||
def _get_file_content_ths(file_path: str = None) -> str:
|
||||
"""
|
||||
获取 JS 文件的内容
|
||||
:param file_path: JS 文件名
|
||||
:return: 文件内容
|
||||
"""
|
||||
with resources.path("adata.common.js", file_path) as f_path:
|
||||
with open(f_path) as f:
|
||||
file_data = f.read()
|
||||
return file_data
|
109
adata/common/utils/snowflake.py
Normal file
109
adata/common/utils/snowflake.py
Normal file
@ -0,0 +1,109 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: 雪花算法 生成唯一 全局id
|
||||
使用方式 单例模式使用
|
||||
import worker
|
||||
@author: 1nchaos
|
||||
@time: 2022/4/8
|
||||
@log: change log
|
||||
"""
|
||||
|
||||
import logging
|
||||
import random
|
||||
import time
|
||||
|
||||
# 64位ID的划分
|
||||
WORKER_ID_BITS = 5
|
||||
DATACENTER_ID_BITS = 5
|
||||
SEQUENCE_BITS = 12
|
||||
|
||||
# 最大取值计算 # 2**5-1 0b11111
|
||||
MAX_WORKER_ID = -1 ^ (-1 << WORKER_ID_BITS)
|
||||
MAX_DATACENTER_ID = -1 ^ (-1 << DATACENTER_ID_BITS)
|
||||
|
||||
# 移位偏移计算
|
||||
WORKER_ID_SHIFT = SEQUENCE_BITS
|
||||
DATACENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS
|
||||
TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTER_ID_BITS
|
||||
|
||||
# 序号循环掩码
|
||||
SEQUENCE_MASK = -1 ^ (-1 << SEQUENCE_BITS)
|
||||
|
||||
# Twitter元年时间戳
|
||||
TWEPOCH = 1580885600337
|
||||
|
||||
logger = logging.getLogger('flask.app')
|
||||
|
||||
|
||||
class _IdWorker(object):
|
||||
"""
|
||||
用于生成雪花算法 id的对象
|
||||
"""
|
||||
|
||||
def __init__(self, datacenter_id=1, worker_id=1, sequence=0):
|
||||
"""
|
||||
初始化
|
||||
:param datacenter_id: 数据中心(机器区域)ID
|
||||
:param worker_id: 机器ID
|
||||
:param sequence: 其实序号
|
||||
"""
|
||||
# sanity check
|
||||
if worker_id > MAX_WORKER_ID or worker_id < 0:
|
||||
raise ValueError('worker_id值越界')
|
||||
if datacenter_id > MAX_DATACENTER_ID or datacenter_id < 0:
|
||||
raise ValueError('datacenter_id值越界')
|
||||
|
||||
self.worker_id = worker_id
|
||||
self.datacenter_id = datacenter_id
|
||||
self.sequence = sequence
|
||||
# 上次计算的时间戳
|
||||
self.last_timestamp = -1
|
||||
|
||||
|
||||
def _gen_timestamp(self):
|
||||
"""
|
||||
生成整数时间戳
|
||||
:return:int timestamp
|
||||
"""
|
||||
return int(time.time() * 1000)
|
||||
|
||||
def _til_next_millis(self, last_timestamp):
|
||||
"""
|
||||
等到下一毫秒
|
||||
"""
|
||||
timestamp = self._gen_timestamp()
|
||||
while timestamp <= last_timestamp:
|
||||
timestamp = self._gen_timestamp()
|
||||
return timestamp
|
||||
|
||||
def id(self):
|
||||
"""
|
||||
获取新ID
|
||||
:return:
|
||||
"""
|
||||
timestamp = self._gen_timestamp()
|
||||
|
||||
# 时钟回拨
|
||||
if timestamp < self.last_timestamp:
|
||||
logging.error('clock is moving backwards. Rejecting requests until {}'.format(self.last_timestamp))
|
||||
raise
|
||||
|
||||
if timestamp == self.last_timestamp:
|
||||
self.sequence = (self.sequence + 1) & SEQUENCE_MASK
|
||||
if self.sequence == 0:
|
||||
timestamp = self._til_next_millis(self.last_timestamp)
|
||||
else:
|
||||
self.sequence = 0
|
||||
|
||||
self.last_timestamp = timestamp
|
||||
|
||||
new_id = ((timestamp - TWEPOCH) << TIMESTAMP_LEFT_SHIFT) | (self.datacenter_id << DATACENTER_ID_SHIFT) | \
|
||||
(self.worker_id << WORKER_ID_SHIFT) | self.sequence
|
||||
return new_id
|
||||
|
||||
|
||||
# 随机分配机器id 和 数据中心
|
||||
worker = _IdWorker(random.randint(0, 31), random.randint(0, 31))
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(worker.id())
|
34
adata/common/utils/sunrequests.py
Normal file
34
adata/common/utils/sunrequests.py
Normal file
@ -0,0 +1,34 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: adata 请求工具类
|
||||
@author: 1nchaos
|
||||
@time:2023/3/30
|
||||
@log: 封装请求次数
|
||||
"""
|
||||
|
||||
import time
|
||||
|
||||
import requests
|
||||
|
||||
|
||||
class SunRequests(object):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
def request(self, method='get', url=None, times=3, sleep_time=1588, **kwargs):
|
||||
"""
|
||||
简单封装的请求,参考requests,增加循环次数和次数之间的等待时间
|
||||
:param method: 请求方法: get;post
|
||||
:param url: url
|
||||
:param times: 次数,int
|
||||
:param sleep_time: 循环的等待时间,毫秒
|
||||
:param kwargs: 其它 requests 参数,用法相同
|
||||
:return: res
|
||||
"""
|
||||
res = None
|
||||
for i in range(times):
|
||||
res = requests.request(method=method, url=url, **kwargs)
|
||||
if res.status_code in (200, 404):
|
||||
return res
|
||||
time.sleep(sleep_time / 1000)
|
||||
return res
|
7
adata/fund/__init__.py
Normal file
7
adata/fund/__init__.py
Normal file
@ -0,0 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: 场内ETF相关数据
|
||||
@author: 1nchaos
|
||||
@time: 2023/4/4
|
||||
@log: change log
|
||||
"""
|
14
adata/fund/etf_market.py
Normal file
14
adata/fund/etf_market.py
Normal file
@ -0,0 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc:
|
||||
@author: 1nchaos
|
||||
@time:2023/4/5
|
||||
@log:
|
||||
"""
|
||||
|
||||
|
||||
class ETFMarket(object):
|
||||
"""ETF 行情"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
7
adata/message/__init__.py
Normal file
7
adata/message/__init__.py
Normal file
@ -0,0 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: readme
|
||||
@author: 1nchaos
|
||||
@time: 2023/4/4
|
||||
@log: change log
|
||||
"""
|
19
adata/stock/__init__.py
Normal file
19
adata/stock/__init__.py
Normal file
@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: 专注股票相关的数据,为量化而生
|
||||
@author: 1nchaos
|
||||
@time: 2023/3/29
|
||||
@log: change log
|
||||
"""
|
||||
from .info import info
|
||||
from .market import market
|
||||
|
||||
|
||||
class Stock(object):
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.info = info
|
||||
self.market = market
|
||||
|
||||
|
||||
stock = Stock()
|
7
adata/stock/index/__init__.py
Normal file
7
adata/stock/index/__init__.py
Normal file
@ -0,0 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: 指数相关数据
|
||||
@author: 1nchaos
|
||||
@time:2022/9/19
|
||||
@log:
|
||||
"""
|
19
adata/stock/info/__init__.py
Normal file
19
adata/stock/info/__init__.py
Normal file
@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: 基本信息相关数据
|
||||
@author: 1nchaos
|
||||
@time: 2023/3/28
|
||||
@log: change log
|
||||
"""
|
||||
from .stock_code import StockCode
|
||||
from .stock_concept import StockConcept
|
||||
from .trade_calendar import TradeCalendar
|
||||
|
||||
|
||||
class Info(StockCode, StockConcept, TradeCalendar):
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
|
||||
info = Info()
|
71
adata/stock/info/stock_code.py
Normal file
71
adata/stock/info/stock_code.py
Normal file
@ -0,0 +1,71 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: 股票代码
|
||||
@author: 1nchaos
|
||||
@time: 2023/3/28
|
||||
@log: change log
|
||||
"""
|
||||
import time
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
from tqdm import tqdm
|
||||
|
||||
from adata.common.headers import baidu_headers
|
||||
|
||||
|
||||
class StockCode(object):
|
||||
"""
|
||||
股票代码
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
def all_code(self):
|
||||
"""
|
||||
获取所有股票的代码 ,后续补充多数据源
|
||||
:return: 所有股票的代码信息: ['stock_code','short_name','exchange']
|
||||
"""
|
||||
return self.__market_rank_baidu()
|
||||
|
||||
def __market_rank_baidu(self):
|
||||
"""
|
||||
获取百度当前涨幅排名的代码
|
||||
web: https://gushitong.baidu.com/top/ab-increase-%E6%B6%A8%E5%B9%85%E6%A6%9C
|
||||
url:https://finance.pae.baidu.com/selfselect/getmarketrank?sort_type=1&sort_key=14&from_mid=1&pn=0&rn=200&group=pclist&type=ab&finClientType=pc
|
||||
其中:pn 起始数 rn 翻页数,最大200
|
||||
:return 代码列表:['stock_code','short_name','exchange']
|
||||
"""
|
||||
# 1. 请求市场排名的 url
|
||||
api_url = f"https://finance.pae.baidu.com/selfselect/getmarketrank" \
|
||||
f"?sort_type=1&sort_key=14&from_mid=1&group=pclist&type=ab&finClientType=pc"
|
||||
max_page_size = 200
|
||||
data = []
|
||||
|
||||
# 2. 一直翻页请求数据,股票目前数据5000,50页一共1w只,后续增加了可以再加
|
||||
for page_no in tqdm(range(49)):
|
||||
api_url = f"{api_url}&pn={page_no * max_page_size}&rn={max_page_size}"
|
||||
try:
|
||||
res = requests.get(api_url, headers=baidu_headers.json_headers, proxies={})
|
||||
res_json = res.json()
|
||||
if res.status_code != 200 or res_json['ResultCode'] != '0':
|
||||
continue
|
||||
# 3. 解析数据
|
||||
result = res_json['Result']['Result']
|
||||
# 结果为空跳出循环
|
||||
if not result:
|
||||
break
|
||||
code_list = result[0]['DisplayData']['resultData']['tplData']['result']['rank']
|
||||
data.extend(code_list)
|
||||
except Exception as e:
|
||||
time.sleep(2)
|
||||
print(e)
|
||||
continue
|
||||
# 4. 封装数据
|
||||
rename = {'name': 'short_name', 'code': 'stock_code'}
|
||||
return pd.DataFrame(data=data)[['code', 'name', 'exchange']].rename(columns=rename)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(StockCode().all_code())
|
207
adata/stock/info/stock_concept.py
Normal file
207
adata/stock/info/stock_concept.py
Normal file
@ -0,0 +1,207 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@summary: 股票概念
|
||||
同花顺概念更及时和完整,所以目前暂只基于同花顺的股票概念抓取
|
||||
|
||||
概念,指数成分
|
||||
来源于同花顺
|
||||
http://q.10jqka.com.cn/gn
|
||||
@author: 1nchaos
|
||||
@date: 2023/3/30 16:17
|
||||
"""
|
||||
import copy
|
||||
import math
|
||||
|
||||
import pandas as pd
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
from adata.common.headers import ths_headers
|
||||
from adata.common.utils import cookie
|
||||
from adata.common.utils import requests
|
||||
|
||||
|
||||
class StockConcept(object):
|
||||
"""
|
||||
股票概念
|
||||
"""
|
||||
CONCEPT_CONSTITUENT_COLUMNS = ['stock_code', 'short_name']
|
||||
CONCEPT_CODE_COLUMNS = ['concept_code', 'index_code', 'name', 'source']
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
def all_concept_code_ths(self):
|
||||
"""
|
||||
获取同花顺概念列表:名称,指数代码,概念代码
|
||||
特别注意:
|
||||
同花顺概念指数代码是8开头
|
||||
概念代码是3开头
|
||||
这两个不要混淆啦,同花顺的网站获取数据需要用到这两个代码
|
||||
:return: 概念[[name,index_code,concept_code]]
|
||||
"""
|
||||
index_df = self.__concept_index_code_ths()
|
||||
code_df = self.__concept_code_ths()
|
||||
result_df_l = pd.merge(index_df, code_df, how='left', on='name')
|
||||
result_df_r = pd.merge(index_df, code_df, how='right', on='name')
|
||||
result_df = result_df_l.append(result_df_r).drop_duplicates(keep='first', inplace=False, ignore_index=True)
|
||||
|
||||
index_df.drop(index_df.index, inplace=True)
|
||||
code_df.drop(code_df.index, inplace=True)
|
||||
result_df_l.drop(result_df_l.index, inplace=True)
|
||||
result_df_r.drop(result_df_r.index, inplace=True)
|
||||
result_df['source'] = '同花顺'
|
||||
return result_df
|
||||
|
||||
def __concept_code_ths(self):
|
||||
"""
|
||||
获取同花顺的所有概念和概念代码,暂时废弃
|
||||
web: http://q.10jqka.com.cn/gn/
|
||||
"""
|
||||
# 1. 请求接口 url
|
||||
api_url = f"http://q.10jqka.com.cn/gn/"
|
||||
for i in range(3):
|
||||
res = requests.request('get', api_url, headers=ths_headers.text_headers, proxies={})
|
||||
# 2. 判断请求是否正确
|
||||
text = res.text
|
||||
if res.status_code != 200 or len(text) < 1:
|
||||
continue
|
||||
# 3. 解析数据
|
||||
soup = BeautifulSoup(text, 'html.parser')
|
||||
data = []
|
||||
for a in soup.find_all('a'):
|
||||
href = str(a['href'])
|
||||
if href.startswith(api_url + 'detail/code/'):
|
||||
data.append([href[-7: -1], a.string, href])
|
||||
|
||||
# 4. 封装数据
|
||||
data_df = pd.DataFrame(data=data, columns=['concept_code', 'name', 'href'])[['concept_code', 'name']]
|
||||
return data_df
|
||||
|
||||
def __concept_index_code_ths(self):
|
||||
"""
|
||||
获取app的概率列表,通过问财询问得到结果
|
||||
:return: app的概念列表: concept_code,name
|
||||
"""
|
||||
data = []
|
||||
for i in range(1, 10):
|
||||
api_url = f"http://search.10jqka.com.cn/gateway/urp/v7/landing/getDataList?perpage=100&page={i}&query=%E6%89%80%E6%9C%89%E6%A6%82%E5%BF%B5&condition=%5B%7B%22indexName%22%3A%22%E6%8C%87%E6%95%B0%40%E5%90%8C%E8%8A%B1%E9%A1%BA%E6%A6%82%E5%BF%B5%E6%8C%87%E6%95%B0%22%2C%22indexProperties%22%3A%5B%5D%2C%22source%22%3A%22new_parser%22%2C%22type%22%3A%22index%22%2C%22indexPropertiesMap%22%3A%7B%7D%2C%22reportType%22%3A%22null%22%2C%22chunkedResult%22%3A%22%E6%89%80%E6%9C%89%E6%A6%82%E5%BF%B5%22%2C%22valueType%22%3A%22_%E6%8C%87%E6%95%B0%E7%B1%BB%E5%9E%8B%22%2C%22domain%22%3A%22abs_a%E6%8C%87%E9%A2%86%E5%9F%9F%22%2C%22uiText%22%3A%22%E5%90%8C%E8%8A%B1%E9%A1%BA%E6%A6%82%E5%BF%B5%E6%8C%87%E6%95%B0%22%2C%22sonSize%22%3A0%2C%22queryText%22%3A%22%E5%90%8C%E8%8A%B1%E9%A1%BA%E6%A6%82%E5%BF%B5%E6%8C%87%E6%95%B0%22%2C%22relatedSize%22%3A0%7D%5D&urp_sort_index=%E6%8C%87%E6%95%B0%E4%BB%A3%E7%A0%81&source=Ths_iwencai_Xuangu&urp_sort_way=desc&codelist=&page_id=&logid=35df00ee5ae706d0dfcd0dbfdb846e0c&ret=json_all&sessionid=35df00ee5ae706d0dfcd0dbfdb846e0c&iwc_token=0ac9667016801698001765831&user_id=Ths_iwencai_Xuangu_7fahywzhbkrh4lwwkwfw936njqbjzsly&uuids%5B0%5D=23119&query_type=zhishu&comp_id=6367801&business_cat=soniu&uuid=23119"
|
||||
res = requests.request('get', url=api_url, headers=ths_headers.c_headers)
|
||||
res_json = res.json()
|
||||
if res_json['status_msg'] == 'ok':
|
||||
data_list = res_json['answer']['components'][0]['data']['datas']
|
||||
if len(data_list) < 1:
|
||||
break
|
||||
for d in data_list:
|
||||
data.append([d['code'], d['指数简称']])
|
||||
data_df = pd.DataFrame(data=data, columns=['index_code', 'name']).drop_duplicates(keep='first', inplace=False,
|
||||
ignore_index=True)
|
||||
return data_df
|
||||
|
||||
def concept_constituent_ths(self, concept_code=None, name=None):
|
||||
"""
|
||||
获取同花顺概念成分,推荐使用概念名称进行查询,名称查询来自问财,概念代码来自网页
|
||||
:param concept_code: 概念代码,3开头
|
||||
:param name: 概念名称
|
||||
:return: 概念的成分股
|
||||
"""
|
||||
if concept_code:
|
||||
return self.__concept_constituent_ths_by_code(concept_code=concept_code)
|
||||
elif name:
|
||||
return self.__index_constituent_ths_by_name(name=name)
|
||||
else:
|
||||
return pd.DataFrame(data=[], columns=self.CONCEPT_CONSTITUENT_COLUMNS)
|
||||
|
||||
def __concept_constituent_ths_by_code(self, concept_code=None):
|
||||
"""
|
||||
同花顺概念成分股
|
||||
web_url :http://q.10jqka.com.cn/gn/detail/field/199112/order/desc/page/1/ajax/1/code/301539
|
||||
answer: http://www.iwencai.com/gateway/urp/v7/landing/getDataList?query=chatgpt%20%E6%A6%82%E5%BF%B5%E6%88%90%E5%88%86&page=1&perpage=100&query_type=stock&comp_id=6734520&uuid=24087
|
||||
:param concept_code: 概念代码: 301539
|
||||
:return:['concept_code', 'stock_code', 'short_name']
|
||||
"""
|
||||
# 1. url拼接页码等参数
|
||||
data = []
|
||||
total_pages = 1
|
||||
curr_page = 1
|
||||
while curr_page <= total_pages:
|
||||
api_url = f"http://q.10jqka.com.cn/gn/detail/field/199112/order/desc/page/" \
|
||||
f"{curr_page}/ajax/1/code/{concept_code}"
|
||||
headers = copy.deepcopy(ths_headers.text_headers)
|
||||
headers['Cookie'] = cookie.ths_cookie()
|
||||
res = requests.request(method='get', url=api_url, headers=headers, proxies={})
|
||||
curr_page += 1
|
||||
# 2. 判断请求是否成功
|
||||
if res.status_code != 200:
|
||||
continue
|
||||
text = res.text
|
||||
if '暂无成份股数据' in text or '概念板块' in text or '概念时间表' in text:
|
||||
break
|
||||
soup = BeautifulSoup(text, 'html.parser')
|
||||
# 3 .获取总的页数
|
||||
if total_pages == 1:
|
||||
page_info = soup.find('span', {'class': 'page_info'})
|
||||
if page_info:
|
||||
total_pages = int(page_info.text.split("/")[1])
|
||||
# 4. 解析数据
|
||||
page_data = []
|
||||
for idx, tr in enumerate(soup.find_all('tr')):
|
||||
if idx != 0:
|
||||
tds = tr.find_all('td')
|
||||
page_data.append({'stock_code': tds[1].contents[0].text, 'short_name': tds[2].contents[0].text})
|
||||
data.extend(page_data)
|
||||
# 5. 封装数据
|
||||
if not data:
|
||||
return pd.DataFrame(data=data, columns=self.CONCEPT_CONSTITUENT_COLUMNS)
|
||||
result_df = pd.DataFrame(data=data)
|
||||
data.clear()
|
||||
return result_df[self.CONCEPT_CONSTITUENT_COLUMNS]
|
||||
|
||||
def __index_constituent_ths_by_name(self, name=None):
|
||||
"""
|
||||
同花顺概念成分股,通过问财询问
|
||||
answer: http://www.iwencai.com/gateway/urp/v7/landing/getDataList?query=chatgpt%20%E6%A6%82%E5%BF%B5%E6%88%90%E5%88%86&page=1&perpage=100&query_type=stock&comp_id=6734520&uuid=24087
|
||||
:param name: 概念名称
|
||||
:return:['concept_code', 'stock_code', 'short_name']
|
||||
"""
|
||||
# 1. url拼接页码等参数
|
||||
data = []
|
||||
total_pages = 1
|
||||
curr_page = 1
|
||||
while curr_page <= total_pages:
|
||||
api_url = f"https://www.iwencai.com/gateway/urp/v7/landing/getDataList?query={name} 概念成分&" \
|
||||
f"page={curr_page}&perpage=100&query_type=stock&comp_id=6734520&uuid=24087"
|
||||
headers = copy.deepcopy(ths_headers.json_headers)
|
||||
headers['Host'] = 'www.iwencai.com'
|
||||
headers['Sec-Fetch-Mode'] = 'navigate'
|
||||
res = requests.request(method='get', url=api_url, headers=headers, proxies={})
|
||||
curr_page += 1
|
||||
# 2. 判断请求是否成功
|
||||
if res.status_code != 200:
|
||||
continue
|
||||
text = res.text.encode('utf-8').decode('unicode escape')
|
||||
if name not in text:
|
||||
break
|
||||
res_json = res.json()
|
||||
data_dic = res_json['answer']['components'][0]['data']
|
||||
# 3 .获取总的页数
|
||||
if total_pages == 1:
|
||||
total_pages = math.ceil(data_dic['meta']['extra']['code_count'] / 100)
|
||||
# 4. 解析数据
|
||||
page_data = []
|
||||
data_list = data_dic['datas']
|
||||
for one in data_list:
|
||||
if (name == one['所属概念']) or \
|
||||
('所属指数类' in one.keys() and (name == one['所属指数类'] or f"{name};" in one['所属指数类'])):
|
||||
page_data.append({'stock_code': one['code'], 'short_name': one['股票简称'], '': ''})
|
||||
data.extend(page_data)
|
||||
# 5. 封装数据
|
||||
if not data:
|
||||
return pd.DataFrame(data=data, columns=self.CONCEPT_CONSTITUENT_COLUMNS)
|
||||
result_df = pd.DataFrame(data=data)
|
||||
data.clear()
|
||||
return result_df[self.CONCEPT_CONSTITUENT_COLUMNS]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(StockConcept().all_concept_code_ths())
|
||||
print(StockConcept().concept_constituent_ths(name='东数西算(算力)'))
|
63
adata/stock/info/trade_calendar.py
Normal file
63
adata/stock/info/trade_calendar.py
Normal file
@ -0,0 +1,63 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: 交易日历
|
||||
@author: 1nchaos
|
||||
@time: 2023/3/28
|
||||
@log: change log
|
||||
"""
|
||||
import pandas as pd
|
||||
from tqdm import tqdm
|
||||
|
||||
from adata.common import requests
|
||||
|
||||
|
||||
class TradeCalendar(object):
|
||||
"""
|
||||
交易日历
|
||||
"""
|
||||
COLUMNS = ['trade_date', 'trade_status', 'day_week']
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
def trade_calendar(self, year=None):
|
||||
"""
|
||||
获取股票交易日历
|
||||
:return: 交易日历信息:
|
||||
trade_date: 交易日;
|
||||
day_week: 一周的第几天,从星期日开始;
|
||||
trade_status: 交易状态:1,交易日;0,非交易日
|
||||
"""
|
||||
return self.__calendar_szse(year=year)
|
||||
|
||||
def __calendar_szse(self, year=None):
|
||||
"""
|
||||
获取深交所交易日历
|
||||
web_url :http://www.szse.cn/api/report/exchange/onepersistenthour/monthList?month=2023-1
|
||||
:param year: 年份:'2023'
|
||||
:return: ['trade_date','day_week','trade_status']
|
||||
"""
|
||||
# 1. url,拼接月份
|
||||
data = []
|
||||
for i in tqdm(range(12)):
|
||||
api_url = f"http://www.szse.cn/api/report/exchange/onepersistenthour/monthList?month={year}-{i + 1}"
|
||||
res = requests.request(method='get', url=api_url, headers={}, proxies={})
|
||||
# 2. 判断请求是否成功
|
||||
if res.status_code != 200:
|
||||
continue
|
||||
res_json = res.json()
|
||||
# 3. 解析数据
|
||||
result = res_json['data']
|
||||
# 结果为空跳出循环
|
||||
if not result:
|
||||
break
|
||||
data.extend(result)
|
||||
# 4. 封装数据
|
||||
rename = {'jyrq': 'trade_date', 'jybz': 'trade_status', 'zrxh': 'day_week'}
|
||||
if not data:
|
||||
return pd.DataFrame(data=data, columns=self.COLUMNS)
|
||||
return pd.DataFrame(data=data).rename(columns=rename)[self.COLUMNS]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(TradeCalendar().trade_calendar(year=2024))
|
19
adata/stock/market/__init__.py
Normal file
19
adata/stock/market/__init__.py
Normal file
@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: 行情相关的数据
|
||||
@author: 1nchaos
|
||||
@time: 2023/3/29
|
||||
@log: change log
|
||||
"""
|
||||
from .stock_dividend import StockDividend
|
||||
from .stock_market import StockMarket
|
||||
from .stock_market_concept import StockMarketConcept
|
||||
|
||||
|
||||
class Market(StockMarket, StockMarketConcept, StockDividend):
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
|
||||
market = Market()
|
83
adata/stock/market/stock_dividend.py
Normal file
83
adata/stock/market/stock_dividend.py
Normal file
@ -0,0 +1,83 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: 股票分红信息
|
||||
数据来源:1. 百度
|
||||
|
||||
@author: 1nchaos
|
||||
@time: 2023/3/29
|
||||
@log: change log
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
|
||||
from adata.common.headers import baidu_headers
|
||||
from adata.common.utils import requests
|
||||
|
||||
|
||||
class StockDividend(object):
|
||||
"""
|
||||
股票分红
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
def get_dividend(self, stock_code='000001'):
|
||||
"""
|
||||
获取当个股票的分红信息
|
||||
:param stock_code: 股票代码
|
||||
:return: 股票分红信息
|
||||
"""
|
||||
return self.__dividend_baidu(stock_code)
|
||||
|
||||
def __dividend_baidu(self, stock_code):
|
||||
"""
|
||||
获取百度的股票分红数据:公告日;分红方案;除权除息日
|
||||
web: https://gushitong.baidu.com/stock/ab-300033
|
||||
url: https://gushitong.baidu.com/opendata?openapi=1&dspName=iphone&tn=tangram&
|
||||
client=app&query=300033&code=300033&word=300033&resource_id=5429&ma_ver=4&finClientType=pc
|
||||
:param stock_code: 6位股票代码
|
||||
:return: 股票分红信息
|
||||
"""
|
||||
columns = ['report_date', 'dividend_plan', 'ex_dividend_date']
|
||||
null_df = pd.DataFrame(data=[], columns=columns)
|
||||
# 1.请求接口 url
|
||||
api_url = f"https://gushitong.baidu.com/opendata?openapi=1&dspName=iphone&tn=tangram&client=app&" \
|
||||
f"query={stock_code}&code={stock_code}&word={stock_code}&resource_id=5429&ma_ver=4&finClientType=pc"
|
||||
res = requests.request('get', api_url, headers=baidu_headers.text_headers)
|
||||
|
||||
# 2. 判断结果是否正确
|
||||
if len(res.text) < 1 or res.status_code != 200:
|
||||
return pd.DataFrame()
|
||||
res_json = res.json()
|
||||
if res_json['ResultCode'] != '0':
|
||||
return null_df
|
||||
# 3.解析数据
|
||||
# 3.1 空数据时返回为空
|
||||
result = res_json['Result']
|
||||
if not result:
|
||||
return null_df
|
||||
|
||||
# 3.2 正常解析数据 basicInfo,shareholderEquity,organRating,executiveInfo,bonusTransfer
|
||||
try:
|
||||
new_company = result[-1]['DisplayData']['resultData']['tplData']['result']['tabs'][-1]['content'][
|
||||
'newCompany']
|
||||
bonus_transfer = new_company['bonusTransfer']
|
||||
header = bonus_transfer['header']
|
||||
body = bonus_transfer['body']
|
||||
except KeyError:
|
||||
# TODO logger
|
||||
return null_df
|
||||
|
||||
# 4. 封装数据
|
||||
result_df = pd.DataFrame(data=body, columns=header)[['公告日', '分红方案', '除权除息日']]
|
||||
result_df['stock_code'] = stock_code
|
||||
rename_columns = {'公告日': 'report_date', '分红方案': 'dividend_plan', '除权除息日': 'ex_dividend_date'}
|
||||
result_df = result_df.rename(columns=rename_columns)
|
||||
# 5. 数据清洗
|
||||
result_df = result_df[result_df.dividend_plan != '利润不分配']
|
||||
return result_df
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(StockDividend().get_dividend(stock_code='000001'))
|
225
adata/stock/market/stock_market.py
Normal file
225
adata/stock/market/stock_market.py
Normal file
@ -0,0 +1,225 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: readme
|
||||
@author: 1nchaos
|
||||
@time: 2023/3/29
|
||||
@log: change log
|
||||
"""
|
||||
|
||||
import time
|
||||
|
||||
import pandas as pd
|
||||
|
||||
from adata.common.headers import baidu_headers, sina_headers
|
||||
from adata.common.utils import requests
|
||||
|
||||
|
||||
class StockMarket(object):
|
||||
"""
|
||||
股票行情 TODO 数据返回类型转换
|
||||
"""
|
||||
MARKET_COLUMNS = ['trade_time', 'open', 'close', 'volume', 'high', 'low', 'amount', 'change', 'change_pct',
|
||||
'turnover_ratio', 'pre_close']
|
||||
MARKET_MIN_COLUMNS = ['stock_code', 'trade_time', 'price', 'change', 'change_pct', 'volume', 'avg_price', 'amount']
|
||||
MARKET_CURRENT_COLUMNS = ['stock_code', 'short_name', 'price', 'change', 'change_pct', 'volume', 'amount']
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
def get_market(self, stock_code: str = '000001', start_date='1990-01-01', k_type=1, adjust_type: int = 1):
|
||||
"""
|
||||
获取单个股票的行情
|
||||
:param stock_code: 股票代码
|
||||
:param start_date: 开始时间
|
||||
:param k_type: k线类型:1.日;2.周;3.月 默认:1 日k
|
||||
:param adjust_type: k线复权类型:0.不复权;1.前复权;2.后复权 默认:1 前复权 (目前:只有前复权,作为股票交易已经可用)
|
||||
:return: k线行情数据
|
||||
"""
|
||||
return self.__market_baidu(stock_code, start_date, k_type)
|
||||
|
||||
def get_market_min(self, stock_code: str = '000001'):
|
||||
"""
|
||||
获取单个股票的今日分时行情
|
||||
:param stock_code: 股票代码
|
||||
:return: 当日分钟行情数据
|
||||
"""
|
||||
return self.__market_baidu_today_min(stock_code)
|
||||
|
||||
def list_market_current(self, code_list=None):
|
||||
"""
|
||||
获取多个股票最新行情信息
|
||||
:param code_list: 股票代码
|
||||
:return: 当前最新的行情价格信息
|
||||
"""
|
||||
if code_list is None:
|
||||
return pd.DataFrame()
|
||||
return self.__market_sina_current(code_list=code_list)
|
||||
|
||||
def __market_baidu(self, stock_code, start_date, k_type=1):
|
||||
"""
|
||||
获取百度的股票行情数据
|
||||
web: https://gushitong.baidu.com/stock/ab-002926
|
||||
url:quotation_fiveday_ab 5日分时,quotation_kline_ab K线, quotation_minute_ab 当日分钟
|
||||
k线
|
||||
https://finance.pae.baidu.com/selfselect/getstockquotation?all=1&isIndex=false&isBk=false&isBlock=false&
|
||||
isFutures=false&isStock=true&newFormat=1&group=quotation_kline_ab&finClientType=pc&
|
||||
code=002926&start_time=2018-02-05 00:00:00&ktype=1
|
||||
分钟
|
||||
https://finance.pae.baidu.com/selfselect/getstockquotation?
|
||||
all=1&code=601318&isIndex=false&isBk=false&isBlock=false&isFutures=false&isStock=true&newFormat=1&
|
||||
group=quotation_minute_ab&finClientType=pc
|
||||
"ma5均价","ma5成交量","ma10均价","ma10成交量","ma20均价","ma20成交量"
|
||||
:param stock_code: 6位股票代码
|
||||
:param start_date: 开始时间
|
||||
:param k_type: k线类型:1.日;2.周;3.月
|
||||
# :param adjust_type: k线复权类型:0.不复权;1.前复权;2.后复权 默认:1 前复权 TODO
|
||||
:return: k线行情数据:"时间戳", "时间","开盘","收盘","成交量","最高","最低","成交额","涨跌额","涨跌幅","换手率","昨收"
|
||||
"""
|
||||
# 1. 请求接口 url
|
||||
api_url = f"https://finance.pae.baidu.com/selfselect/getstockquotation?all=1&isIndex=false&isBk=false&" \
|
||||
f"isBlock=false&isFutures=false&isStock=true&newFormat=1&group=quotation_kline_ab&finClientType=pc&" \
|
||||
f"code={stock_code}&start_time={start_date} 00:00:00&ktype={k_type}"
|
||||
|
||||
res_json = None
|
||||
for i in range(3):
|
||||
res = requests.request('get', api_url, headers=baidu_headers.json_headers, proxies={})
|
||||
# 2. 校验请求结果数据
|
||||
res_json = res.json()
|
||||
if res_json['ResultCode'] == '0':
|
||||
break
|
||||
time.sleep(2)
|
||||
# 3.解析数据
|
||||
# 3.1 空数据时返回为空
|
||||
result = res_json['Result']
|
||||
if not result:
|
||||
return pd.DataFrame(data=[], columns=self.MARKET_COLUMNS)
|
||||
|
||||
# 3.2. 正常解析数据
|
||||
keys = res_json['Result']['newMarketData']['keys']
|
||||
market_data = res_json['Result']['newMarketData']['marketData']
|
||||
market_data_list = str(market_data).split(';')
|
||||
data = []
|
||||
for one in market_data_list:
|
||||
data.append(one.split(','))
|
||||
|
||||
# 4. 封装数据
|
||||
rename_columns = {'turnoverratio': 'turnover_ratio', 'preClose': 'pre_close', 'range': 'change',
|
||||
'ratio': 'change_pct', 'time': 'trade_time'}
|
||||
result_df = pd.DataFrame(data=data, columns=keys).rename(columns=rename_columns)[self.MARKET_COLUMNS]
|
||||
result_df['stock_code'] = stock_code
|
||||
result_df['trade_date'] = result_df['trade_time']
|
||||
result_df['trade_time'] = pd.to_datetime(result_df['trade_time']).dt.strftime('%Y-%m-%d %H:%M:%S')
|
||||
result_df.replace('--', None, inplace=True)
|
||||
result_df.replace('', None, inplace=True)
|
||||
result_df['change'] = result_df['change'].str.replace('+', '', regex=True)
|
||||
result_df['change_pct'] = result_df['change_pct'].str.replace('+', '', regex=True)
|
||||
# 5. 数据清洗,剔除成交量为0的异常数据
|
||||
result_df['amount'] = result_df['amount'].astype(float)
|
||||
result_df = result_df[result_df['amount'] > 0]
|
||||
result_df.replace('--', None, inplace=True)
|
||||
result_df.replace('', None, inplace=True)
|
||||
result_df['change'] = result_df['change'].str.replace('+', '', regex=True).astype(float)
|
||||
result_df['change_pct'] = result_df['change_pct'].str.replace('+', '', regex=True).astype(float)
|
||||
return result_df
|
||||
|
||||
def __market_baidu_today_min(self, stock_code):
|
||||
"""
|
||||
获取百度的股票行情数据
|
||||
web: https://gushitong.baidu.com/stock/ab-002926
|
||||
url: https://finance.pae.baidu.com/selfselect/getstockquotation?
|
||||
all=1&code=601318&isIndex=false&isBk=false&isBlock=false&isFutures=false&isStock=true&newFormat=1
|
||||
&group=quotation_minute_ab&finClientType=pc
|
||||
time, price, ratio, increase, volume, avgPrice, amount, timeKey, datetime, oriAmount
|
||||
:param stock_code: 6位股票代码
|
||||
:return: k线行情数据:"时间","价格","涨跌率","涨幅","均价","成交量", "成交额"
|
||||
"""
|
||||
# 1. 请求接口 url
|
||||
api_url = f"https://finance.pae.baidu.com/selfselect/getstockquotation?all=1&isIndex=false&isBk=false&" \
|
||||
f"isBlock=false&isFutures=false&isStock=true&newFormat=1&group=quotation_minute_ab&" \
|
||||
f"finClientType=pc&code={stock_code}"
|
||||
|
||||
res_json = None
|
||||
for i in range(3):
|
||||
res = requests.request('get', api_url, headers=baidu_headers.json_headers, proxies={})
|
||||
# 2. 校验请求结果数据
|
||||
res_json = res.json()
|
||||
if res_json['ResultCode'] == '0':
|
||||
break
|
||||
time.sleep(2)
|
||||
# 3.解析数据
|
||||
# 3.1 空数据时返回为空
|
||||
result = res_json['Result']
|
||||
if not result:
|
||||
return pd.DataFrame(data=[], columns=self.MARKET_MIN_COLUMNS)
|
||||
|
||||
# 3.2. 正常解析数据
|
||||
market_data_list = res_json['Result']['priceinfo']
|
||||
|
||||
# 4. 封装数据
|
||||
field = ['time', 'price', 'ratio', 'increase', 'volume', 'avgPrice', 'amount', 'timeKey', 'datetime',
|
||||
'oriAmount']
|
||||
rename_columns = {'avgPrice': 'avg_price', 'oriAmount': 'ori_amount', 'ratio': 'change_pct',
|
||||
'increase': 'change'}
|
||||
result_df = pd.DataFrame(data=market_data_list, columns=field).rename(columns=rename_columns)
|
||||
result_df['amount'] = result_df['ori_amount']
|
||||
result_df['stock_code'] = stock_code
|
||||
# 这里是分钟均价,数据存在四舍五入的情况
|
||||
result_df['volume'] = result_df['volume'].astype(int) * 100
|
||||
result_df['trade_time'] = pd.to_datetime(result_df['time'], unit='s', utc=True).dt.tz_convert(
|
||||
'Asia/Shanghai')
|
||||
result_df['trade_time'] = pd.to_datetime(result_df['trade_time']).dt.strftime("%Y-%m-%d %H:%M:%S")
|
||||
result_df['trade_date'] = result_df['trade_time'].str[:10]
|
||||
result_df['change'] = result_df['change'].str.replace('+', '', regex=True).astype(float)
|
||||
result_df['change_pct'] = result_df['change_pct'].str.replace('+', '', regex=True).astype(float)
|
||||
return result_df[self.MARKET_MIN_COLUMNS]
|
||||
|
||||
def __market_sina_current(self, code_list):
|
||||
"""
|
||||
获取新浪的最新股票行情
|
||||
url : https://hq.sinajs.cn/list=s_sh600905,s_sz000725,s_sz000100,s_sh601919
|
||||
:param code_list: 代码列表
|
||||
:return: 最新行情数据:代码,简称,当前价格(元),涨跌额(元),涨跌幅(%),成交量(股),成交额(元)
|
||||
"""
|
||||
# 0.进行参数拼接处理
|
||||
api_url = f"https://hq.sinajs.cn/list="
|
||||
for code in code_list:
|
||||
if code.startswith('0') or code.startswith('3'):
|
||||
api_url += 's_sz' + code + ','
|
||||
elif code.startswith('6') or code.startswith('9'):
|
||||
api_url += 's_sh' + code + ','
|
||||
elif code.startswith('4') or code.startswith('8'):
|
||||
api_url += 's_bj' + code + ','
|
||||
|
||||
# 1.请求接口
|
||||
res = requests.request('get', api_url, headers=sina_headers.c_headers)
|
||||
|
||||
# 2. 判断结果是否正确
|
||||
if len(res.text) < 1 or res.status_code != 200:
|
||||
return pd.DataFrame(data=[], columns=self.MARKET_CURRENT_COLUMNS)
|
||||
# 3.解析数据
|
||||
|
||||
# 正常解析数据 var hq_str_s_bj872925="平安银行,14.840,0.480,3.343,374847,5483780.180";
|
||||
data_list = res.text.split(';')
|
||||
data = []
|
||||
for data_str in data_list:
|
||||
if len(data_str) < 8:
|
||||
continue
|
||||
idx = data_str.index('=')
|
||||
code = [data_str[idx - 6:idx]]
|
||||
code.extend(data_str[idx + 2:-1].split(','))
|
||||
if len(code) == 7:
|
||||
data.append(code)
|
||||
|
||||
# 4. 封装数据
|
||||
result_df = pd.DataFrame(data=data, columns=self.MARKET_CURRENT_COLUMNS)
|
||||
# 北京的单位是股和万元
|
||||
mask = result_df['stock_code'].str.startswith(('0', '3', '6', '9'))
|
||||
result_df.loc[mask, 'volume'] = result_df['volume'].astype(int) * 100
|
||||
result_df.loc[mask, 'amount'] = result_df['amount'].astype(float) * 10000
|
||||
return result_df
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(StockMarket().get_market(stock_code='000001', start_date='2021-01-01', k_type=1))
|
||||
# print(StockMarket().get_market_min(stock_code='000001'))
|
||||
# print(StockMarket().list_market_current(code_list=['000001', '600001', '000795', '872925']))
|
172
adata/stock/market/stock_market_concept.py
Normal file
172
adata/stock/market/stock_market_concept.py
Normal file
@ -0,0 +1,172 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@summary: 股票概念 行情
|
||||
同花顺概念更及时和完整,所以目前暂只基于同花顺的股票概念抓取,网页数据中心和手机概念板块
|
||||
http://d.10jqka.com.cn/v6/line/48_885772/01/last1800.js
|
||||
http://search.10jqka.com.cn/gateway/urp/v7/landing/getDataList?query=%E6%89%80%E6%9C%89%E6%A6%82%E5%BF%B5&condition=%5B%7B%22indexName%22%3A%22%E6%8C%87%E6%95%B0%40%E5%90%8C%E8%8A%B1%E9%A1%BA%E6%A6%82%E5%BF%B5%E6%8C%87%E6%95%B0%22%2C%22indexProperties%22%3A%5B%5D%2C%22source%22%3A%22new_parser%22%2C%22type%22%3A%22index%22%2C%22indexPropertiesMap%22%3A%7B%7D%2C%22reportType%22%3A%22null%22%2C%22chunkedResult%22%3A%22%E6%89%80%E6%9C%89%E6%A6%82%E5%BF%B5%22%2C%22valueType%22%3A%22_%E6%8C%87%E6%95%B0%E7%B1%BB%E5%9E%8B%22%2C%22domain%22%3A%22abs_a%E6%8C%87%E9%A2%86%E5%9F%9F%22%2C%22uiText%22%3A%22%E5%90%8C%E8%8A%B1%E9%A1%BA%E6%A6%82%E5%BF%B5%E6%8C%87%E6%95%B0%22%2C%22sonSize%22%3A0%2C%22queryText%22%3A%22%E5%90%8C%E8%8A%B1%E9%A1%BA%E6%A6%82%E5%BF%B5%E6%8C%87%E6%95%B0%22%2C%22relatedSize%22%3A0%7D%5D&urp_sort_index=%E6%8C%87%E6%95%B0%E4%BB%A3%E7%A0%81&source=Ths_iwencai_Xuangu&perpage=500&page=1&urp_sort_way=desc&codelist=&page_id=&logid=35df00ee5ae706d0dfcd0dbfdb846e0c&ret=json_all&sessionid=35df00ee5ae706d0dfcd0dbfdb846e0c&iwc_token=0ac9667016801698001765831&user_id=Ths_iwencai_Xuangu_7fahywzhbkrh4lwwkwfw936njqbjzsly&uuids%5B0%5D=23119&query_type=zhishu&comp_id=6367801&business_cat=soniu&uuid=23119
|
||||
885772 表示同花顺的概念指数的代码
|
||||
@author: 1nchaos
|
||||
@date: 2023/3/30 16:17
|
||||
"""
|
||||
import copy
|
||||
import json
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
from adata.common.headers import ths_headers
|
||||
from adata.common.utils import requests, cookie
|
||||
|
||||
|
||||
class StockMarketConcept(object):
|
||||
"""
|
||||
股票概念 行情
|
||||
"""
|
||||
COLUMNS = ['trade_date', 'open', 'high', 'low', 'close', 'volume', 'amount']
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
def get_market_concept_ths(self, index_code: str = '886013', k_type: int = 1, adjust_type: int = 1):
|
||||
"""
|
||||
获取同花顺的概率的行情
|
||||
web: http://q.10jqka.com.cn/gn/
|
||||
pc: http://d.10jqka.com.cn/v4/line/bk_885772/21/last.js
|
||||
app: http://d.10jqka.com.cn/v6/line/48_886013/01/last1800.js
|
||||
00 日k不复权;01日k前复权;02日k后复权;11周k前复权;21月k前复权
|
||||
:param index_code: 同花顺概念指数代码
|
||||
:param k_type: k线类型:1.日;2.周;3.月 默认:1 日k
|
||||
:param adjust_type: k线复权类型:0.不复权;1.前复权;2.后复权 默认:1 前复权
|
||||
:return: k线行情数据 [日期,开,高,低,收,成交量,成交额]
|
||||
;20230419,958.901,981.118,958.449,961.107,521143220,20442229000.000
|
||||
成交量:股 820953530 821万手
|
||||
成交额:元 16959251000.000 169.6亿
|
||||
"""
|
||||
# 0.参数校验
|
||||
if not index_code.startswith('8'):
|
||||
raise RuntimeError('index_code错误,是8开头的指数代码,')
|
||||
# 1.接口 url
|
||||
api_url = f"http://d.10jqka.com.cn/v6/line/48_{index_code}/{k_type - 1}{adjust_type}/last1800.js"
|
||||
# 同花顺可能ip限制,降低请求次数
|
||||
text = self.__get_text(api_url, index_code)
|
||||
if '<h1>Nginx forbidden.</h1>' in text:
|
||||
raise Exception('ip被限制了:请降低频率或更换ip')
|
||||
result_text = text[text.index('{'):-1]
|
||||
data_list = json.loads(result_text)['data'].split(';')
|
||||
data = []
|
||||
for d in data_list:
|
||||
data.append(str(d).split(',')[0:7])
|
||||
result_df = pd.DataFrame(data=data, columns=self.COLUMNS)
|
||||
result_df['index_code'] = index_code
|
||||
result_df['trade_time'] = pd.to_datetime(result_df['trade_date']).dt.strftime('%Y-%m-%d %H:%M:%S')
|
||||
result_df['trade_date'] = pd.to_datetime(result_df['trade_date'], format='%Y%m%d').dt.strftime('%Y-%m-%d')
|
||||
result_df['close'] = result_df['close'].astype(float)
|
||||
result_df['change'] = result_df['close'] - result_df['close'].shift(1)
|
||||
result_df['change_pct'] = result_df['change'] / result_df['close'].shift(1) * 100
|
||||
result_df.replace('--', None, inplace=True)
|
||||
result_df.replace('', None, inplace=True)
|
||||
result_df.replace(np.nan, None, inplace=True)
|
||||
return result_df
|
||||
|
||||
def get_market_concept_min_ths(self, index_code):
|
||||
"""
|
||||
获取概念行情当日分时
|
||||
web: http://d.10jqka.com.cn/v6/time/48_886013/last.js
|
||||
0930,958.901,74456973,36.807,2022925; "pre": "960.374",
|
||||
:param index_code: 概念指数代码
|
||||
:return 时间,现价,成交额(元),均价,成交量(股) 涨跌额,涨跌幅
|
||||
'index_code', 'trade_time', 'price', 'change', 'change_pct', 'volume', 'avg_price', 'amount'
|
||||
"""
|
||||
# 1.接口 url
|
||||
api_url = f"http://d.10jqka.com.cn/v6/time/48_{index_code}/last.js"
|
||||
text = self.__get_text(api_url, index_code)
|
||||
if '<h1>Nginx forbidden.</h1>' in text:
|
||||
raise Exception('ip被限制了:请降低频率或更换ip')
|
||||
# 2. 解析数据
|
||||
result_json = json.loads(text[text.index('{'):-1])[f"48_{index_code}"]
|
||||
pre_price = result_json['pre']
|
||||
trade_date = result_json['date']
|
||||
data_list = result_json['data'].split(';')
|
||||
data = []
|
||||
for d in data_list:
|
||||
data.append(str(d).split(','))
|
||||
# 3. 封装数据
|
||||
result_df = pd.DataFrame(data=data, columns=['trade_time', 'price', 'amount', 'avg_price', 'volume'])
|
||||
result_df['index_code'] = index_code
|
||||
result_df['trade_time'] = trade_date + result_df['trade_time']
|
||||
result_df['trade_date'] = pd.to_datetime(trade_date, format='%Y%m%d').strftime('%Y-%m-%d')
|
||||
result_df['trade_time'] = pd.to_datetime(result_df['trade_time'], format='%Y%m%d%H%M').dt.strftime(
|
||||
'%Y-%m-%d %H:%M:%S')
|
||||
result_df['price'] = result_df['price']
|
||||
result_df['change'] = result_df['price'].astype(float) - float(pre_price)
|
||||
result_df['change_pct'] = result_df['change'] / float(pre_price) * 100
|
||||
result_df.replace('--', None, inplace=True)
|
||||
result_df.replace('', None, inplace=True)
|
||||
result_df.replace(np.nan, None, inplace=True)
|
||||
return result_df
|
||||
|
||||
def get_market_concept_today_ths(self, index_code: str = '886013', k_type: int = 1, adjust_type: int = 1):
|
||||
"""
|
||||
获取同花顺当前的概念行情
|
||||
web: http://q.10jqka.com.cn/gn/
|
||||
pc: http://d.10jqka.com.cn/v6/line/48_886042/01/today.js
|
||||
quotebridge_v6_line_48_886042_01_today({"48_886042":{"1":"20230425","7":"891.344","8":"892.350","9":"853.800",
|
||||
"11":"860.076","13":491708080,"19":"17647511000.000","74":"","1968584":"","66":"","open":1,"dt":"2244",
|
||||
"name":"\u5b58\u50a8\u82af\u7247","marketType":""}})
|
||||
|
||||
:param index_code: 同花顺概念指数代码
|
||||
:param k_type: k线类型:1.日;2.周;3.月 默认:1 日k
|
||||
:param adjust_type: k线复权类型:0.不复权;1.前复权;2.后复权 默认:1 前复权
|
||||
:return: k线行情数据 [概念代码,交易时间,交易日期,开,高,低,当前价格,成交量,成交额]
|
||||
;20230419,958.901,981.118,958.449,961.107,521143220,20442229000.000,存储芯片
|
||||
k: 1, 7, 8, 9, 11, 13, 19, name
|
||||
成交量:股 820953530 821万手
|
||||
成交额:元 16959251000.000 169.6亿
|
||||
"""
|
||||
# 1.接口 url
|
||||
api_url = f"http://d.10jqka.com.cn/v6/line/48_{index_code}/{k_type - 1}{adjust_type}/today.js"
|
||||
headers = copy.deepcopy(ths_headers.text_headers)
|
||||
headers['Host'] = 'd.10jqka.com.cn'
|
||||
# 同花顺可能ip限制,降低请求次数
|
||||
text = self.__get_text(api_url, index_code)
|
||||
if '<h1>Nginx forbidden.</h1>' in text:
|
||||
raise Exception('ip被限制了:请降低频率或更换ip')
|
||||
result_text = text[text.index('{'):-1]
|
||||
data_list = [json.loads(result_text)[f"48_{index_code}"]]
|
||||
rename = {'1': 'trade_date', '7': 'open', '8': 'high', '9': 'low', '11': 'price', '13': 'volume',
|
||||
'19': 'amount', 'open': 'status'}
|
||||
result_df = pd.DataFrame(data=data_list).rename(columns=rename)
|
||||
result_df['trade_time'] = result_df['trade_date'] + result_df['dt']
|
||||
result_df['trade_time'] = pd.to_datetime(result_df['trade_time'], format='%Y%m%d%H%M').dt.strftime(
|
||||
'%Y-%m-%d %H:%M:%S')
|
||||
columns = ['trade_time', 'trade_date', 'open', 'high', 'low', 'price', 'volume', 'amount']
|
||||
result_df = result_df[columns]
|
||||
result_df['index_code'] = index_code
|
||||
result_df['trade_date'] = pd.to_datetime(result_df['trade_date'], format='%Y%m%d').dt.strftime('%Y-%m-%d')
|
||||
return result_df
|
||||
|
||||
def __get_text(self, api_url, code):
|
||||
"""
|
||||
获取同花顺的请求 text
|
||||
:param api_url: url
|
||||
:param code: 代码
|
||||
:return:
|
||||
"""
|
||||
headers = copy.deepcopy(ths_headers.text_headers)
|
||||
headers['Host'] = 'd.10jqka.com.cn'
|
||||
headers['Cookie'] = cookie.ths_cookie()
|
||||
text = ''
|
||||
for i in range(2):
|
||||
res = requests.request('get', api_url, headers=headers, proxies={})
|
||||
text = res.text
|
||||
if code in text:
|
||||
break
|
||||
time.sleep(2)
|
||||
return text
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(StockMarketConcept().get_market_concept_ths(index_code='886041'))
|
||||
print(StockMarketConcept().get_market_concept_min_ths(index_code='886041'))
|
||||
print(StockMarketConcept().get_market_concept_today_ths(index_code='886041'))
|
7
adata/stock/sentiment/__init__.py
Normal file
7
adata/stock/sentiment/__init__.py
Normal file
@ -0,0 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: 新闻舆情相关的数据
|
||||
@author: 1nchaos
|
||||
@time:2023/04/06
|
||||
@log:
|
||||
"""
|
0
config.toml
Normal file
0
config.toml
Normal file
154
docs/DIC.md
Normal file
154
docs/DIC.md
Normal file
@ -0,0 +1,154 @@
|
||||
# AData 字典表
|
||||
|
||||
> 整个项目API的数据字典,按照模块层级分类命名,描述尽量精简,以便进行查阅。
|
||||
|
||||
## 股票-stock
|
||||
|
||||
### 一、基本信息-Info
|
||||
|
||||
#### 1. 股票代码信息(info)
|
||||
|
||||
| 字段 | 类型 | 注释 | 说明 |
|
||||
| ---------- | ------ | ------ | --------------------------- |
|
||||
| stock_code | string | 代码 | 600001 |
|
||||
| short_name | string | 简称 | 中国平安 |
|
||||
| exchange | string | 交易所 | SH:上交;BJ:北交;SZ:深交 |
|
||||
|
||||
#### 2. 概念指数信息(index-concept)
|
||||
|
||||
| 字段 | 类型 | 注释 | 说明 |
|
||||
| ------------ | ------ | -------- | --------------------------------------------------- |
|
||||
| name | string | 名称 | 物联网 |
|
||||
| index_code | string | 指数代码 | 同花顺的概念指数代码是:8开头;例:885312 |
|
||||
| concept_code | string | 概念代码 | 同花顺的概念代码是:3开头;例:309061;注意不要混淆 |
|
||||
| soruce | string | 来源 | |
|
||||
|
||||
#### 11. 交易日历
|
||||
|
||||
| 字段 | 类型 | 注释 | 说明 |
|
||||
| ------------ | ---- | ------------------------------ | -------------- |
|
||||
| trade_date | date | 交易日 | 2023-05-20 |
|
||||
| trade_status | int | 交易状态:0.非交易日;1.交易日 | 1 |
|
||||
| day_week | int | 一周第几天 | 从星期天开始的 |
|
||||
|
||||
### 二、行情信息-Market
|
||||
|
||||
#### 1. 分红(dividend)
|
||||
|
||||
| 字段 | 类型 | 注释 | 说明 |
|
||||
| ---------------- | ------ | ---------- | ---------------------------- |
|
||||
| stock_code | string | 代码 | 600001 |
|
||||
| report_date | date | 公告日 | 1990-01-01 |
|
||||
| dividend_plan | string | 分红方案 | 10股派3.00元,10股转赠5.00股 |
|
||||
| ex_dividend_date | date | 除权除息日 | 1990-01-01 |
|
||||
|
||||
|
||||
|
||||
#### 2. 行情(market)
|
||||
|
||||
##### 2.1 k线
|
||||
|
||||
| 字段 | 类型 | 注释 | 说明 |
|
||||
| -------------- | ------- | ---------- | ----------------------------------------- |
|
||||
| stock_code | string | 代码 | 600001 |
|
||||
| trade_time | time | 交易时间 | 1990-01-01 00:00:00;分时图使用具体的时间 |
|
||||
| trade_date | date | 交易日期 | 1990-01-01 |
|
||||
| open | decimal | 开盘价(元) | 9.98 |
|
||||
| close | decimal | 收盘价(元) | 9.98 |
|
||||
| high | decimal | 最高价(元) | 9.98 |
|
||||
| low | decimal | 最低价(元) | 9.98 |
|
||||
| volume | decimal | 成交量(股) | 64745722 |
|
||||
| amount | decimal | 成交额(元) | 934285179.00 |
|
||||
| change | decimal | 涨跌额(元) | -0.02 |
|
||||
| change_pct | decimal | 涨跌幅(%) | -0.16 |
|
||||
| turnover_ratio | decimal | 换手率(%) | 0.38 |
|
||||
| pre_close | decimal | 昨收(元) | 10.00 |
|
||||
|
||||
##### 2.2 分时
|
||||
|
||||
| 字段 | 类型 | 注释 | 说明 |
|
||||
| ---------- | ------- | ---------- | ----------------------------------------- |
|
||||
| stock_code | string | 代码 | 600001 |
|
||||
| trade_time | time | 交易时间 | 1990-01-01 00:00:00;分时图使用具体的时间 |
|
||||
| trade_date | date | 交易日期 | 1990-01-01 |
|
||||
| price | decimal | 价格(元) | 9.98 |
|
||||
| avg_price | decimal | 平均价(元) | 9.98 |
|
||||
| change | decimal | 涨跌额(元) | -0.02 |
|
||||
| change_pct | decimal | 涨跌幅(%) | -0.16 |
|
||||
| volume | decimal | 成交量(股) | 64745722 |
|
||||
| amount | decimal | 成交额(元) | 934285179.00 |
|
||||
|
||||
##### 2.3 实时
|
||||
|
||||
| 字段 | 类型 | 注释 | 说明 |
|
||||
| ---------- | ------- | ------------ | -------- |
|
||||
| stock_code | string | 代码 | 600001 |
|
||||
| short_name | string | 简称 | 平安银行 |
|
||||
| price | decimal | 当前价格(元) | 12.36 |
|
||||
| change | decimal | 涨跌额(元) | 0.02 |
|
||||
| change_pct | decimal | 涨跌幅(%) | 0.16 |
|
||||
| volume | decimal | 成交量(股) | 34452500 |
|
||||
| amount | decimal | 成交额(元) | |
|
||||
|
||||
#### 3. 概念行情(concept market)
|
||||
|
||||
##### 3.1 k线
|
||||
|
||||
| 字段 | 类型 | 注释 | 说明 |
|
||||
| ---------- | ------- | ---------- | ----------------------------------------- |
|
||||
| index_code | string | 代码 | 886041 |
|
||||
| trade_time | time | 交易时间 | 1990-01-01 00:00:00;分时图使用具体的时间 |
|
||||
| trade_date | date | 交易日期 | 1990-01-01 |
|
||||
| open | decimal | 开盘价(元) | 9.98 |
|
||||
| close | decimal | 收盘价(元) | 9.98 |
|
||||
| high | decimal | 最高价(元) | 9.98 |
|
||||
| low | decimal | 最低价(元) | 9.98 |
|
||||
| volume | decimal | 成交量(股) | 64745722 |
|
||||
| amount | decimal | 成交额(元) | 934285179.00 |
|
||||
| change | decimal | 涨跌额(元) | -0.02 |
|
||||
| change_pct | decimal | 涨跌幅(%) | -0.16 |
|
||||
|
||||
##### 3.2 分时
|
||||
|
||||
| 字段 | 类型 | 注释 | 说明 |
|
||||
| ---------- | ------- | ---------- | ----------------------------------------- |
|
||||
| index_code | string | 代码 | 886041 |
|
||||
| trade_time | time | 交易时间 | 1990-01-01 00:00:00;分时图使用具体的时间 |
|
||||
| trade_date | date | 交易日期 | 1990-01-01 |
|
||||
| price | decimal | 现价(元) | 9.98 |
|
||||
| avg_price | decimal | 均价价(元) | 9.98 |
|
||||
| high | decimal | 最高价(元) | 9.98 |
|
||||
| low | decimal | 最低价(元) | 9.98 |
|
||||
| volume | decimal | 成交量(股) | 64745722 |
|
||||
| amount | decimal | 成交额(元) | 934285179.00 |
|
||||
| change | decimal | 涨跌额(元) | -0.02 |
|
||||
| change_pct | decimal | 涨跌幅(%) | -0.16 |
|
||||
|
||||
##### 3.3 实时
|
||||
|
||||
| 字段 | 类型 | 注释 | 说明 |
|
||||
| ---------- | ------- | ---------- | ----------------------------------- |
|
||||
| index_code | string | 代码 | 886041 |
|
||||
| trade_time | time | 交易时间 | 1990-01-01 00:00:00;返回当前的时间 |
|
||||
| trade_date | date | 交易日期 | 1990-01-01 |
|
||||
| open | decimal | 开盘价(元) | 9.98 |
|
||||
| price | decimal | 现价(元) | 9.98 |
|
||||
| high | decimal | 最高价(元) | 9.98 |
|
||||
| low | decimal | 最低价(元) | 9.98 |
|
||||
| volume | decimal | 成交量(股) | 64745722 |
|
||||
| amount | decimal | 成交额(元) | 934285179.00 |
|
||||
|
||||
## 债券-Bond
|
||||
|
||||
## 基金-ETF
|
||||
|
||||
## 舆情
|
||||
|
||||
### 更新记录
|
||||
|
||||
| 相关版本 | 更新日期 | 更新内容 | 备注 |
|
||||
| -------- | -------- | -------- | ---- |
|
||||
| | | | |
|
||||
| | | | |
|
||||
| | | | |
|
||||
|
33
docs/temp.md
Normal file
33
docs/temp.md
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
### 打包上传的步骤
|
||||
4、安装打包工具
|
||||
|
||||
python -m pip install --upgrade setuptools wheel
|
||||
|
||||
5、打包模块
|
||||
|
||||
# 创建存放模块的目录,执行如下命令
|
||||
python setup.py sdist bdist_wheel
|
||||
|
||||
6、上传模块
|
||||
|
||||
6.1、安装用于发布模块的工具:twine 【已安装无需重复安装】
|
||||
|
||||
python -m pip install --upgrade twine
|
||||
或
|
||||
pip install --upgrade twine
|
||||
|
||||
提示:python -m 的作用是 run library module as a script (terminates option list)[作为脚本运行库模块(终止选项列表)]
|
||||
|
||||
6.2、发布(上传)
|
||||
|
||||
python -m twine upload --repository-url https://upload.pypi.org/legacy/ dist/*
|
||||
或
|
||||
twine upload --repository-url https://upload.pypi.org/legacy/ dist/*
|
||||
|
||||
注意:上传时,提示需要输入PyPI的用户名和密码.
|
||||
|
||||
7、测试在线安装模块
|
||||
|
||||
|
||||
|
5
requirements.txt
Normal file
5
requirements.txt
Normal file
@ -0,0 +1,5 @@
|
||||
tqdm~=4.65.0
|
||||
requests~=2.26.0
|
||||
pandas~=1.5.3
|
||||
beautifulsoup4~=4.11.2
|
||||
py_mini_racer>=0.6.0
|
65
setup.py
Normal file
65
setup.py
Normal file
@ -0,0 +1,65 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: setup
|
||||
@author: 1nchaos
|
||||
@time: 2023/04/05
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from setuptools import find_packages
|
||||
|
||||
here = os.path.abspath(os.path.dirname(__file__))
|
||||
about = {}
|
||||
with open(os.path.join(here, "adata", "__version__.py"), "r") as f:
|
||||
exec(f.read(), about)
|
||||
|
||||
with open("README.md", "r", encoding='utf-8') as f:
|
||||
readme = f.read()
|
||||
|
||||
requires = [
|
||||
"tqdm~=4.65.0",
|
||||
"requests~=2.26.0",
|
||||
"pandas~=1.5.3",
|
||||
"beautifulsoup4~=4.11.2",
|
||||
"py_mini_racer~=0.6.0",
|
||||
]
|
||||
|
||||
|
||||
def setup_package():
|
||||
metadata = dict(
|
||||
name=about["__title__"],
|
||||
version=about["__version__"],
|
||||
description=about["__description__"],
|
||||
long_description=readme,
|
||||
long_description_content_type="text/markdown",
|
||||
url=about["__url__"],
|
||||
author=about["__author__"],
|
||||
author_email=about["__author_email__"],
|
||||
license=about["__license__"],
|
||||
packages=find_packages(exclude=("tests", "docs")),
|
||||
install_requires=requires,
|
||||
include_package_data=True,
|
||||
classifiers=[
|
||||
# Trove classifiers
|
||||
# Full list: https://pypi.python.org/pypi?%3Aaction=list_classifiers
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python :: 3.7",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
],
|
||||
)
|
||||
|
||||
try:
|
||||
from setuptools import setup
|
||||
except ImportError:
|
||||
from distutils.core import setup
|
||||
|
||||
setup(**metadata)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
setup_package()
|
6
tests/__init__.py
Normal file
6
tests/__init__.py
Normal file
@ -0,0 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@summary:
|
||||
@author: 1nchaos
|
||||
@date: 2023/3/30 10:00
|
||||
"""
|
23
tests/bs4_test.py
Normal file
23
tests/bs4_test.py
Normal file
@ -0,0 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@desc: readme
|
||||
@author: 1nchaos
|
||||
@time: 2023/5/8
|
||||
@log: change log
|
||||
"""
|
||||
import re
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
if __name__ == '__main__':
|
||||
html = '''<div class="m-pager" id="m-page">
|
||||
<a class="cur" page="1" href="javascript:void(0)">1</a> <a class="changePage" page="2" href="javascript:void(0);">2</a> <a class="changePage" page="3" href="javascript:void(0);">3</a> <a class="changePage" page="4" href="javascript:void(0);">4</a> <a class="changePage" page="5" href="javascript:void(0);">5</a> <a class="changePage" page="2" href="javascript:void(0);">下一页</a><a class="changePage" page="10" href="javascript:void(0);">尾页</a><span class="page_info">1/10</span>
|
||||
</div>'''
|
||||
|
||||
soup = BeautifulSoup(html, 'html.parser')
|
||||
|
||||
# 获取总页数
|
||||
page_info = soup.find('span', {'class': 'page_info'}).text
|
||||
total_pages = int(page_info.split("/")[1])
|
||||
|
||||
print(total_pages) # 输出: 10
|
21
tests/stock_test.py
Normal file
21
tests/stock_test.py
Normal file
@ -0,0 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@summary:
|
||||
@author: 1nchaos
|
||||
@date: 2023/3/30 10:00
|
||||
"""
|
||||
|
||||
from adata import *
|
||||
from adata.stock.market import *
|
||||
|
||||
# from adata.stock import dividend
|
||||
|
||||
if __name__ == '__main__':
|
||||
# print(stock.market.dividend.get_dividend('000001'))
|
||||
# print(code.all_code())
|
||||
# print(sd.stock.info.all_gn_code_ths())
|
||||
# print(stock.info.all_gn_code_ths())
|
||||
# print(sd.stock.info.code.all_code())
|
||||
# print(sd.stock.market.gn_market.get_market_gn_ths())
|
||||
# print(stock.market.stock_market.get_market())
|
||||
print(market.get_market())
|
Loading…
Reference in New Issue
Block a user