mns-common 1.5.1.7__py3-none-any.whl → 1.5.1.9__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.
Potentially problematic release.
This version of mns-common might be problematic. Click here for more details.
- mns_common/api/{akshare → em/real_time/real_time}/__init__.py +1 -1
- mns_common/api/em/real_time/{east_money_debt_api.py → real_time/east_money_debt_api.py} +135 -19
- mns_common/api/em/real_time/{east_money_etf_api.py → real_time/east_money_etf_api.py} +140 -10
- mns_common/api/em/real_time/{east_money_stock_a_api.py → real_time/east_money_stock_a_api.py} +18 -16
- mns_common/api/em/real_time/{east_money_stock_hk_api.py → real_time/east_money_stock_hk_api.py} +234 -102
- mns_common/api/em/real_time/{real_time_quotes_repeat_api.py → real_time/real_time_quotes_repeat_api.py} +0 -4
- {mns_common-1.5.1.7.dist-info → mns_common-1.5.1.9.dist-info}/METADATA +1 -1
- {mns_common-1.5.1.7.dist-info → mns_common-1.5.1.9.dist-info}/RECORD +16 -22
- mns_common/api/akshare/k_line_api.py +0 -123
- mns_common/api/akshare/stock_bid_ask_api.py +0 -94
- mns_common/api/akshare/stock_dt_pool.py +0 -47
- mns_common/api/akshare/stock_zb_pool.py +0 -48
- mns_common/api/akshare/stock_zt_pool_api.py +0 -47
- mns_common/api/akshare/yjyg_sync_api.py +0 -98
- /mns_common/api/em/{concept → real_time/concept}/__init__.py +0 -0
- /mns_common/api/em/{concept → real_time/concept}/em_concept_index_api.py +0 -0
- /mns_common/api/em/{gd → real_time/gd}/__init__.py +0 -0
- /mns_common/api/em/{gd → real_time/gd}/east_money_stock_gdfx_free_top_10_api.py +0 -0
- /mns_common/api/em/real_time/{east_money_stock_a_v2_api.py → real_time/east_money_stock_a_v2_api.py} +0 -0
- /mns_common/api/em/real_time/{east_money_stock_us_api.py → real_time/east_money_stock_us_api.py} +0 -0
- {mns_common-1.5.1.7.dist-info → mns_common-1.5.1.9.dist-info}/WHEEL +0 -0
- {mns_common-1.5.1.7.dist-info → mns_common-1.5.1.9.dist-info}/top_level.txt +0 -0
|
@@ -8,14 +8,19 @@ file_path = os.path.abspath(__file__)
|
|
|
8
8
|
end = file_path.index('mns') + 14
|
|
9
9
|
project_path = file_path[0:end]
|
|
10
10
|
sys.path.append(project_path)
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
import akshare as ak
|
|
12
14
|
import pandas as pd
|
|
13
15
|
from loguru import logger
|
|
14
|
-
import json
|
|
15
16
|
import requests
|
|
16
17
|
import time
|
|
17
|
-
import akshare as ak
|
|
18
18
|
import numpy as np
|
|
19
|
+
import mns_common.component.proxies.proxy_common_api as proxy_common_api
|
|
20
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
21
|
+
from threading import Lock
|
|
22
|
+
import concurrent.futures
|
|
23
|
+
import mns_common.utils.data_frame_util as data_frame_util
|
|
19
24
|
|
|
20
25
|
# 最大返回条数
|
|
21
26
|
max_number = 600
|
|
@@ -24,19 +29,49 @@ min_number = 500
|
|
|
24
29
|
# 分页条数
|
|
25
30
|
page_number = 100
|
|
26
31
|
|
|
32
|
+
fields = ("f352,f2,f3,f5,f6,f8,f10,f11,f22,f12,f14,f15,f16,f17,f18,f20,f21,f26,f33,f34,f35,f62,f66,f69,f72,f184,"
|
|
33
|
+
"f211,f212,f232,f233,f234")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def get_kzz_count(pn, proxies, page_size, time_out):
|
|
37
|
+
current_timestamp = str(int(round(time.time() * 1000, 0)))
|
|
38
|
+
url = "https://push2.eastmoney.com/api/qt/clist/get"
|
|
39
|
+
|
|
40
|
+
params = {
|
|
41
|
+
"cb": "jQuery34103608466964799838_" + current_timestamp,
|
|
42
|
+
"pn": str(pn),
|
|
43
|
+
"np": 3,
|
|
44
|
+
"ut": "8a086bfc3570bdde64a6a1c585cccb35",
|
|
45
|
+
"fltt": 1,
|
|
46
|
+
"invt": 1,
|
|
47
|
+
"fs": "m:0+e:11,m:1+e:11,m:1+e:11+s:4194304,m:0+e:11+s:8388608",
|
|
48
|
+
"dpt": "zqsc.zpg",
|
|
49
|
+
"fields": fields,
|
|
50
|
+
"wbp2u": "|0|0|0|wap",
|
|
51
|
+
"fid": "f12",
|
|
52
|
+
"po": 1,
|
|
53
|
+
"pz": str(page_size),
|
|
54
|
+
"_": current_timestamp
|
|
55
|
+
}
|
|
56
|
+
try:
|
|
57
|
+
if proxies is None:
|
|
58
|
+
r = requests.get(url, params, timeout=time_out)
|
|
59
|
+
else:
|
|
60
|
+
r = requests.get(url, params, proxies=proxies, timeout=time_out)
|
|
61
|
+
data_text = r.text
|
|
62
|
+
total_number = int(data_json['data']['total'])
|
|
63
|
+
return total_number
|
|
64
|
+
except Exception as e:
|
|
65
|
+
logger.error("获取可转债列表,实时行情异常:{}", e)
|
|
66
|
+
return 0
|
|
27
67
|
|
|
28
|
-
# fields_02 = "f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18,f19,f20,f21,f22,f23,f24,f25,f26,f27,f28,f29,f30,f31,f32,f33,f34,f35,f36,f37,f38,f39,f40,f41,f42,f43,f44,f45,f46,f47,f48,f49,f50,f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61,f62,f63,f64,f65,f66,f67,f68,f69,f70,f71,f72,f73,f74,f75,f76,f77,f78,f79,f80,f81,f82,f83,f84,f85,f86,f87,f88,f89,f90,f91,f92,f93,f94,f95,f96,f97,f98,f99,f100,f101,f102,f103,f104,f105,f106,f107,f108" \
|
|
29
|
-
# ",f109,f110,f111,f112,f113,f114,f115,f116,f117,f118,f119,f120,f121,f122,f123,f124,f125,f126,f127,f128,f129,f130,f131,f132,f133,f134,f135,f136,f137,f138,f139,f140,f141,f142,f143,f144,f145,f146,f147,f148,f149,f150,f151,f152,f153,f154,f155,f156,f157,f158,f159,f160,f161,f162,f163,f164,f165,f166,f167,f168,f169,f170,f171,f172,f173,f174,f175,f176,f177,f178,f179,f180,f181,f182,f183,f184,f185,f186,f187,f188,f189,f190,f191,f192,f193,f194,f195,f196,f197,f198,f199,f200" \
|
|
30
|
-
# ",f209,f210,f211,f212,f213,f214,f215,f216,f217,f218,f219,f220,f221,f222,f223,f224,f225,f226,f227,f228,f229,f230,f231,f232,f233,f234,f235,f236,f237,f238,f239,f240,f241,f242,f243,f244,f245,f246,f247,f248,f249,f250,f251,f252,f253,f254,f255,f256,f257,f258,f259,f260,f261,f262,f263,f264,f265,f266,f267,f268,f269,f270,f271,f272,f273,f274,f275,f276,f277,f278,f279,f280,f281,f282,f283,f284,f285,f286,f287,f288,f289,f290,f291,f292,f293,f294,f295,f296,f297,f298,f299,f300" \
|
|
31
|
-
# ",f309,f310,f312,f313,f314,f315,f316,f317,f318,f319,f320,f321,f322,f323,f324,f325,f326,f327,f328,f329,f330,f331,f332,f333,f334,f335,f336,f337,f338,f339,f340,f341,f342,f343,f344,f345,f346,f347,f348,f349,f350,f351,f352,f353,f354,f355,f356,f357,f358,f359,f360,f361,f362,f363,f364,f365,f366,f367,f368,f369,f370,f371,f372,f373,f374,f375,f376,f377,f378,f379,f380,f381,f382,f383,f384,f385,f386,f387,f388,f389,f390,f391,f392,f393,f394,f395,f396,f397,f398,f399,f401"
|
|
32
|
-
#
|
|
33
68
|
|
|
34
69
|
#
|
|
35
70
|
# url = https://push2.eastmoney.com/api/qt/clist/get?cb=jQuery34103608466964799838_1718163189869&pn=1&np=1&ut
|
|
36
71
|
# =8a086bfc3570bdde64a6a1c585cccb35&fltt=1&invt=1&fs=m:0+e:11,m:1+e:11,m:1+e:11+s:4194304,
|
|
37
72
|
# m:0+e:11+s:8388608&dpt=zqsc.zpg&fields=f1,f2,f3,f4,f5,f6,f8,f10,f12,f13,f14,f18,f22,f152,
|
|
38
73
|
# f237&wbp2u=|0|0|0|wap&fid=f3&po=1&pz=2000&_=1718163189870
|
|
39
|
-
def get_debt_page_data(
|
|
74
|
+
def get_debt_page_data(pn, proxies, page_size, time_out) -> pd.DataFrame:
|
|
40
75
|
current_timestamp = str(int(round(time.time() * 1000, 0)))
|
|
41
76
|
url = "https://push2.eastmoney.com/api/qt/clist/get"
|
|
42
77
|
|
|
@@ -53,14 +88,14 @@ def get_debt_page_data(fields, pn, proxies) -> pd.DataFrame:
|
|
|
53
88
|
"wbp2u": "|0|0|0|wap",
|
|
54
89
|
"fid": "f12",
|
|
55
90
|
"po": 1,
|
|
56
|
-
"pz":
|
|
91
|
+
"pz": str(page_size),
|
|
57
92
|
"_": current_timestamp
|
|
58
93
|
}
|
|
59
94
|
try:
|
|
60
95
|
if proxies is None:
|
|
61
|
-
r = requests.get(url, params)
|
|
96
|
+
r = requests.get(url, params, timeout=time_out)
|
|
62
97
|
else:
|
|
63
|
-
r = requests.get(url, params, proxies=proxies)
|
|
98
|
+
r = requests.get(url, params, proxies=proxies, timeout=time_out)
|
|
64
99
|
data_text = r.text
|
|
65
100
|
|
|
66
101
|
if pn == 1:
|
|
@@ -117,8 +152,6 @@ def all_debt_ticker_data(fields, proxies) -> pd.DataFrame:
|
|
|
117
152
|
|
|
118
153
|
|
|
119
154
|
def get_debt_real_time_quotes(proxies):
|
|
120
|
-
fields = ("f352,f2,f3,f5,f6,f8,f10,f11,f22,f12,f14,f15,f16,f17,f18,f20,f21,f26,f33,f34,f35,f62,f66,f69,f72,f184,"
|
|
121
|
-
"f211,f212,f232,f233,f234")
|
|
122
155
|
# 获取第一页数据
|
|
123
156
|
page_one_df = get_debt_page_data(fields, 1, proxies)
|
|
124
157
|
# 数据接口正常返回5600以上的数量
|
|
@@ -298,9 +331,92 @@ def get_kzz_bond_info():
|
|
|
298
331
|
logger.error("获取可转债信息异常:{}", e)
|
|
299
332
|
|
|
300
333
|
|
|
334
|
+
def repeated_acquisition_ask_etf_async(time_out, max_number, num_threads, pages_per_thread):
|
|
335
|
+
per_page = page_number
|
|
336
|
+
total_pages = (max_number + per_page - 1) // per_page # 向上取整
|
|
337
|
+
result_df = pd.DataFrame()
|
|
338
|
+
|
|
339
|
+
# 创建线程锁以确保线程安全
|
|
340
|
+
df_lock = Lock()
|
|
341
|
+
|
|
342
|
+
# 计算每个线程处理的页数范围
|
|
343
|
+
def process_page_range(start_page, end_page, thread_id):
|
|
344
|
+
nonlocal result_df
|
|
345
|
+
local_df = pd.DataFrame()
|
|
346
|
+
current_page = start_page
|
|
347
|
+
proxy_ip = proxy_common_api.generate_proxy_ip_api(1)
|
|
348
|
+
|
|
349
|
+
while current_page <= end_page and current_page <= total_pages:
|
|
350
|
+
proxies = {"https": proxy_ip, "http": proxy_ip}
|
|
351
|
+
try:
|
|
352
|
+
page_df = get_debt_page_data(current_page, proxies, page_number, time_out)
|
|
353
|
+
if data_frame_util.is_not_empty(page_df):
|
|
354
|
+
local_df = pd.concat([local_df, page_df])
|
|
355
|
+
logger.info("线程{}获取页面数据成功: {}", thread_id, current_page)
|
|
356
|
+
current_page += 1
|
|
357
|
+
else:
|
|
358
|
+
time.sleep(0.2)
|
|
359
|
+
proxy_ip = proxy_common_api.generate_proxy_ip_api(1)
|
|
360
|
+
logger.info("线程{}获取页面数据失败: {}", thread_id, current_page)
|
|
361
|
+
except BaseException as e:
|
|
362
|
+
time.sleep(1)
|
|
363
|
+
proxy_ip = proxy_common_api.generate_proxy_ip_api(1)
|
|
364
|
+
logger.error("线程{}处理页面{}时发生错误: {}", thread_id, current_page, e)
|
|
365
|
+
|
|
366
|
+
with df_lock:
|
|
367
|
+
result_df = pd.concat([result_df, local_df])
|
|
368
|
+
return len(local_df)
|
|
369
|
+
|
|
370
|
+
# 计算每个线程的页面范围
|
|
371
|
+
page_ranges = []
|
|
372
|
+
for i in range(num_threads):
|
|
373
|
+
start_page = i * pages_per_thread + 1
|
|
374
|
+
end_page = (i + 1) * pages_per_thread
|
|
375
|
+
if start_page > total_pages:
|
|
376
|
+
break
|
|
377
|
+
page_ranges.append((start_page, end_page, i + 1))
|
|
378
|
+
|
|
379
|
+
# 使用线程池执行任务
|
|
380
|
+
with concurrent.futures.ThreadPoolExecutor(max_workers=num_threads) as executor:
|
|
381
|
+
# 提交所有任务
|
|
382
|
+
futures = [
|
|
383
|
+
executor.submit(process_page_range, start, end, tid)
|
|
384
|
+
for start, end, tid in page_ranges
|
|
385
|
+
]
|
|
386
|
+
|
|
387
|
+
# 等待所有任务完成并获取结果
|
|
388
|
+
results = []
|
|
389
|
+
for future in concurrent.futures.as_completed(futures):
|
|
390
|
+
try:
|
|
391
|
+
result = future.result()
|
|
392
|
+
results.append(result)
|
|
393
|
+
except Exception as e:
|
|
394
|
+
logger.error("线程执行出错: {}", e)
|
|
395
|
+
|
|
396
|
+
return rename_real_time_quotes_df(result_df)
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
def get_kzz_real_time_quotes(time_out, pages_per_thread):
|
|
400
|
+
try_numer = 3
|
|
401
|
+
while try_numer > 0:
|
|
402
|
+
proxy_ip = proxy_common_api.generate_proxy_ip_api(1)
|
|
403
|
+
proxies = {"https": proxy_ip,
|
|
404
|
+
"http": proxy_ip}
|
|
405
|
+
|
|
406
|
+
max_number = get_kzz_count(1, proxies, 20, time_out)
|
|
407
|
+
if max_number > 0:
|
|
408
|
+
break
|
|
409
|
+
try_numer = try_numer - 1
|
|
410
|
+
if max_number == 0:
|
|
411
|
+
return pd.DataFrame()
|
|
412
|
+
|
|
413
|
+
total_pages = (max_number + page_number - 1) // page_number # 向上取整
|
|
414
|
+
|
|
415
|
+
num_threads = int((total_pages / pages_per_thread) + 1)
|
|
416
|
+
return repeated_acquisition_ask_etf_async(time_out, max_number, num_threads, pages_per_thread)
|
|
417
|
+
|
|
418
|
+
|
|
301
419
|
if __name__ == '__main__':
|
|
302
|
-
|
|
303
|
-
print(
|
|
304
|
-
|
|
305
|
-
df = get_debt_real_time_quotes(None)
|
|
306
|
-
logger.info(df)
|
|
420
|
+
test_df = get_kzz_real_time_quotes(30, 6)
|
|
421
|
+
print(test_df)
|
|
422
|
+
|
|
@@ -6,12 +6,16 @@ end = file_path.index('mns') + 16
|
|
|
6
6
|
project_path = file_path[0:end]
|
|
7
7
|
sys.path.append(project_path)
|
|
8
8
|
|
|
9
|
-
from concurrent.futures import ThreadPoolExecutor
|
|
10
9
|
import pandas as pd
|
|
11
10
|
from loguru import logger
|
|
12
11
|
import requests
|
|
13
12
|
import time
|
|
14
13
|
import numpy as np
|
|
14
|
+
import mns_common.component.proxies.proxy_common_api as proxy_common_api
|
|
15
|
+
import concurrent.futures
|
|
16
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
17
|
+
from threading import Lock
|
|
18
|
+
import mns_common.utils.data_frame_util as data_frame_util
|
|
15
19
|
|
|
16
20
|
# 最大返回条数
|
|
17
21
|
max_number = 1200
|
|
@@ -21,7 +25,7 @@ min_number = 1000
|
|
|
21
25
|
page_number = 100
|
|
22
26
|
|
|
23
27
|
|
|
24
|
-
def
|
|
28
|
+
def get_etf_count(pn, proxies, page_size, time_out):
|
|
25
29
|
"""
|
|
26
30
|
东方财富-ETF 实时行情
|
|
27
31
|
https://quote.eastmoney.com/center/gridlist.html#fund_etf
|
|
@@ -32,7 +36,7 @@ def get_fund_etf_page_df(pn, proxies) -> pd.DataFrame:
|
|
|
32
36
|
url = "https://88.push2.eastmoney.com/api/qt/clist/get"
|
|
33
37
|
params = {
|
|
34
38
|
"pn": str(pn),
|
|
35
|
-
"pz":
|
|
39
|
+
"pz": str(page_size),
|
|
36
40
|
"po": "1",
|
|
37
41
|
"np": "3",
|
|
38
42
|
"ut": "bd1d9ddb04089700cf9c27f6f7426281",
|
|
@@ -53,16 +57,59 @@ def get_fund_etf_page_df(pn, proxies) -> pd.DataFrame:
|
|
|
53
57
|
}
|
|
54
58
|
try:
|
|
55
59
|
if proxies is None:
|
|
56
|
-
r = requests.get(url, params)
|
|
60
|
+
r = requests.get(url, params, timeout=time_out)
|
|
57
61
|
else:
|
|
58
|
-
r = requests.get(url, params, proxies=proxies)
|
|
62
|
+
r = requests.get(url, params, proxies=proxies, timeout=time_out)
|
|
63
|
+
data_json = r.json()
|
|
64
|
+
total_number = int(data_json['data']['total'])
|
|
65
|
+
return total_number
|
|
66
|
+
except Exception as e:
|
|
67
|
+
logger.error("获取ETF列表,实时行情异常:{}", e)
|
|
68
|
+
return pd.DataFrame()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def get_fund_etf_page_df(pn, proxies, page_size, time_out) -> pd.DataFrame:
|
|
72
|
+
"""
|
|
73
|
+
东方财富-ETF 实时行情
|
|
74
|
+
https://quote.eastmoney.com/center/gridlist.html#fund_etf
|
|
75
|
+
:return: ETF 实时行情
|
|
76
|
+
:rtype: pandas.DataFrame
|
|
77
|
+
"""
|
|
78
|
+
current_timestamp = str(int(round(time.time() * 1000, 0)))
|
|
79
|
+
url = "https://88.push2.eastmoney.com/api/qt/clist/get"
|
|
80
|
+
params = {
|
|
81
|
+
"pn": str(pn),
|
|
82
|
+
"pz": str(page_size),
|
|
83
|
+
"po": "1",
|
|
84
|
+
"np": "3",
|
|
85
|
+
"ut": "bd1d9ddb04089700cf9c27f6f7426281",
|
|
86
|
+
"fltt": "2",
|
|
87
|
+
"invt": "2",
|
|
88
|
+
"wbp2u": "|0|0|0|web",
|
|
89
|
+
"fid": "f12",
|
|
90
|
+
"fs": "b:MK0021,b:MK0022,b:MK0023,b:MK0024",
|
|
91
|
+
"fields": (
|
|
92
|
+
"f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,"
|
|
93
|
+
"f12,f13,f14,f15,f16,f17,f18,f20,f21,"
|
|
94
|
+
"f23,f24,f25,f26,f22,f11,f30,f31,f32,f33,"
|
|
95
|
+
"f34,f35,f38,f62,f63,f64,f65,f66,f69,"
|
|
96
|
+
"f72,f75,f78,f81,f84,f87,f115,f124,f128,"
|
|
97
|
+
"f136,f152,f184,f297,f402,f441"
|
|
98
|
+
),
|
|
99
|
+
"_": str(current_timestamp),
|
|
100
|
+
}
|
|
101
|
+
try:
|
|
102
|
+
if proxies is None:
|
|
103
|
+
r = requests.get(url, params, timeout=time_out)
|
|
104
|
+
else:
|
|
105
|
+
r = requests.get(url, params, proxies=proxies, timeout=time_out)
|
|
59
106
|
data_json = r.json()
|
|
60
107
|
if pn == 1:
|
|
61
108
|
try:
|
|
62
109
|
global max_number
|
|
63
110
|
max_number = int(data_json['data']['total'])
|
|
64
111
|
except Exception as e:
|
|
65
|
-
logger.error(
|
|
112
|
+
logger.error("获取第{}页ETF列表异常:{}", page_size, str(e))
|
|
66
113
|
return pd.DataFrame()
|
|
67
114
|
|
|
68
115
|
temp_df = pd.DataFrame(data_json["data"]["diff"])
|
|
@@ -367,8 +414,91 @@ def get_etf_real_time_quotes(proxies):
|
|
|
367
414
|
return page_df
|
|
368
415
|
|
|
369
416
|
|
|
417
|
+
def repeated_acquisition_ask_etf_async(time_out, max_number, num_threads, pages_per_thread):
|
|
418
|
+
per_page = page_number
|
|
419
|
+
total_pages = (max_number + per_page - 1) // per_page # 向上取整
|
|
420
|
+
result_df = pd.DataFrame()
|
|
421
|
+
|
|
422
|
+
# 创建线程锁以确保线程安全
|
|
423
|
+
df_lock = Lock()
|
|
424
|
+
|
|
425
|
+
# 计算每个线程处理的页数范围
|
|
426
|
+
def process_page_range(start_page, end_page, thread_id):
|
|
427
|
+
nonlocal result_df
|
|
428
|
+
local_df = pd.DataFrame()
|
|
429
|
+
current_page = start_page
|
|
430
|
+
proxy_ip = proxy_common_api.generate_proxy_ip_api(1)
|
|
431
|
+
|
|
432
|
+
while current_page <= end_page and current_page <= total_pages:
|
|
433
|
+
proxies = {"https": proxy_ip, "http": proxy_ip}
|
|
434
|
+
try:
|
|
435
|
+
page_df = get_fund_etf_page_df(current_page, proxies, page_number, time_out)
|
|
436
|
+
if data_frame_util.is_not_empty(page_df):
|
|
437
|
+
local_df = pd.concat([local_df, page_df])
|
|
438
|
+
logger.info("线程{}获取页面数据成功: {}", thread_id, current_page)
|
|
439
|
+
current_page += 1
|
|
440
|
+
else:
|
|
441
|
+
time.sleep(0.2)
|
|
442
|
+
proxy_ip = proxy_common_api.generate_proxy_ip_api(1)
|
|
443
|
+
logger.info("线程{}获取页面数据失败: {}", thread_id, current_page)
|
|
444
|
+
except BaseException as e:
|
|
445
|
+
time.sleep(1)
|
|
446
|
+
proxy_ip = proxy_common_api.generate_proxy_ip_api(1)
|
|
447
|
+
logger.error("线程{}处理页面{}时发生错误: {}", thread_id, current_page, e)
|
|
448
|
+
|
|
449
|
+
with df_lock:
|
|
450
|
+
result_df = pd.concat([result_df, local_df])
|
|
451
|
+
return len(local_df)
|
|
452
|
+
|
|
453
|
+
# 计算每个线程的页面范围
|
|
454
|
+
page_ranges = []
|
|
455
|
+
for i in range(num_threads):
|
|
456
|
+
start_page = i * pages_per_thread + 1
|
|
457
|
+
end_page = (i + 1) * pages_per_thread
|
|
458
|
+
if start_page > total_pages:
|
|
459
|
+
break
|
|
460
|
+
page_ranges.append((start_page, end_page, i + 1))
|
|
461
|
+
|
|
462
|
+
# 使用线程池执行任务
|
|
463
|
+
with concurrent.futures.ThreadPoolExecutor(max_workers=num_threads) as executor:
|
|
464
|
+
# 提交所有任务
|
|
465
|
+
futures = [
|
|
466
|
+
executor.submit(process_page_range, start, end, tid)
|
|
467
|
+
for start, end, tid in page_ranges
|
|
468
|
+
]
|
|
469
|
+
|
|
470
|
+
# 等待所有任务完成并获取结果
|
|
471
|
+
results = []
|
|
472
|
+
for future in concurrent.futures.as_completed(futures):
|
|
473
|
+
try:
|
|
474
|
+
result = future.result()
|
|
475
|
+
results.append(result)
|
|
476
|
+
except Exception as e:
|
|
477
|
+
logger.error("线程执行出错: {}", e)
|
|
478
|
+
|
|
479
|
+
return rename_etf(result_df)
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
def get_etf_real_time_quotes(time_out, pages_per_thread):
|
|
483
|
+
try_numer = 3
|
|
484
|
+
while try_numer > 0:
|
|
485
|
+
proxy_ip = proxy_common_api.generate_proxy_ip_api(1)
|
|
486
|
+
proxies = {"https": proxy_ip,
|
|
487
|
+
"http": proxy_ip}
|
|
488
|
+
|
|
489
|
+
max_number = get_etf_count(1, proxies, 20, time_out)
|
|
490
|
+
if max_number>0:
|
|
491
|
+
break
|
|
492
|
+
try_numer = try_numer - 1
|
|
493
|
+
if max_number == 0:
|
|
494
|
+
return pd.DataFrame()
|
|
495
|
+
|
|
496
|
+
total_pages = (max_number + page_number - 1) // page_number # 向上取整
|
|
497
|
+
|
|
498
|
+
num_threads = int((total_pages / pages_per_thread) + 1)
|
|
499
|
+
return repeated_acquisition_ask_etf_async(time_out, max_number, num_threads, pages_per_thread)
|
|
500
|
+
|
|
501
|
+
|
|
370
502
|
if __name__ == '__main__':
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
fund_etf_df = fund_etf_df.fillna(0)
|
|
374
|
-
print(fund_etf_df)
|
|
503
|
+
test_df = get_etf_real_time_quotes(30, 6)
|
|
504
|
+
print(test_df)
|
mns_common/api/em/real_time/{east_money_stock_a_api.py → real_time/east_money_stock_a_api.py}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import os
|
|
2
1
|
import sys
|
|
3
|
-
|
|
2
|
+
import os
|
|
3
|
+
import time
|
|
4
4
|
|
|
5
5
|
file_path = os.path.abspath(__file__)
|
|
6
6
|
end = file_path.index('mns') + 16
|
|
@@ -12,6 +12,7 @@ import json
|
|
|
12
12
|
import pandas as pd
|
|
13
13
|
from concurrent.futures import ThreadPoolExecutor
|
|
14
14
|
import datetime
|
|
15
|
+
from loguru import logger
|
|
15
16
|
import mns_common.utils.data_frame_util as data_frame_util
|
|
16
17
|
|
|
17
18
|
mongodb_util = MongodbUtil('27017')
|
|
@@ -68,7 +69,7 @@ def get_stock_page_data(pn, proxies, page_size):
|
|
|
68
69
|
global max_number
|
|
69
70
|
max_number = int(data_text[begin_index_total + 8:end_index_total - 1])
|
|
70
71
|
except Exception as e:
|
|
71
|
-
|
|
72
|
+
logger.error(f"获取第{pn}页股票列表异常: {e}")
|
|
72
73
|
return pd.DataFrame()
|
|
73
74
|
|
|
74
75
|
begin_index = data_text.index('[')
|
|
@@ -78,11 +79,9 @@ def get_stock_page_data(pn, proxies, page_size):
|
|
|
78
79
|
if data_json is None:
|
|
79
80
|
return pd.DataFrame()
|
|
80
81
|
else:
|
|
81
|
-
|
|
82
|
-
result_df['page_number'] = pn
|
|
83
|
-
return result_df
|
|
82
|
+
return pd.DataFrame(data_json)
|
|
84
83
|
except Exception as e:
|
|
85
|
-
logger.error("获取第{}页股票列表异常:{}"
|
|
84
|
+
logger.error(f"获取第{pn}页股票列表异常: {e}")
|
|
86
85
|
return pd.DataFrame()
|
|
87
86
|
|
|
88
87
|
|
|
@@ -291,13 +290,16 @@ def get_sum_north_south_net_buy_amt():
|
|
|
291
290
|
return df
|
|
292
291
|
|
|
293
292
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
if __name__ == '__main__':
|
|
297
|
-
|
|
298
|
-
proxy_ip = proxy_common_api.generate_proxy_ip_api(1)
|
|
299
|
-
proxies = {"https": proxy_ip,
|
|
300
|
-
"http": proxy_ip}
|
|
293
|
+
# 示例调用
|
|
294
|
+
if __name__ == "__main__":
|
|
301
295
|
while True:
|
|
302
|
-
|
|
303
|
-
|
|
296
|
+
ip_proxy_pool = mongodb_util.find_all_data('ip_proxy_pool')
|
|
297
|
+
if data_frame_util.is_not_empty(ip_proxy_pool):
|
|
298
|
+
proxy_ip = list(ip_proxy_pool['ip'])[0]
|
|
299
|
+
proxy = {
|
|
300
|
+
"https": proxy_ip}
|
|
301
|
+
df = get_real_time_quotes_all_stocks(proxy)
|
|
302
|
+
logger.info("涨停数据,{}", 1)
|
|
303
|
+
else:
|
|
304
|
+
time.sleep(1)
|
|
305
|
+
logger.error("ip为空")
|