akshare 1.16.16__py3-none-any.whl → 1.16.18__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.
akshare/__init__.py CHANGED
@@ -3025,9 +3025,11 @@ amac_manager_cancelled_info # 中国证券投资基金业协会-信息公示-诚
3025
3025
  1.16.14 fix: fix stock_info_global_cls interface
3026
3026
  1.16.15 fix: fix stock_board_concept_name_em interface
3027
3027
  1.16.16 fix: fix stock_board_concept_spot_em interface
3028
+ 1.16.17 fix: fix stock_research_report_em interface
3029
+ 1.16.18 fix: fix stock_board_concept_spot_em interface
3028
3030
  """
3029
3031
 
3030
- __version__ = "1.16.16"
3032
+ __version__ = "1.16.18"
3031
3033
  __author__ = "AKFamily"
3032
3034
 
3033
3035
  import sys
@@ -4276,6 +4278,16 @@ from akshare.stock_feature.stock_report_em import (
4276
4278
  """
4277
4279
  from akshare.stock_feature.stock_yjbb_em import stock_yjbb_em
4278
4280
 
4281
+ """
4282
+ 同花顺-概念板块
4283
+ """
4284
+ from akshare.stock_feature.stock_board_concept_ths import (
4285
+ stock_board_concept_info_ths,
4286
+ stock_board_concept_summary_ths,
4287
+ stock_board_concept_index_ths,
4288
+ stock_board_concept_name_ths,
4289
+ )
4290
+
4279
4291
  """
4280
4292
  同花顺-行业板块
4281
4293
  """
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env python
2
2
  # -*- coding:utf-8 -*-
3
3
  """
4
- Date: 2025/2/26 17:00
4
+ Date: 2025/2/28 16:30
5
5
  Desc: 东方财富-沪深板块-概念板块
6
6
  https://quote.eastmoney.com/center/boardlist.html#concept_board
7
7
  """
8
8
 
9
+ import re
9
10
  from functools import lru_cache
10
11
 
11
12
  import pandas as pd
@@ -13,7 +14,7 @@ import requests
13
14
 
14
15
 
15
16
  @lru_cache()
16
- def stock_board_concept_name_em() -> pd.DataFrame:
17
+ def __stock_board_concept_name_em() -> pd.DataFrame:
17
18
  """
18
19
  东方财富网-行情中心-沪深京板块-概念板块-名称
19
20
  https://quote.eastmoney.com/center/boardlist.html#concept_board
@@ -97,11 +98,11 @@ def stock_board_concept_name_em() -> pd.DataFrame:
97
98
  return temp_df
98
99
 
99
100
 
100
- def stock_board_concept_spot_em() -> pd.DataFrame:
101
+ def stock_board_concept_name_em() -> pd.DataFrame:
101
102
  """
102
- 东方财富网-行情中心-沪深京板块-概念板块-实时行情
103
+ 东方财富网-行情中心-沪深京板块-概念板块-名称
103
104
  https://quote.eastmoney.com/center/boardlist.html#concept_board
104
- :return: 概念板块-实时行情
105
+ :return: 概念板块-名称
105
106
  :rtype: pandas.DataFrame
