mns-common 1.4.1.8__py3-none-any.whl → 1.5.7.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. mns_common/api/akshare/__init__.py +0 -1
  2. mns_common/api/akshare/k_line_api.py +19 -2
  3. mns_common/api/akshare/stock_bid_ask_api.py +10 -3
  4. mns_common/api/akshare/stock_zb_pool.py +2 -0
  5. mns_common/api/akshare/stock_zt_pool_api.py +1 -1
  6. mns_common/api/em/gd/east_money_stock_gdfx_free_top_10_api.py +62 -7
  7. mns_common/api/em/real_time/__init__.py +1 -1
  8. mns_common/api/em/real_time/east_money_debt_api.py +140 -70
  9. mns_common/api/em/real_time/east_money_etf_api.py +138 -27
  10. mns_common/api/em/real_time/east_money_stock_a_api.py +24 -28
  11. mns_common/api/em/real_time/east_money_stock_a_v2_api.py +97 -53
  12. mns_common/api/em/real_time/east_money_stock_common_api.py +174 -0
  13. mns_common/api/em/real_time/east_money_stock_hk_api.py +223 -272
  14. mns_common/api/em/real_time/east_money_stock_hk_gtt_api.py +260 -0
  15. mns_common/api/em/real_time/east_money_stock_multi_thread_api_v3.py +154 -0
  16. mns_common/api/em/real_time/east_money_stock_us_api.py +146 -82
  17. mns_common/api/em/real_time/real_time_quotes_repeat_api.py +195 -0
  18. mns_common/api/k_line/stock_k_line_data_api.py +11 -1
  19. mns_common/api/kpl/common/kpl_common_api.py +35 -0
  20. mns_common/api/proxies/liu_guan_proxy_api.py +55 -5
  21. mns_common/api/ths/company/company_product_area_industry_index_query.py +46 -0
  22. mns_common/api/ths/company/ths_company_info_api.py +2 -1
  23. mns_common/api/ths/company/ths_company_info_web.py +159 -0
  24. mns_common/api/ths/concept/app/ths_concept_index_app.py +3 -1
  25. mns_common/api/ths/wen_cai/ths_wen_cai_api.py +1 -1
  26. mns_common/api/ths/zt/ths_stock_zt_pool_api.py +20 -1
  27. mns_common/api/ths/zt/ths_stock_zt_pool_v2_api.py +105 -29
  28. mns_common/api/xueqiu/xue_qiu_k_line_api.py +2 -2
  29. mns_common/component/common_service_fun_api.py +26 -6
  30. mns_common/component/data/data_init_api.py +13 -8
  31. mns_common/component/deal/deal_service_api.py +70 -8
  32. mns_common/component/deal/deal_service_v2_api.py +167 -0
  33. mns_common/component/em/em_stock_info_api.py +9 -3
  34. mns_common/component/main_line/main_line_zt_reason_service.py +237 -0
  35. mns_common/component/proxies/proxy_common_api.py +141 -45
  36. mns_common/component/us/us_stock_etf_info_api.py +125 -0
  37. mns_common/constant/db_name_constant.py +40 -16
  38. mns_common/constant/extra_income_db_name.py +79 -19
  39. mns_common/constant/strategy_classify.py +17 -2
  40. mns_common/db/MongodbUtil.py +3 -0
  41. mns_common/db/MongodbUtilLocal.py +3 -0
  42. {mns_common-1.4.1.8.dist-info → mns_common-1.5.7.2.dist-info}/METADATA +1 -1
  43. {mns_common-1.4.1.8.dist-info → mns_common-1.5.7.2.dist-info}/RECORD +47 -41
  44. mns_common/api/ths/concept/web/ths_company_info_web.py +0 -163
  45. mns_common/component/qmt/qmt_buy_service.py +0 -172
  46. mns_common/component/task/real_time_data_sync_check.py +0 -110
  47. /mns_common/component/{qmt → main_line}/__init__.py +0 -0
  48. /mns_common/component/{task → us}/__init__.py +0 -0
  49. {mns_common-1.4.1.8.dist-info → mns_common-1.5.7.2.dist-info}/WHEEL +0 -0
  50. {mns_common-1.4.1.8.dist-info → mns_common-1.5.7.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,260 @@
1
+ import sys
2
+ import os
3
+
4
+ file_path = os.path.abspath(__file__)
5
+ end = file_path.index('mns') + 16
6
+ project_path = file_path[0:end]
7
+ sys.path.append(project_path)
8
+
9
+ import pandas as pd
10
+ from loguru import logger
11
+ import requests
12
+ import time
13
+ import mns_common.component.proxies.proxy_common_api as proxy_common_api
14
+ import concurrent.futures
15
+
16
+ from threading import Lock
17
+ import mns_common.utils.data_frame_util as data_frame_util
18
+
19
+ # 分页条数
20
+ page_number = 100
21
+
22
+
23
+ def rename_hg_ggt(temp_df):
24
+ temp_df.columns = [
25
+ "序号",
26
+ "-",
27
+ "最新价",
28
+ "涨跌幅",
29
+ "涨跌额",
30
+ "成交量",
31
+ "成交额",
32
+ "-",
33
+ "-",
34
+ "-",
35
+ "-",
36
+ "-",
37
+ "代码",
38
+ "-",
39
+ "名称",
40
+ "最高",
41
+ "最低",
42
+ "今开",
43
+ "昨收",
44
+ "-",
45
+ "-",
46
+ "-",
47
+ "-",
48
+ "-",
49
+ "-",
50
+ "-",
51
+ "-",
52
+ "-",
53
+ "-",
54
+ "-",
55
+ "-",
56
+ "-",
57
+ "-",
58
+ "-",
59
+ "-",
60
+ ]
61
+ temp_df = temp_df[
62
+ [
63
+ "序号",
64
+ "代码",
65
+ "名称",
66
+ "最新价",
67
+ "涨跌额",
68
+ "涨跌幅",
69
+ "今开",
70
+ "最高",
71
+ "最低",
72
+ "昨收",
73
+ "成交量",
74
+ "成交额",
75
+ ]
76
+ ]
77
+
78
+ temp_df = temp_df.rename(columns={
79
+ "序号": "index",
80
+ "代码": "symbol",
81
+ "名称": "name",
82
+ "最新价": "now_price",
83
+ "涨跌额": "range",
84
+ "涨跌幅": "chg",
85
+ "今开": "open",
86
+ "最高": "high",
87
+ "最低": "low",
88
+ "昨收": "yesterday_price",
89
+ "成交额": "amount",
90
+ "成交量": "volume",
91
+ })
92
+
93
+ return temp_df
94
+
95
+
96
+ # 获取港股通个数
97
+ def get_stock_hk_ggt_components_em_count(cookie, pn, proxies, page_size, time_out):
98
+ headers = {
99
+ 'Cookie': cookie
100
+ }
101
+ url = "https://33.push2.eastmoney.com/api/qt/clist/get"
102
+ current_timestamp = str(int(round(time.time() * 1000, 0)))
103
+ params = {
104
+ "pn": str(pn),
105
+ "pz": str(page_size),
106
+ "po": "1",
107
+ "np": "2",
108
+ "ut": "bd1d9ddb04089700cf9c27f6f7426281",
109
+ "fltt": "2",
110
+ "fid": "f3",
111
+ "fs": "b:DLMK0146,b:DLMK0144",
112
+ "fields": "f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18,f19,f20,f21,f23,f24,"
113
+ "f25,f26,f22,f33,f11,f62,f128,f136,f115,f152",
114
+ "_": str(current_timestamp),
115
+ }
116
+ try:
117
+ if proxies is None:
118
+ r = requests.get(url, params, timeout=time_out, headers=headers)
119
+ else:
120
+ r = requests.get(url, params, proxies=proxies, timeout=time_out, headers=headers)
121
+ data_json = r.json()
122
+ total_number = int(data_json['data']['total'])
123
+ return total_number
124
+ except Exception as e:
125
+ logger.error("获取港股通列表,实时行情异常:{}", e)
126
+ return 0
127
+
128
+
129
+ # 获取港股通名单 todo 被封以后替换
130
+ def stock_hk_ggt_components_em(cookie, pn, proxies, page_size, time_out) -> pd.DataFrame:
131
+ """
132
+ 东方财富网-行情中心-港股市场-港股通成份股
133
+ https://quote.eastmoney.com/center/gridlist.html#hk_components
134
+ :return: 港股通成份股
135
+ :rtype: pandas.DataFrame
136
+ """
137
+ headers = {
138
+ 'Cookie': cookie
139
+ }
140
+ url = "https://33.push2.eastmoney.com/api/qt/clist/get"
141
+ params = {
142
+ "pn": str(pn),
143
+ "pz": str(page_size),
144
+ "po": "1",
145
+ "np": "2",
146
+ "ut": "bd1d9ddb04089700cf9c27f6f7426281",
147
+ "fltt": "2",
148
+ "fid": "f3",
149
+ "fs": "b:DLMK0146,b:DLMK0144",
150
+ "fields": "f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18,f19,f20,f21,f23,f24,"
151
+ "f25,f26,f22,f33,f11,f62,f128,f136,f115,f152",
152
+ "_": "1639974456250",
153
+ }
154
+ try:
155
+ if proxies is None:
156
+ r = requests.get(url, params=params, timeout=time_out, headers=headers)
157
+ else:
158
+ r = requests.get(url, params=params, proxies=proxies, timeout=time_out, headers=headers)
159
+
160
+ data_json = r.json()
161
+ temp_df = pd.DataFrame(data_json["data"]["diff"]).T
162
+ temp_df.reset_index(inplace=True)
163
+ temp_df["index"] = temp_df.index + 1
164
+ return temp_df
165
+ except Exception as e:
166
+ logger.error("获取港股通列表:{}", e)
167
+
168
+
169
+ def repeated_acquisition_ask_hk_gtt_async(em_cookie, time_out, max_number, num_threads, pages_per_thread):
170
+ per_page = page_number
171
+ total_pages = (max_number + per_page - 1) // per_page # 向上取整
172
+ result_df = pd.DataFrame()
173
+
174
+ # 创建线程锁以确保线程安全
175
+ df_lock = Lock()
176
+
177
+ # 计算每个线程处理的页数范围
178
+ def process_page_range(start_page, end_page, thread_id):
179
+ nonlocal result_df
180
+ local_df = pd.DataFrame()
181
+ current_page = start_page
182
+ proxy_ip = proxy_common_api.generate_proxy_ip_api(1)
183
+
184
+ while current_page <= end_page and current_page <= total_pages:
185
+ proxies = {"https": proxy_ip, "http": proxy_ip}
186
+ try:
187
+ page_df = stock_hk_ggt_components_em(em_cookie, current_page, proxies, page_number, time_out)
188
+ if data_frame_util.is_not_empty(page_df):
189
+ local_df = pd.concat([local_df, page_df])
190
+ logger.info("线程{}获取页面数据成功: {}", thread_id, current_page)
191
+ current_page += 1
192
+ else:
193
+ time.sleep(0.2)
194
+ proxy_ip = proxy_common_api.generate_proxy_ip_api(1)
195
+ logger.info("线程{}获取页面数据失败: {}", thread_id, current_page)
196
+ except BaseException as e:
197
+ time.sleep(1)
198
+ proxy_ip = proxy_common_api.generate_proxy_ip_api(1)
199
+ logger.error("线程{}处理页面{}时发生错误: {}", thread_id, current_page, e)
200
+
201
+ with df_lock:
202
+ result_df = pd.concat([result_df, local_df])
203
+ return len(local_df)
204
+
205
+ # 计算每个线程的页面范围
206
+ page_ranges = []
207
+ for i in range(num_threads):
208
+ start_page = i * pages_per_thread + 1
209
+ end_page = (i + 1) * pages_per_thread
210
+ if start_page > total_pages:
211
+ break
212
+ page_ranges.append((start_page, end_page, i + 1))
213
+
214
+ # 使用线程池执行任务
215
+ with concurrent.futures.ThreadPoolExecutor(max_workers=num_threads) as executor:
216
+ # 提交所有任务
217
+ futures = [
218
+ executor.submit(process_page_range, start, end, tid)
219
+ for start, end, tid in page_ranges
220
+ ]
221
+
222
+ # 等待所有任务完成并获取结果
223
+ results = []
224
+ for future in concurrent.futures.as_completed(futures):
225
+ try:
226
+ result = future.result()
227
+ results.append(result)
228
+ except Exception as e:
229
+ logger.error("线程执行出错: {}", e)
230
+
231
+ return rename_hg_ggt(result_df)
232
+
233
+
234
+ # 港股通实时行情
235
+ def get_ggt_real_time_quotes(em_cookie, time_out, pages_per_thread):
236
+ try_numer = 3
237
+ while try_numer > 0:
238
+ proxy_ip = proxy_common_api.generate_proxy_ip_api(1)
239
+ proxies = {"https": proxy_ip,
240
+ "http": proxy_ip}
241
+
242
+ max_number = get_stock_hk_ggt_components_em_count(em_cookie, 1, proxies, 20, time_out)
243
+ if max_number > 0:
244
+ break
245
+ try_numer = try_numer - 1
246
+ if max_number == 0:
247
+ return pd.DataFrame()
248
+
249
+ total_pages = (max_number + page_number - 1) // page_number # 向上取整
250
+
251
+ num_threads = int((total_pages / pages_per_thread) + 1)
252
+ return repeated_acquisition_ask_hk_gtt_async(em_cookie, time_out, max_number, num_threads, pages_per_thread)
253
+
254
+
255
+ import mns_common.component.cookie.cookie_info_service as cookie_info_service
256
+
257
+ if __name__ == '__main__':
258
+ em_cookie_test = cookie_info_service.get_em_cookie()
259
+ test_df = get_ggt_real_time_quotes(em_cookie_test, 30, 6)
260
+ print(test_df)
@@ -0,0 +1,154 @@
1
+ from mns_common.db.MongodbUtil import MongodbUtil
2
+ import requests
3
+ import json
4
+ import pandas as pd
5
+ from concurrent.futures import ThreadPoolExecutor
6
+ import datetime
7
+ from loguru import logger
8
+ import mns_common.component.proxies.proxy_common_api as proxy_common_api
9
+ import mns_common.api.em.real_time.east_money_stock_common_api as east_money_stock_common_api
10
+
11
+ mongodb_util = MongodbUtil('27017')
12
+
13
+ fields = ("f352,f2,f3,f5,f6,f8,f10,f11,f22,f12,f14,f15,f16,f17,"
14
+ "f18,f20,f21,f26,f33,f34,f35,f62,f66,f69,f72,f100,f184,f211,f212"),
15
+ fs = "m:0 t:6,m:0 t:80,m:1 t:2,m:1 t:23,m:0 t:81 s:2048"
16
+
17
+ # 分页条数
18
+ PAGE_SIZE = 100
19
+
20
+
21
+ def all_stock_ticker_data_new(initial_proxies, time_out, max_number) -> pd.DataFrame:
22
+ """
23
+ 使用多线程获取所有股票数据,失败页面会使用新IP重试,最多使用10个IP
24
+ """
25
+
26
+ total_pages = (max_number + PAGE_SIZE - 1) // PAGE_SIZE # 向上取整
27
+ all_pages = set(range(1, total_pages + 1)) # 所有需要获取的页码
28
+ success_pages = set() # 成功获取的页码
29
+ results = [] # 存储成功获取的数据
30
+ used_ip_count = 1 # 已使用IP计数器(初始IP算第一个)
31
+ MAX_IP_LIMIT = 10 # IP使用上限
32
+
33
+ # 循环处理直到所有页面成功或达到IP上限
34
+ while (all_pages - success_pages) and (used_ip_count < MAX_IP_LIMIT):
35
+ # 获取当前需要处理的失败页码
36
+ current_failed_pages = all_pages - success_pages
37
+ if used_ip_count > 1:
38
+ logger.info("当前需要处理的失败页码: {}, 已使用IP数量: {}/{}", current_failed_pages, used_ip_count,
39
+ MAX_IP_LIMIT)
40
+
41
+ # 首次使用初始代理,后续获取新代理
42
+ if len(success_pages) == 0:
43
+ proxies = initial_proxies
44
+ else:
45
+ # 每次重试前获取新代理并计数
46
+ # logger.info("获取新代理IP处理失败页面")
47
+ new_proxy_ip = proxy_common_api.generate_proxy_ip_api(1)
48
+ proxies = {"https": new_proxy_ip}
49
+ # logger.info("新代理IP: {}, 已使用IP数量: {}/{}", new_proxy_ip, used_ip_count + 1, MAX_IP_LIMIT)
50
+ used_ip_count += 1 # 增加IP计数器
51
+
52
+ # 创建线程池处理当前失败的页码
53
+ with ThreadPoolExecutor(max_workers=10) as executor:
54
+ futures = {
55
+ executor.submit(get_stock_page_data, pn, proxies, PAGE_SIZE, time_out): pn
56
+ for pn in current_failed_pages
57
+ }
58
+
59
+ # 收集结果并记录成功页码
60
+ for future, pn in futures.items():
61
+ try:
62
+ result = future.result()
63
+ if not result.empty:
64
+ results.append(result)
65
+ success_pages.add(pn)
66
+ # else:
67
+ # logger.warning("页码 {} 未返回有效数据", pn)
68
+ except Exception as e:
69
+ continue
70
+ # logger.error("页码 {} 处理异常: {}", pn, str(e))
71
+
72
+ # 检查是否达到IP上限
73
+ if used_ip_count >= MAX_IP_LIMIT and (all_pages - success_pages):
74
+ remaining_pages = all_pages - success_pages
75
+ logger.warning("已达到最大IP使用限制({}个),剩余未获取页码: {}, 返回现有数据", MAX_IP_LIMIT, remaining_pages)
76
+
77
+ # 合并所有成功获取的数据
78
+ if results:
79
+ return pd.concat(results, ignore_index=True)
80
+ else:
81
+ return pd.DataFrame()
82
+
83
+
84
+ def get_stock_page_data(pn, proxies, page_size, time_out):
85
+ """获取单页股票数据"""
86
+ current_time = datetime.datetime.now()
87
+ current_timestamp_ms = int(current_time.timestamp() * 1000)
88
+
89
+ url = "https://33.push2.eastmoney.com/api/qt/clist/get"
90
+ params = {
91
+ "cb": "jQuery1124046660442520420653_" + str(current_timestamp_ms),
92
+ "pn": str(pn),
93
+ "pz": str(page_size),
94
+ "po": "0",
95
+ "np": "3",
96
+ "ut": "bd1d9ddb04089700cf9c27f6f7426281",
97
+ "fltt": "2",
98
+ "invt": "2",
99
+ "wbp2u": "|0|0|0|web",
100
+ "fid": "f12",
101
+ "fs": fs,
102
+ "fields": fields,
103
+ "_": current_timestamp_ms
104
+ }
105
+
106
+ try:
107
+ if proxies is None:
108
+ r = requests.get(url, params, timeout=time_out)
109
+ else:
110
+ r = requests.get(url, params, proxies=proxies, timeout=time_out)
111
+
112
+ if r.status_code != 200:
113
+ return pd.DataFrame()
114
+
115
+ data_text = r.text
116
+ begin_index = data_text.index('[')
117
+ end_index = data_text.index(']')
118
+ data_json = data_text[begin_index:end_index + 1]
119
+ data_json = json.loads(data_json)
120
+
121
+ if not data_json:
122
+ return pd.DataFrame()
123
+
124
+ result_df = pd.DataFrame(data_json)
125
+ result_df['page_number'] = pn
126
+ return result_df
127
+ except Exception as e:
128
+ return pd.DataFrame()
129
+
130
+
131
+ def get_real_time_quotes_all_stocks(time_out):
132
+ try_numer = 3
133
+ while try_numer > 0:
134
+ proxy_ip = proxy_common_api.generate_proxy_ip_api(1)
135
+ initial_proxies = {"https": proxy_ip,
136
+ "http": proxy_ip}
137
+
138
+ total_number = east_money_stock_common_api.get_stocks_num(1, initial_proxies, 20, time_out)
139
+ if total_number > 0:
140
+ break
141
+ try_numer = try_numer - 1
142
+ if total_number == 0:
143
+ return pd.DataFrame()
144
+
145
+ page_df = all_stock_ticker_data_new(initial_proxies, time_out, total_number)
146
+ page_df = east_money_stock_common_api.rename_real_time_quotes_df(page_df)
147
+ page_df.drop_duplicates('symbol', keep='last', inplace=True)
148
+ return page_df
149
+
150
+
151
+ if __name__ == '__main__':
152
+ # 调用方式
153
+ df = get_real_time_quotes_all_stocks(5)
154
+ logger.info("数据条数,{}", df.shape[0])