106
107
  """
107
108
  url = "https://79.push2.eastmoney.com/api/qt/clist/get"
@@ -181,6 +182,55 @@ def stock_board_concept_spot_em() -> pd.DataFrame:
181
182
  return temp_df
182
183
 
183
184
 
185
+ def stock_board_concept_spot_em(symbol: str = "可燃冰") -> pd.DataFrame:
186
+ """
187
+ 东方财富网-行情中心-沪深京板块-概念板块-实时行情
188
+ https://quote.eastmoney.com/bk/90.BK0818.html
189
+ :return: 概念板块-实时行情
190
+ :rtype: pandas.DataFrame
191
+ """
192
+ url = "https://91.push2.eastmoney.com/api/qt/stock/get"
193
+ field_map = {
194
+ "f43": "最新",
195
+ "f44": "最高",
196
+ "f45": "最低",
197
+ "f46": "开盘",
198
+ "f47": "成交量",
199
+ "f48": "成交额",
200
+ "f170": "涨跌幅",
201
+ "f171": "振幅",
202
+ "f168": "换手率",
203
+ "f169": "涨跌额",
204
+ }
205
+
206
+ if re.match(pattern=r"^BK\d+", string=symbol):
207
+ em_code = symbol
208
+ else:
209
+ industry_listing = __stock_board_concept_name_em()
210
+ em_code = industry_listing.query("板块名称 == @symbol")["板块代码"].values[0]
211
+ params = dict(
212
+ fields=",".join(field_map.keys()),
213
+ mpi="1000",
214
+ invt="2",
215
+ fltt="1",
216
+ secid=f"90.{em_code}",
217
+ ut="fa5fd1943c7b386f172d6893dbfba10b",
218
+ )
219
+ r = requests.get(url, params=params)
220
+ data_dict = r.json()
221
+ result = pd.DataFrame.from_dict(data_dict["data"], orient="index")
222
+ result.rename(field_map, inplace=True)
223
+ result.reset_index(inplace=True)
224
+ result.columns = ["item", "value"]
225
+ result["value"] = pd.to_numeric(result["value"], errors="coerce")
226
+
227
+ # 各项转换成正常单位. 除了成交量与成交额, 原始数据中已是正常单位(元)
228
+ result["value"] = result["value"] * 1e-2
229
+ result.iloc[4, 1] = result.iloc[4, 1] * 1e2
230
+ result.iloc[5, 1] = result.iloc[5, 1] * 1e2
231
+ return result
232
+
233
+
184
234
  def stock_board_concept_hist_em(
185
235
  symbol: str = "绿色电力",
186
236
  period: str = "daily",
@@ -209,7 +259,7 @@ def stock_board_concept_hist_em(
209
259
  "weekly": "102",
210
260
  "monthly": "103",
211
261
  }
212
- stock_board_concept_em_map = stock_board_concept_name_em()
262
+ stock_board_concept_em_map = __stock_board_concept_name_em()
213
263
  stock_board_code = stock_board_concept_em_map[
214
264
  stock_board_concept_em_map["板块名称"] == symbol
215
265
  ]["板块代码"].values[0]
@@ -285,7 +335,7 @@ def stock_board_concept_hist_min_em(
285
335
  :return: 分时历史行情
286
336
  :rtype: pandas.DataFrame
287
337
  """
288
- stock_board_concept_em_map = stock_board_concept_name_em()
338
+ stock_board_concept_em_map = __stock_board_concept_name_em()
289
339
  stock_board_code = stock_board_concept_em_map[
290
340
  stock_board_concept_em_map["板块名称"] == symbol
291
341
  ]["板块代码"].values[0]
@@ -391,7 +441,7 @@ def stock_board_concept_cons_em(symbol: str = "融资融券") -> pd.DataFrame:
391
441
  :return: 板块成份
392
442
  :rtype: pandas.DataFrame
393
443
  """
394
- stock_board_concept_em_map = stock_board_concept_name_em()
444
+ stock_board_concept_em_map = __stock_board_concept_name_em()
395
445
  stock_board_code = stock_board_concept_em_map[
396
446
  stock_board_concept_em_map["板块名称"] == symbol
397
447
  ]["板块代码"].values[0]
@@ -490,7 +540,7 @@ if __name__ == "__main__":
490
540
  stock_board_concept_em_df = stock_board_concept_name_em()
491
541
  print(stock_board_concept_em_df)
492
542
 
493
- stock_board_concept_spot_em_df = stock_board_concept_spot_em()
543
+ stock_board_concept_spot_em_df = stock_board_concept_spot_em(symbol="可燃冰")
494
544
  print(stock_board_concept_spot_em_df)
495
545
 
496
546
  stock_board_concept_hist_em_df = stock_board_concept_hist_em(
@@ -1,17 +1,120 @@
1
1
  #!/usr/bin/env python
2
2
  # -*- coding:utf-8 -*-
3
3
  """
4
- Date: 2024/8/23 17:50
4
+ Date: 2025/2/28 16:30
5
5
  Desc: 东方财富-沪深板块-行业板块
6
6
  https://quote.eastmoney.com/center/boardlist.html#industry_board
7
7
  """
8
8
 
9
9
  import re
10
+ from functools import lru_cache
10
11
 
11
12
  import pandas as pd
12
13
  import requests
13
14
 
14
15
 
16
+ @lru_cache()
17
+ def __stock_board_industry_name_em() -> pd.DataFrame:
18
+ """
19
+ 东方财富网-沪深板块-行业板块-名称
20
+ https://quote.eastmoney.com/center/boardlist.html#industry_board
21
+ :return: 行业板块-名称
22
+ :rtype: pandas.DataFrame
23
+ """
24
+ url = "https://17.push2.eastmoney.com/api/qt/clist/get"
25
+ params = {
26
+ "pn": "1",
27
+ "pz": "50000",
28
+ "po": "1",
29
+ "np": "2",
30
+ "ut": "bd1d9ddb04089700cf9c27f6f7426281",
31
+ "fltt": "2",
32
+ "invt": "2",
33
+ "fid": "f3",
34
+ "fs": "m:90 t:2 f:!50",
35
+ "fields": "f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18,f20,f21,"
36
+ "f23,f24,f25,f26,f22,f33,f11,f62,f128,f136,f115,f152,f124,f107,f104,f105,"
37
+ "f140,f141,f207,f208,f209,f222",
38
+ "_": "1626075887768",
39
+ }
40
+ r = requests.get(url, params=params)
41
+ data_json = r.json()
42
+ temp_df = pd.DataFrame(data_json["data"]["diff"]).T
43
+ temp_df.reset_index(inplace=True)
44
+ temp_df["index"] = temp_df.index + 1
45
+ temp_df.columns = [
46
+ "排名",
47
+ "-",
48
+ "最新价",
49
+ "涨跌幅",
50
+ "涨跌额",
51
+ "-",
52
+ "_",
53
+ "-",
54
+ "换手率",
55
+ "-",
56
+ "-",
57
+ "-",
58
+ "板块代码",
59
+ "-",
60
+ "板块名称",
61
+ "-",
62
+ "-",
63
+ "-",
64
+ "-",
65
+ "总市值",
66
+ "-",
67
+ "-",
68
+ "-",
69
+ "-",
70
+ "-",
71
+ "-",
72
+ "-",
73
+ "-",
74
+ "上涨家数",
75
+ "下跌家数",
76
+ "-",
77
+ "-",
78
+ "-",
79
+ "领涨股票",
80
+ "-",
81
+ "-",
82
+ "领涨股票-涨跌幅",
83
+ "-",
84
+ "-",
85
+ "-",
86
+ "-",
87
+ "-",
88
+ ]
89
+ temp_df = temp_df[
90
+ [
91
+ "排名",
92
+ "板块名称",
93
+ "板块代码",
94
+ "最新价",
95
+ "涨跌额",
96
+ "涨跌幅",
97
+ "总市值",
98
+ "换手率",
99
+ "上涨家数",
100
+ "下跌家数",
101
+ "领涨股票",
102
+ "领涨股票-涨跌幅",
103
+ ]
104
+ ]
105
+ temp_df["最新价"] = pd.to_numeric(temp_df["最新价"], errors="coerce")
106
+ temp_df["涨跌额"] = pd.to_numeric(temp_df["涨跌额"], errors="coerce")
107
+ temp_df["涨跌幅"] = pd.to_numeric(temp_df["涨跌幅"], errors="coerce")
108
+ temp_df["总市值"] = pd.to_numeric(temp_df["总市值"], errors="coerce")
109
+ temp_df["换手率"] = pd.to_numeric(temp_df["换手率"], errors="coerce")
110
+ temp_df["上涨家数"] = pd.to_numeric(temp_df["上涨家数"], errors="coerce")
111
+ temp_df["下跌家数"] = pd.to_numeric(temp_df["下跌家数"], errors="coerce")
112
+ temp_df["领涨股票-涨跌幅"] = pd.to_numeric(
113
+ temp_df["领涨股票-涨跌幅"], errors="coerce"
114
+ )
115
+ return temp_df
116
+
117
+
15
118
  def stock_board_industry_name_em() -> pd.DataFrame:
16
119
  """
17
120
  东方财富网-沪深板块-行业板块-名称
@@ -139,9 +242,8 @@ def stock_board_industry_spot_em(symbol: str = "小金属") -> pd.DataFrame:
139
242
  if re.match(pattern=r"^BK\d+", string=symbol):
140
243
  em_code = symbol
141
244
  else:
142
- industry_listing = stock_board_industry_name_em()
245
+ industry_listing = __stock_board_industry_name_em()
143
246
  em_code = industry_listing.query("板块名称 == @symbol")["板块代码"].values[0]
144
-
145
247
  params = dict(
146
248
  fields=",".join(field_map.keys()),
147
249
  mpi="1000",
@@ -193,7 +295,7 @@ def stock_board_industry_hist_em(
193
295
  "周k": "102",
194
296
  "月k": "103",
195
297
  }
196
- stock_board_concept_em_map = stock_board_industry_name_em()
298
+ stock_board_concept_em_map = __stock_board_industry_name_em()
197
299
  stock_board_code = stock_board_concept_em_map[
198
300
  stock_board_concept_em_map["板块名称"] == symbol
199
301
  ]["板块代码"].values[0]
@@ -269,7 +371,7 @@ def stock_board_industry_hist_min_em(
269
371
  :return: 分时历史行情
270
372
  :rtype: pandas.DataFrame
271
373
  """
272
- stock_board_concept_em_map = stock_board_industry_name_em()
374
+ stock_board_concept_em_map = __stock_board_industry_name_em()
273
375
  stock_board_code = stock_board_concept_em_map[
274
376
  stock_board_concept_em_map["板块名称"] == symbol
275
377
  ]["板块代码"].values[0]
@@ -378,11 +480,11 @@ def stock_board_industry_cons_em(symbol: str = "小金属") -> pd.DataFrame:
378
480
  :return: 板块成份
379
481
  :rtype: pandas.DataFrame
380
482
  """
381
- stock_board_concept_em_map = stock_board_industry_name_em()
483
+ stock_board_concept_em_map = __stock_board_industry_name_em()
382
484
  stock_board_code = stock_board_concept_em_map[
383
485
  stock_board_concept_em_map["板块名称"] == symbol
384
486
  ]["板块代码"].values[0]
385
- url = "http://29.push2.eastmoney.com/api/qt/clist/get"
487
+ url = "https://29.push2.eastmoney.com/api/qt/clist/get"
386
488
  params = {
387
489
  "pn": "1",
388
490
  "pz": "50000",
@@ -0,0 +1,286 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding:utf-8 -*-
3
+ """
4
+ Date: 2025/2/28 13:20
5
+ Desc: 同花顺-板块-概念板块
6
+ https://q.10jqka.com.cn/thshy/
7
+ """
8
+
9
+ from datetime import datetime
10
+ from functools import lru_cache
11
+ from io import StringIO
12
+
13
+ import pandas as pd
14
+ import requests
15
+ from bs4 import BeautifulSoup
16
+ import py_mini_racer
17
+
18
+ from akshare.datasets import get_ths_js
19
+ from akshare.utils import demjson
20
+ from akshare.utils.tqdm import get_tqdm
21
+
22
+
23
+ def _get_file_content_ths(file: str = "ths.js") -> str:
24
+ """
25
+ 获取 JS 文件的内容
26
+ :param file: JS 文件名
27
+ :type file: str
28
+ :return: 文件内容
29
+ :rtype: str
30
+ """
31
+ setting_file_path = get_ths_js(file)
32
+ with open(setting_file_path, encoding="utf-8") as f:
33
+ file_data = f.read()
34
+ return file_data
35
+
36
+
37
+ @lru_cache()
38
+ def _get_stock_board_concept_name_ths() -> dict:
39
+ """
40
+ 获取同花顺概念板块代码和名称字典
41
+ :return: 获取同花顺概念板块代码和名称字典
42
+ :rtype: dict
43
+ """
44
+ js_code = py_mini_racer.MiniRacer()
45
+ js_content = _get_file_content_ths("ths.js")
46
+ js_code.eval(js_content)
47
+ v_code = js_code.call("v")
48
+ headers = {
49
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
50
+ "Chrome/89.0.4389.90 Safari/537.36",
51
+ "Cookie": f"v={v_code}",
52
+ }
53
+ url = "https://q.10jqka.com.cn/gn/detail/code/307822/"
54
+ r = requests.get(url, headers=headers)
55
+ soup = BeautifulSoup(r.text, features="lxml")
56
+ code_list = [
57
+ item["href"].split("/")[-2]
58
+ for item in soup.find(name="div", attrs={"class": "cate_inner"}).find_all("a")
59
+ ]
60
+ name_list = [
61
+ item.text
62
+ for item in soup.find(name="div", attrs={"class": "cate_inner"}).find_all("a")
63
+ ]
64
+ name_code_map = dict(zip(name_list, code_list))
65
+ return name_code_map
66
+
67
+
68
+ def stock_board_concept_name_ths() -> pd.DataFrame:
69
+ """
70
+ 同花顺-板块-概念板块-概念
71
+ http://q.10jqka.com.cn/thshy/
72
+ :return: 所有概念板块的名称和链接
73
+ :rtype: pandas.DataFrame
74
+ """
75
+ code_name_ths_map = _get_stock_board_concept_name_ths()
76
+ temp_df = pd.DataFrame.from_dict(code_name_ths_map, orient="index")
77
+ temp_df.reset_index(inplace=True)
78
+ temp_df.columns = ["name", "code"]
79
+ temp_df = temp_df[
80
+ [
81
+ "name",
82
+ "code",
83
+ ]
84
+ ]
85
+ return temp_df
86
+
87
+
88
+ def stock_board_concept_info_ths(symbol: str = "阿里巴巴概念") -> pd.DataFrame:
89
+ """
90
+ 同花顺-板块-概念板块-板块简介
91
+ http://q.10jqka.com.cn/gn/detail/code/301558/
92
+ :param symbol: 板块简介
93
+ :type symbol: str
94
+ :return: 板块简介
95
+ :rtype: pandas.DataFrame
96
+ """
97
+ stock_board_ths_map_df = stock_board_concept_name_ths()
98
+ symbol_code = stock_board_ths_map_df[stock_board_ths_map_df["name"] == symbol][
99
+ "code"
100
+ ].values[0]
101
+ url = f"http://q.10jqka.com.cn/gn/detail/code/{symbol_code}/"
102
+ headers = {
103
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
104
+ "Chrome/89.0.4389.90 Safari/537.36",
105
+ }
106
+ r = requests.get(url, headers=headers)
107
+ soup = BeautifulSoup(r.text, features="lxml")
108
+ name_list = [
109
+ item.text.strip()
110
+ for item in soup.find(name="div", attrs={"class": "board-infos"}).find_all("dt")
111
+ ]
112
+ value_list = [
113
+ item.text.strip().replace("\n", "/")
114
+ for item in soup.find(name="div", attrs={"class": "board-infos"}).find_all("dd")
115
+ ]
116
+ temp_df = pd.DataFrame([name_list, value_list]).T
117
+ temp_df.columns = ["项目", "值"]
118
+ return temp_df
119
+
120
+
121
+ def stock_board_concept_index_ths(
122
+ symbol: str = "阿里巴巴概念",
123
+ start_date: str = "20200101",
124
+ end_date: str = "20250228",
125
+ ) -> pd.DataFrame:
126
+ """
127
+ 同花顺-板块-概念板块-指数数据
128
+ https://q.10jqka.com.cn/gn/detail/code/301558/
129
+ :param start_date: 开始时间
130
+ :type start_date: str
131
+ :param end_date: 结束时间
132
+ :type end_date: str
133
+ :param symbol: 指数数据
134
+ :type symbol: str
135
+ :return: 指数数据
136
+ :rtype: pandas.DataFrame
137
+ """
138
+ js_code = py_mini_racer.MiniRacer()
139
+ js_content = _get_file_content_ths("ths.js")
140
+ js_code.eval(js_content)
141
+ v_code = js_code.call("v")
142
+
143
+ code_map = _get_stock_board_concept_name_ths()
144
+ symbol_code = code_map[symbol]
145
+ headers = {
146
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
147
+ "Chrome/89.0.4389.90 Safari/537.36",
148
+ }
149
+ url = f"https://q.10jqka.com.cn/gn/detail/code/{symbol_code}"
150
+ r = requests.get(url=url, headers=headers)
151
+ soup = BeautifulSoup(r.text, features="lxml")
152
+ inner_code = soup.find(name="input", attrs={"id": "clid"})["value"]
153
+ big_df = pd.DataFrame()
154
+ current_year = datetime.now().year
155
+ begin_year = int(start_date[:4])
156
+ tqdm = get_tqdm()
157
+ for year in tqdm(range(begin_year, current_year + 1), leave=False):
158
+ url = f"https://d.10jqka.com.cn/v4/line/bk_{inner_code}/01/{year}.js"
159
+ headers = {
160
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
161
+ "Chrome/89.0.4389.90 Safari/537.36",
162
+ "Referer": "http://q.10jqka.com.cn",
163
+ "Host": "d.10jqka.com.cn",
164
+ "Cookie": f"v={v_code}",
165
+ }
166
+ r = requests.get(url, headers=headers)
167
+ data_text = r.text
168
+
169
+ try:
170
+ demjson.decode(data_text[data_text.find("{") : -1])
171
+ except: # noqa: E722
172
+ continue
173
+ temp_df = demjson.decode(data_text[data_text.find("{") : -1])
174
+ temp_df = pd.DataFrame(temp_df["data"].split(";"))
175
+ temp_df = temp_df.iloc[:, 0].str.split(",", expand=True)
176
+ big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
177
+
178
+ if len(big_df.columns) == 11:
179
+ big_df.columns = [
180
+ "日期",
181
+ "开盘价",
182
+ "最高价",
183
+ "最低价",
184
+ "收盘价",
185
+ "成交量",
186
+ "成交额",
187
+ "_",
188
+ "_",
189
+ "_",
190
+ "_",
191
+ ]
192
+ else:
193
+ big_df.columns = [
194
+ "日期",
195
+ "开盘价",
196
+ "最高价",
197
+ "最低价",
198
+ "收盘价",
199
+ "成交量",
200
+ "成交额",
201
+ "_",
202
+ "_",
203
+ "_",
204
+ "_",
205
+ "_",
206
+ ]
207
+ big_df = big_df[
208
+ [
209
+ "日期",
210
+ "开盘价",
211
+ "最高价",
212
+ "最低价",
213
+ "收盘价",
214
+ "成交量",
215
+ "成交额",
216
+ ]
217
+ ]
218
+ big_df["日期"] = pd.to_datetime(big_df["日期"], errors="coerce").dt.date
219
+ big_df.index = pd.to_datetime(big_df["日期"], errors="coerce")
220
+ big_df = big_df[start_date:end_date]
221
+ big_df.reset_index(drop=True, inplace=True)
222
+ big_df["开盘价"] = pd.to_numeric(big_df["开盘价"], errors="coerce")
223
+ big_df["最高价"] = pd.to_numeric(big_df["最高价"], errors="coerce")
224
+ big_df["最低价"] = pd.to_numeric(big_df["最低价"], errors="coerce")
225
+ big_df["收盘价"] = pd.to_numeric(big_df["收盘价"], errors="coerce")
226
+ big_df["成交量"] = pd.to_numeric(big_df["成交量"], errors="coerce")
227
+ big_df["成交额"] = pd.to_numeric(big_df["成交额"], errors="coerce")
228
+ return big_df
229
+
230
+
231
+ def stock_board_concept_summary_ths() -> pd.DataFrame:
232
+ """
233
+ 同花顺-数据中心-概念板块-概念时间表
234
+ https://q.10jqka.com.cn/gn/
235
+ :return: 概念时间表
236
+ :rtype: pandas.DataFrame
237
+ """
238
+ js_code = py_mini_racer.MiniRacer()
239
+ js_content = _get_file_content_ths("ths.js")
240
+ js_code.eval(js_content)
241
+ v_code = js_code.call("v")
242
+ headers = {
243
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
244
+ "Chrome/89.0.4389.90 Safari/537.36",
245
+ "Cookie": f"v={v_code}",
246
+ }
247
+ url = "http://q.10jqka.com.cn/gn/index/field/addtime/order/desc/page/1/ajax/1/"
248
+ r = requests.get(url, headers=headers)
249
+ soup = BeautifulSoup(r.text, features="lxml")
250
+ page_num = soup.find(name="span", attrs={"class": "page_info"}).text.split("/")[1]
251
+ big_df = pd.DataFrame()
252
+ tqdm = get_tqdm()
253
+ for page in tqdm(range(1, int(page_num) + 1), leave=False):
254
+ url = f"http://q.10jqka.com.cn/gn/index/field/addtime/order/desc/page/{page}/ajax/1/"
255
+ r = requests.get(url, headers=headers)
256
+ try:
257
+ temp_df = pd.read_html(StringIO(r.text))[0]
258
+ big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
259
+ except ValueError:
260
+ break
261
+ big_df["日期"] = pd.to_datetime(big_df["日期"], errors="coerce").dt.date
262
+ big_df["成分股数量"] = pd.to_numeric(big_df["成分股数量"], errors="coerce")
263
+ return big_df
264
+
265
+
266
+ if __name__ == "__main__":
267
+ stock_board_concept_name_ths_df = stock_board_concept_name_ths()
268
+ print(stock_board_concept_name_ths_df)
269
+
270
+ stock_board_concept_info_ths_df = stock_board_concept_info_ths(
271
+ symbol="阿里巴巴概念"
272
+ )
273
+ print(stock_board_concept_info_ths_df)
274
+
275
+ stock_board_concept_index_ths_df = stock_board_concept_index_ths(
276
+ symbol="阿里巴巴概念", start_date="20200101", end_date="20250228"
277
+ )
278
+ print(stock_board_concept_index_ths_df)
279
+
280
+ stock_board_concept_summary_ths_df = stock_board_concept_summary_ths()
281
+ print(stock_board_concept_summary_ths_df)
282
+
283
+ for stock in stock_board_concept_name_ths_df["name"]:
284
+ print(stock)
285
+ stock_board_industry_index_ths_df = stock_board_concept_index_ths(symbol=stock)
286
+ print(stock_board_industry_index_ths_df)
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env python
2
2
  # -*- coding:utf-8 -*-
3
3
  """
4
- Date: 2024/7/21 18:20
4
+ Date: 2025/2/28 13:20
5
5
  Desc: 同花顺-板块-同花顺行业
6
6
  https://q.10jqka.com.cn/thshy/
7
7
  """
@@ -29,7 +29,7 @@ def _get_file_content_ths(file: str = "ths.js") -> str:
29
29
  :rtype: str
30
30
  """
31
31
  setting_file_path = get_ths_js(file)
32
- with open(setting_file_path) as f:
32
+ with open(setting_file_path, encoding="utf-8") as f:
33
33
  file_data = f.read()
34
34
  return file_data
35
35
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env python
2
2
  # -*- coding:utf-8 -*-
3
3
  """
4
- Date: 2025/1/13 22:00
4
+ Date: 2025/2/28 13:00
5
5
  Desc: 东方财富网-数据中心-研究报告-个股研报
6
6
  https://data.eastmoney.com/report/stock.jshtml
7
7
  """
@@ -67,6 +67,9 @@ def stock_research_report_em(symbol: str = "000001") -> pd.DataFrame:
67
67
  predict_next_year_pe_title = f"{current_year + 1}-盈利预测-市盈率"
68
68
  predict_next_two_year_eps_title = f"{current_year + 2}-盈利预测-收益"
69
69
  predict_next_two_year_pe_title = f"{current_year + 2}-盈利预测-市盈率"
70
+ big_df["pdfUrl"] = big_df["infoCode"].apply(
71
+ lambda x: f"https://pdf.dfcfw.com/pdf/H3_{x}_1.pdf"
72
+ )
70
73
  big_df.rename(
71
74
  columns={
72
75
  "index": "序号",
@@ -121,6 +124,7 @@ def stock_research_report_em(symbol: str = "000001") -> pd.DataFrame:
121
124
  "authorID": "-",
122
125
  "count": "近一月个股研报数",
123
126
  "orgType": "-",
127
+ "pdfUrl": "报告PDF链接",
124
128
  },
125
129
  inplace=True,
126
130
  )
@@ -141,6 +145,7 @@ def stock_research_report_em(symbol: str = "000001") -> pd.DataFrame:
141
145
  predict_next_two_year_pe_title,
142
146
  "行业",
143
147
  "日期",
148
+ "报告PDF链接",
144
149
  ]
145
150
  ]
146
151
  big_df["日期"] = pd.to_datetime(big_df["日期"], errors="coerce").dt.date
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: akshare
3
- Version: 1.16.16
3
+ Version: 1.16.18
4
4
  Summary: AKShare is an elegant and simple financial data interface library for Python, built for human beings!
5
5
  Home-page: https://github.com/akfamily/akshare
6
6
  Author: AKFamily
@@ -1,4 +1,4 @@
1
- akshare/__init__.py,sha256=prx47KTjVEM_yjduO2LywB5h9TxVnalCrbb2TJ139u4,188363
1
+ akshare/__init__.py,sha256=7KwD4mtIrWqpTY0Pu66f4m5MfAQ4IU0eN5Ay4VGsx5A,188704
2
2
  akshare/datasets.py,sha256=rKuRNZrqi6IMsZ9nyvO3Rx02js0tH3zMLjz8HQNAoPQ,963
3
3
  akshare/exceptions.py,sha256=WEJjIhSmJ_xXNW6grwV4nufE_cfmmyuhmueVGiN1VAg,878
4
4
  akshare/request.py,sha256=HtFFf9MhfEibR-ETWe-1Tts6ELU4VKSqA-ghaXjegQM,4252
@@ -231,8 +231,8 @@ akshare/stock/__init__.py,sha256=jSa9260d6aNZajaW68chI2mpPkDSXLOgi3eXrqo4MQ8,82
231
231
  akshare/stock/cons.py,sha256=0oyUW5Pu-iQ3qgh-TFemM_O5f1fAwVe-PsI4Qa8EYpQ,42956
232
232
  akshare/stock/stock_allotment_cninfo.py,sha256=OVjVdWp2XVRNbJvVgtgVVoBmPBJgBB4RyIIgA_9QHM8,6066
233
233
  akshare/stock/stock_ask_bid_em.py,sha256=nXQhYIpU4k7GUc7nthWC29zVS9GhYb9ppQTLD0gycF4,3438
234
- akshare/stock/stock_board_concept_em.py,sha256=Inmp1_t3HYUZtESPEiWI8sppPagGUHuvh8v3DMl7cgM,16736
235
- akshare/stock/stock_board_industry_em.py,sha256=ViXBcqSfUnBSvCDo-D7ZRupd9PpI1uEQ19KMAuGxGuQ,16201
234
+ akshare/stock/stock_board_concept_em.py,sha256=JAyXNCuDf-IdkklRSz7D3rUwTwRM4aoLJgliQeivpSo,18431
235
+ akshare/stock/stock_board_industry_em.py,sha256=aaMU78BLVxSTQ4Z55212DsfQDBerKD2OX3as1J9-w1s,19041
236
236
  akshare/stock/stock_cg_equity_mortgage.py,sha256=Pui5aWKKPwGuKjF_GNpejDzsMGNPrxiaJviLz3x2e9I,3426
237
237
  akshare/stock/stock_cg_guarantee.py,sha256=ts7qcQhhyN1PHB7Q4XlMn38HhfVvubOvky9RZfmUP94,3844
238
238
  akshare/stock/stock_cg_lawsuit.py,sha256=6Y92pPw0JgyrInteqHuU07G1jwmdX2wjaDtrJN8y6Hg,4129
@@ -291,7 +291,8 @@ akshare/stock_feature/stock_a_pe_and_pb.py,sha256=wf6AuJOCKwfYxskbrLjIjz21a1MzYv
291
291
  akshare/stock_feature/stock_account_em.py,sha256=PA-531xnv5uerFrYGc40mk8q8O0DGciHC_XVlE9udis,3342
292
292
  akshare/stock_feature/stock_all_pb.py,sha256=2yQLq03qXNbTB5AtJ-Q8uJldOluElH5zTjYneY3aaZ0,1194
293
293
  akshare/stock_feature/stock_analyst_em.py,sha256=Md3_G-Px0O1lk4dx5dCEKl8Vjgwt79Sh-FSh_sW1Elo,9508
294
- akshare/stock_feature/stock_board_industry_ths.py,sha256=KvaWYEdxidYo4qL4LRJOZRsTNe0e3GeiBq1YLi8mf0I,15084
294
+ akshare/stock_feature/stock_board_concept_ths.py,sha256=_FVWd6oxiSWB1X7TS5obHv9pObll3_rBXYwaAhNZ8KM,9689
295
+ akshare/stock_feature/stock_board_industry_ths.py,sha256=c22JP9MJGncLaqvBmkAxHUz3HKNMCKf58Rug9n2vlAU,15102
295
296
  akshare/stock_feature/stock_buffett_index_lg.py,sha256=NpNccHmGjtqLz6aUladB6InPzO2pjoImbgCgmNEYUuM,2027
296
297
  akshare/stock_feature/stock_classify_sina.py,sha256=Lg7ROG5W9HioFRplJI2rZ6tAAHM09N3g9qF6kReIQYI,3210
297
298
  akshare/stock_feature/stock_comment_em.py,sha256=uSOS5YmyXB9jSDsZf1fNC0RPGTE6_4RzjwxaewhJQtc,13697
@@ -332,7 +333,7 @@ akshare/stock_feature/stock_market_legu.py,sha256=_LeyGUGyZFeD-1fnJPc4eIQkeoWAmo
332
333
  akshare/stock_feature/stock_pankou_em.py,sha256=A3lu1hKddXwMFo9vKPLCQfL3Zh77xr2IbcAtKs8Lc9Y,5599
333
334
  akshare/stock_feature/stock_qsjy_em.py,sha256=7EHroLZC3-X_3WNhb7GV9MPQHbxjtkfKI_YEbTvnSb0,3913
334
335
  akshare/stock_feature/stock_report_em.py,sha256=jhePrTKGIYzdz8idiPoDs1vEajd73XRIFpZyWQggKa4,18075
335
- akshare/stock_feature/stock_research_report_em.py,sha256=q98MMIw3AGQy6z96zBQgb-MaE9LPPbkLMhWRChlHEn8,5948
336
+ akshare/stock_feature/stock_research_report_em.py,sha256=yc5aoFPlda_x3q_T_WD31PH5d2RymnMOFB1tITXhzog,6135
336
337
  akshare/stock_feature/stock_sns_sseinfo.py,sha256=TGGLw5P77Hh-sSHgw_KKoK29d1m_V_2GDQXe9m_XFew,4556
337
338
  akshare/stock_feature/stock_sy_em.py,sha256=GysP1WvPpqCLhbCRXH5sxwmXCPYvgtbJYQ_jltDqaA0,17721
338
339
  akshare/stock_feature/stock_technology_ths.py,sha256=4u9z7H6MYEutOYAQvYfzgc_FxG6XlhkMLujSotAbraw,30827
@@ -380,8 +381,8 @@ akshare/utils/token_process.py,sha256=K4rGXjh_tgugbRcyOK2h2x0jP3PT65IIK7nxhUKhOe
380
381
  akshare/utils/tqdm.py,sha256=MuPNwcswkOGjwWQOMWXi9ZvQ_RmW4obCWRj2i7HM7FE,847
381
382
  tests/__init__.py,sha256=gNzhlO0UPjFq6Ieb38kaVIODXv4cTDByrdohAZnDYt4,82
382
383
  tests/test_func.py,sha256=j1MGYbZI2if2j_LY1S4FLsf4qfq4NwVqD5wmRlv5Log,832
383
- akshare-1.16.16.dist-info/LICENSE,sha256=mmSZCPgfHiVw34LXuFArd-SUgQtBJ_QsIlh-kWlDHfs,1073
384
- akshare-1.16.16.dist-info/METADATA,sha256=K8O_FccamgG_aLGLi1UrsaYWliTGqkT3zLBS-sqt6jE,13720
385
- akshare-1.16.16.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
386
- akshare-1.16.16.dist-info/top_level.txt,sha256=jsf9ZzZPmHaISTVumQPsAw7vv7Yv-PdEVW70SMEelQQ,14
387
- akshare-1.16.16.dist-info/RECORD,,
384
+ akshare-1.16.18.dist-info/LICENSE,sha256=mmSZCPgfHiVw34LXuFArd-SUgQtBJ_QsIlh-kWlDHfs,1073
385
+ akshare-1.16.18.dist-info/METADATA,sha256=6vz1edzPefOIGHI7gk223yqPpj4-GHDm_LvIdCia_JE,13720
386
+ akshare-1.16.18.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
387
+ akshare-1.16.18.dist-info/top_level.txt,sha256=jsf9ZzZPmHaISTVumQPsAw7vv7Yv-PdEVW70SMEelQQ,14
388
+ akshare-1.16.18.dist-info/RECORD,,