akshare 1.14.49__py3-none-any.whl → 1.17.99__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 (343) hide show
  1. akshare/__init__.py +595 -129
  2. akshare/air/air_hebei.py +77 -54
  3. akshare/air/air_zhenqi.py +0 -4
  4. akshare/air/cons.py +1 -0
  5. akshare/air/crypto.js +1 -1
  6. akshare/air/outcrypto.js +1 -1
  7. akshare/article/cons.py +1 -0
  8. akshare/article/epu_index.py +4 -3
  9. akshare/article/ff_factor.py +19 -8
  10. akshare/article/fred_md.py +4 -1
  11. akshare/article/risk_rv.py +3 -8
  12. akshare/bank/bank_cbirc_2020.py +11 -11
  13. akshare/bank/cons.py +7 -6
  14. akshare/bond/bond_buy_back_em.py +228 -0
  15. akshare/bond/bond_cb_sina.py +1 -0
  16. akshare/bond/bond_cb_ths.py +17 -9
  17. akshare/bond/bond_cbond.py +19 -14
  18. akshare/bond/bond_china.py +38 -39
  19. akshare/bond/bond_china_money.py +1 -1
  20. akshare/bond/bond_convert.py +10 -9
  21. akshare/bond/bond_em.py +37 -17
  22. akshare/bond/bond_summary.py +38 -37
  23. akshare/bond/bond_zh_cov.py +31 -40
  24. akshare/bond/bond_zh_sina.py +4 -0
  25. akshare/bond/cons.py +14 -11
  26. akshare/cal/__init__.py +0 -0
  27. akshare/cal/rv.py +170 -0
  28. akshare/cost/cost_living.py +7 -5
  29. akshare/crypto/__init__.py +1 -1
  30. akshare/crypto/crypto_bitcoin_cme.py +9 -7
  31. akshare/crypto/crypto_hold.py +4 -2
  32. akshare/currency/currency.py +1 -0
  33. akshare/currency/currency_china_bank_sina.py +11 -6
  34. akshare/data/__init__.py +1 -1
  35. akshare/data/cninfo.js +1 -1
  36. akshare/datasets.py +10 -21
  37. akshare/economic/cons.py +10 -3
  38. akshare/economic/macro_australia.py +74 -69
  39. akshare/economic/macro_bank.py +95 -653
  40. akshare/economic/macro_canada.py +92 -81
  41. akshare/economic/macro_china.py +97 -105
  42. akshare/economic/macro_china_hk.py +0 -1
  43. akshare/economic/macro_euro.py +103 -56
  44. akshare/economic/macro_finance_ths.py +7 -5
  45. akshare/economic/macro_germany.py +1 -1
  46. akshare/economic/macro_japan.py +0 -1
  47. akshare/economic/macro_other.py +1 -6
  48. akshare/economic/macro_swiss.py +2 -3
  49. akshare/economic/macro_uk.py +1 -1
  50. akshare/economic/macro_usa.py +7 -9
  51. akshare/economic/marco_cnbs.py +11 -6
  52. akshare/energy/energy_carbon.py +0 -1
  53. akshare/energy/energy_oil_em.py +1 -2
  54. akshare/event/cons.py +1 -0
  55. akshare/exceptions.py +43 -0
  56. akshare/file_fold/calendar.json +245 -2
  57. akshare/forex/__init__.py +0 -0
  58. akshare/forex/cons.py +192 -0
  59. akshare/forex/forex_em.py +149 -0
  60. akshare/fortune/fortune_500.py +1 -37
  61. akshare/fortune/fortune_bloomberg.py +6 -3
  62. akshare/fortune/fortune_forbes_500.py +3 -6
  63. akshare/fortune/fortune_hurun.py +2 -1
  64. akshare/fortune/fortune_xincaifu_500.py +17 -14
  65. akshare/fund/fund_announcement_em.py +145 -0
  66. akshare/fund/fund_aum_em.py +49 -35
  67. akshare/fund/fund_em.py +251 -220
  68. akshare/fund/fund_etf_em.py +44 -35
  69. akshare/fund/fund_etf_sina.py +75 -27
  70. akshare/fund/fund_etf_ths.py +2 -0
  71. akshare/fund/fund_fee_em.py +172 -0
  72. akshare/fund/fund_fhsp_em.py +42 -32
  73. akshare/fund/fund_init_em.py +8 -5
  74. akshare/fund/fund_lof_em.py +12 -19
  75. akshare/fund/fund_manager.py +25 -11
  76. akshare/fund/fund_overview_em.py +42 -0
  77. akshare/fund/fund_portfolio_em.py +23 -21
  78. akshare/fund/fund_position_lg.py +19 -8
  79. akshare/fund/fund_rank_em.py +2 -5
  80. akshare/fund/fund_rating.py +33 -12
  81. akshare/fund/fund_scale_em.py +24 -13
  82. akshare/fund/fund_scale_sina.py +20 -10
  83. akshare/fund/fund_xq.py +3 -2
  84. akshare/futures/cons.py +135 -39
  85. akshare/futures/cot.py +55 -56
  86. akshare/futures/futures_basis.py +49 -11
  87. akshare/futures/futures_comex_em.py +1 -0
  88. akshare/futures/futures_comm_ctp.py +1 -1
  89. akshare/futures/futures_contract_detail.py +59 -9
  90. akshare/futures/futures_daily_bar.py +66 -59
  91. akshare/futures/futures_foreign.py +14 -8
  92. akshare/futures/futures_hf_em.py +215 -61
  93. akshare/futures/futures_hist_em.py +191 -0
  94. akshare/futures/futures_hq_sina.py +5 -3
  95. akshare/futures/futures_index_ccidx.py +24 -82
  96. akshare/futures/futures_inventory_99.py +70 -272
  97. akshare/futures/futures_inventory_em.py +14 -11
  98. akshare/futures/futures_news_shmet.py +2 -2
  99. akshare/futures/futures_roll_yield.py +11 -24
  100. akshare/futures/futures_rule.py +7 -3
  101. akshare/futures/futures_rule_em.py +38 -0
  102. akshare/futures/futures_settlement_price_sgx.py +21 -6
  103. akshare/futures/futures_stock_js.py +0 -1
  104. akshare/futures/futures_to_spot.py +5 -6
  105. akshare/futures/futures_warehouse_receipt.py +48 -47
  106. akshare/futures/futures_zh_sina.py +3 -3
  107. akshare/futures/receipt.py +298 -165
  108. akshare/futures/requests_fun.py +16 -3
  109. akshare/futures/symbol_var.py +32 -13
  110. akshare/futures_derivative/cons.py +100 -103
  111. akshare/futures_derivative/futures_contract_info_cffex.py +55 -39
  112. akshare/futures_derivative/futures_contract_info_czce.py +2 -0
  113. akshare/futures_derivative/futures_contract_info_dce.py +43 -17
  114. akshare/futures_derivative/futures_contract_info_gfex.py +43 -31
  115. akshare/futures_derivative/futures_contract_info_ine.py +43 -34
  116. akshare/futures_derivative/futures_contract_info_shfe.py +3 -4
  117. akshare/futures_derivative/futures_cot_sina.py +8 -6
  118. akshare/futures_derivative/futures_index_sina.py +25 -13
  119. akshare/fx/cons.py +12 -7
  120. akshare/fx/fx_c_swap_cm.py +62 -0
  121. akshare/fx/fx_quote.py +3 -2
  122. akshare/fx/fx_quote_baidu.py +2 -1
  123. akshare/hf/__init__.py +1 -1
  124. akshare/hf/hf_sp500.py +8 -7
  125. akshare/index/cons.py +132 -28
  126. akshare/index/index_cni.py +7 -7
  127. akshare/index/index_cons.py +2 -2
  128. akshare/index/index_csindex.py +68 -0
  129. akshare/index/index_cx.py +20 -20
  130. akshare/index/index_drewry.py +17 -16
  131. akshare/index/index_eri.py +1 -0
  132. akshare/index/index_global_em.py +167 -0
  133. akshare/index/index_global_sina.py +82 -0
  134. akshare/index/index_kq_fz.py +17 -14
  135. akshare/index/index_kq_ss.py +1 -0
  136. akshare/index/index_option_qvix.py +351 -16
  137. akshare/index/index_research_sw.py +21 -21
  138. akshare/index/index_spot.py +9 -5
  139. akshare/index/index_stock_hk.py +5 -9
  140. akshare/index/index_stock_zh.py +111 -24
  141. akshare/index/index_stock_zh_csindex.py +3 -367
  142. akshare/index/index_sugar.py +18 -4
  143. akshare/index/index_sw.py +10 -2
  144. akshare/index/index_yw.py +53 -75
  145. akshare/index/index_zh_em.py +15 -82
  146. akshare/interest_rate/interbank_rate_em.py +0 -1
  147. akshare/movie/jm.js +0 -1
  148. akshare/news/__init__.py +1 -1
  149. akshare/news/news_baidu.py +395 -222
  150. akshare/news/news_stock.py +49 -16
  151. akshare/option/cons.py +2 -2
  152. akshare/option/option_commodity.py +341 -220
  153. akshare/option/option_commodity_sina.py +22 -26
  154. akshare/option/option_contract_info_ctp.py +63 -0
  155. akshare/option/option_current_sse.py +61 -0
  156. akshare/option/option_current_szse.py +84 -0
  157. akshare/option/option_czce.py +37 -9
  158. akshare/option/option_daily_stats_sse_szse.py +0 -1
  159. akshare/option/option_em.py +4 -8
  160. akshare/option/option_finance.py +60 -12
  161. akshare/option/option_finance_sina.py +7 -7
  162. akshare/option/option_lhb_em.py +0 -1
  163. akshare/option/option_margin.py +62 -0
  164. akshare/option/option_premium_analysis_em.py +58 -53
  165. akshare/option/option_risk_analysis_em.py +11 -8
  166. akshare/option/option_risk_indicator_sse.py +3 -4
  167. akshare/option/option_value_analysis_em.py +62 -55
  168. akshare/other/__init__.py +1 -1
  169. akshare/pro/__init__.py +0 -1
  170. akshare/pro/client.py +6 -4
  171. akshare/pro/cons.py +3 -2
  172. akshare/pro/data_pro.py +6 -5
  173. akshare/qdii/__init__.py +0 -0
  174. akshare/qdii/qdii_jsl.py +233 -0
  175. akshare/qhkc/__init__.py +1 -6
  176. akshare/qhkc/qhkc_api.py +64 -22
  177. akshare/qhkc_web/__init__.py +1 -6
  178. akshare/qhkc_web/qhkc_fund.py +10 -6
  179. akshare/qhkc_web/qhkc_index.py +28 -14
  180. akshare/qhkc_web/qhkc_tool.py +62 -59
  181. akshare/rate/__init__.py +1 -1
  182. akshare/rate/repo_rate.py +36 -32
  183. akshare/reits/__init__.py +1 -1
  184. akshare/reits/reits_basic.py +149 -13
  185. akshare/request.py +117 -0
  186. akshare/spot/__init__.py +1 -1
  187. akshare/spot/spot_hog_soozhu.py +165 -3
  188. akshare/spot/spot_sge.py +70 -9
  189. akshare/stock/cons.py +60 -23
  190. akshare/stock/stock_allotment_cninfo.py +8 -8
  191. akshare/stock/stock_ask_bid_em.py +3 -78
  192. akshare/stock/stock_board_concept_em.py +160 -35
  193. akshare/stock/stock_board_industry_em.py +163 -70
  194. akshare/stock/stock_dividend_cninfo.py +31 -17
  195. akshare/stock/stock_dzjy_em.py +347 -260
  196. akshare/stock/stock_fund_em.py +72 -64
  197. akshare/stock/stock_fund_hold.py +1 -2
  198. akshare/stock/stock_gsrl_em.py +1 -0
  199. akshare/stock/stock_hk_comparison_em.py +175 -0
  200. akshare/stock/stock_hk_famous.py +4 -5
  201. akshare/stock/stock_hk_fhpx_ths.py +2 -1
  202. akshare/stock/stock_hk_hot_rank_em.py +1 -0
  203. akshare/stock/stock_hk_sina.py +84 -36
  204. akshare/stock/stock_hold_control_cninfo.py +82 -0
  205. akshare/stock/stock_hold_control_em.py +0 -2
  206. akshare/stock/stock_hot_rank_em.py +4 -1
  207. akshare/stock/stock_hot_search_baidu.py +32 -19
  208. akshare/stock/stock_hot_up_em.py +4 -1
  209. akshare/stock/stock_hsgt_em.py +155 -0
  210. akshare/stock/stock_industry.py +1 -0
  211. akshare/stock/stock_industry_cninfo.py +1 -2
  212. akshare/stock/stock_info.py +6 -4
  213. akshare/stock/stock_info_em.py +17 -11
  214. akshare/stock/stock_intraday_em.py +4 -78
  215. akshare/stock/stock_intraday_sina.py +2 -2
  216. akshare/stock/stock_news_cx.py +39 -0
  217. akshare/stock/stock_profile_cninfo.py +7 -7
  218. akshare/stock/stock_profile_em.py +302 -0
  219. akshare/stock/stock_rank_forecast.py +6 -5
  220. akshare/stock/stock_repurchase_em.py +7 -2
  221. akshare/stock/stock_share_changes_cninfo.py +7 -5
  222. akshare/stock/stock_share_hold.py +24 -20
  223. akshare/stock/stock_stop.py +6 -6
  224. akshare/stock/stock_summary.py +153 -417
  225. akshare/stock/stock_us_famous.py +5 -6
  226. akshare/stock/stock_us_js.py +3 -2
  227. akshare/stock/stock_us_pink.py +38 -27
  228. akshare/stock/stock_us_sina.py +7 -3
  229. akshare/stock/stock_weibo_nlp.py +18 -20
  230. akshare/stock/stock_xq.py +24 -22
  231. akshare/stock/stock_zh_a_sina.py +8 -5
  232. akshare/stock/stock_zh_a_special.py +240 -243
  233. akshare/stock/stock_zh_a_tick_tx.py +11 -3
  234. akshare/stock/stock_zh_ah_tx.py +23 -26
  235. akshare/stock/stock_zh_b_sina.py +2 -2
  236. akshare/stock/stock_zh_comparison_em.py +250 -0
  237. akshare/stock/stock_zh_kcb_sina.py +67 -64
  238. akshare/stock_a/__init__.py +0 -0
  239. akshare/stock_a/stock_board_concept_name_em.py +170 -0
  240. akshare/stock_a/stock_individual_fund_flow_rank.py +258 -0
  241. akshare/stock_a/stock_zh_a_spot.py +212 -0
  242. akshare/stock_feature/cons.py +1 -0
  243. akshare/stock_feature/stock_a_indicator.py +9 -54
  244. akshare/stock_feature/stock_a_pe_and_pb.py +23 -5
  245. akshare/stock_feature/stock_account_em.py +0 -1
  246. akshare/stock_feature/stock_all_pb.py +2 -1
  247. akshare/stock_feature/stock_analyst_em.py +36 -30
  248. akshare/stock_feature/stock_board_concept_ths.py +328 -0
  249. akshare/stock_feature/stock_board_industry_ths.py +57 -2
  250. akshare/stock_feature/stock_buffett_index_lg.py +10 -8
  251. akshare/stock_feature/stock_classify_sina.py +3 -6
  252. akshare/stock_feature/stock_comment_em.py +81 -144
  253. akshare/stock_feature/stock_congestion_lg.py +2 -1
  254. akshare/stock_feature/stock_cyq_em.py +5 -11
  255. akshare/stock_feature/stock_disclosure_cninfo.py +6 -6
  256. akshare/stock_feature/stock_dxsyl_em.py +121 -74
  257. akshare/stock_feature/stock_ebs_lg.py +5 -4
  258. akshare/stock_feature/stock_esg_sina.py +29 -7
  259. akshare/stock_feature/stock_fhps_em.py +2 -1
  260. akshare/stock_feature/stock_fhps_ths.py +15 -7
  261. akshare/stock_feature/stock_fund_flow.py +30 -22
  262. akshare/stock_feature/stock_gddh_em.py +19 -11
  263. akshare/stock_feature/stock_gdfx_em.py +226 -113
  264. akshare/stock_feature/stock_gdhs.py +75 -50
  265. akshare/stock_feature/stock_gdzjc_em.py +21 -10
  266. akshare/stock_feature/stock_gpzy_em.py +78 -46
  267. akshare/stock_feature/stock_gxl_lg.py +3 -2
  268. akshare/stock_feature/stock_hist_em.py +137 -234
  269. akshare/stock_feature/stock_hist_tx.py +13 -10
  270. akshare/stock_feature/stock_hk_valuation_baidu.py +20 -8
  271. akshare/stock_feature/stock_hot_xq.py +4 -6
  272. akshare/stock_feature/stock_hsgt_em.py +269 -97
  273. akshare/stock_feature/stock_hsgt_exchange_rate.py +115 -87
  274. akshare/stock_feature/stock_hsgt_min_em.py +13 -16
  275. akshare/stock_feature/stock_info.py +7 -80
  276. akshare/stock_feature/stock_inner_trade_xq.py +38 -31
  277. akshare/stock_feature/stock_jgdy_em.py +43 -40
  278. akshare/stock_feature/stock_lhb_em.py +119 -3
  279. akshare/stock_feature/stock_margin_em.py +0 -1
  280. akshare/stock_feature/stock_margin_sse.py +0 -2
  281. akshare/stock_feature/stock_pankou_em.py +71 -35
  282. akshare/stock_feature/stock_qsjy_em.py +13 -4
  283. akshare/stock_feature/stock_report_em.py +151 -7
  284. akshare/stock_feature/stock_research_report_em.py +55 -20
  285. akshare/stock_feature/stock_sy_em.py +20 -15
  286. akshare/stock_feature/stock_technology_ths.py +122 -77
  287. akshare/stock_feature/stock_tfp_em.py +2 -1
  288. akshare/stock_feature/stock_three_report_em.py +21 -5
  289. akshare/stock_feature/stock_ttm_lyr.py +18 -9
  290. akshare/stock_feature/stock_value_em.py +83 -0
  291. akshare/stock_feature/stock_yjbb_em.py +58 -32
  292. akshare/stock_feature/stock_yjyg_cninfo.py +6 -2
  293. akshare/stock_feature/stock_yjyg_em.py +1 -1
  294. akshare/stock_feature/stock_yzxdr_em.py +24 -22
  295. akshare/stock_feature/stock_zdhtmx_em.py +20 -6
  296. akshare/stock_feature/stock_zh_vote_baidu.py +4 -1
  297. akshare/stock_feature/stock_ztb_em.py +39 -24
  298. akshare/stock_fundamental/__init__.py +1 -1
  299. akshare/stock_fundamental/stock_basic_info_xq.py +119 -0
  300. akshare/stock_fundamental/{stock_finance_hk.py → stock_finance_hk_em.py} +23 -16
  301. akshare/stock_fundamental/{stock_finance.py → stock_finance_sina.py} +60 -7
  302. akshare/stock_fundamental/stock_finance_ths.py +524 -57
  303. akshare/stock_fundamental/stock_finance_us_em.py +268 -0
  304. akshare/stock_fundamental/stock_gbjg_em.py +80 -0
  305. akshare/stock_fundamental/stock_hold.py +26 -17
  306. akshare/stock_fundamental/stock_ipo_declare.py +1 -0
  307. akshare/stock_fundamental/stock_kcb_detail_sse.py +10 -10
  308. akshare/stock_fundamental/stock_kcb_sse.py +26 -25
  309. akshare/stock_fundamental/stock_notice.py +12 -3
  310. akshare/stock_fundamental/stock_profit_forecast_em.py +31 -13
  311. akshare/stock_fundamental/stock_profit_forecast_hk_etnet.py +64 -41
  312. akshare/stock_fundamental/stock_profit_forecast_ths.py +86 -35
  313. akshare/stock_fundamental/stock_recommend.py +20 -4
  314. akshare/stock_fundamental/stock_zygc.py +5 -62
  315. akshare/utils/context.py +43 -0
  316. akshare/utils/demjson.py +2009 -1338
  317. akshare/utils/func.py +49 -2
  318. akshare/utils/multi_decrypt.py +53 -0
  319. akshare/utils/token_process.py +6 -5
  320. {akshare-1.14.49.dist-info → akshare-1.17.99.dist-info}/METADATA +54 -80
  321. akshare-1.17.99.dist-info/RECORD +409 -0
  322. {akshare-1.14.49.dist-info → akshare-1.17.99.dist-info}/WHEEL +1 -1
  323. {akshare-1.14.49.dist-info → akshare-1.17.99.dist-info/licenses}/LICENSE +1 -1
  324. tests/test_func.py +3 -5
  325. akshare/bond/bond_futures.py +0 -50
  326. akshare/bond/bond_investing.py +0 -139
  327. akshare/crypto/crypto_hist_investing.py +0 -249
  328. akshare/fund/fund_announcement.py +0 -56
  329. akshare/futures/futures_international.py +0 -170
  330. akshare/futures/futures_news_baidu.py +0 -54
  331. akshare/futures/inventory_data.py +0 -100
  332. akshare/futures_derivative/futures_index_price_nh.py +0 -61
  333. akshare/futures_derivative/futures_index_return_nh.py +0 -47
  334. akshare/futures_derivative/futures_index_volatility_nh.py +0 -53
  335. akshare/futures_derivative/futures_other_index_nh.py +0 -145
  336. akshare/index/index_fear_greed_funddb.py +0 -78
  337. akshare/index/index_investing.py +0 -232
  338. akshare/sport/__init__.py +0 -6
  339. akshare/sport/sport_olympic.py +0 -27
  340. akshare/stock_feature/stock_wencai.py +0 -104
  341. akshare/stock_fundamental/stock_mda_ym.py +0 -40
  342. akshare-1.14.49.dist-info/RECORD +0 -387
  343. {akshare-1.14.49.dist-info → akshare-1.17.99.dist-info}/top_level.txt +0 -0
@@ -1,272 +1,445 @@
1
1
  # -*- coding:utf-8 -*-
2
2
  # !/usr/bin/env python
3
3
  """
4
- Date: 2024/3/27 10:00
4
+ Date: 2025/12/1 22:00
5
5
  Desc: 百度股市通-经济数据
6
6
  https://gushitong.baidu.com/calendar
7
7
  """
8
-
9
- import http.client
10
- import json
11
- from urllib.parse import urlencode
8
+ import math
9
+ import re
12
10
 
13
11
  import pandas as pd
14
- import requests
12
+ from curl_cffi import requests
15
13
 
16
14
 
17
- def news_economic_baidu(date: str = "20240327") -> pd.DataFrame:
15
+ def _get_baidu_cookie(headers: dict) -> str:
18
16
  """
19
- 百度股市通-经济数据
20
- https://gushitong.baidu.com/calendar
21
- :param date: 查询日期
22
- :type date: str
23
- :return: 经济数据
24
- :rtype: pandas.DataFrame
17
+ 安全获取百度股市通所需的Cookie
18
+ :param headers: 基础请求头
19
+ :return: 格式化的Cookie字符串
20
+ :raises ValueError: 当无法获取必要Cookie时
21
+ :raises ConnectionError: 网络请求失败时
25
22
  """
26
- start_date = "-".join([date[:4], date[4:6], date[6:]])
27
- end_date = "-".join([date[:4], date[4:6], date[6:]])
28
- url = "https://finance.pae.baidu.com/api/financecalendar"
29
- params = {
30
- "start_date": start_date,
31
- "end_date": end_date,
32
- "market": "",
33
- "cate": "economic_data",
34
- # "rn": "500",
35
- # "pn": "0",
23
+ try:
24
+ # 使用Session保持Cookie上下文
25
+ with requests.Session() as session:
26
+ session.headers.update(headers)
27
+
28
+ # 第一步:获取基础Cookie (BAIDUID系列)
29
+ resp1 = session.get(
30
+ "https://gushitong.baidu.com/calendar",
31
+ impersonate="chrome110",
32
+ timeout=10
33
+ )
34
+ resp1.raise_for_status()
35
+
36
+ # 验证必要Cookie
37
+ baiduid = resp1.cookies.get("BAIDUID")
38
+ baiduid_bfess = resp1.cookies.get("BAIDUID_BFESS")
39
+ if not all([baiduid, baiduid_bfess]):
40
+ raise ValueError("Missing BAIDUID cookies in first response")
41
+
42
+ # 第二步:提取并请求hm.js
43
+ hm_pattern = r'https://hm\.baidu\.com/hm\.js\?\w+'
44
+ hm_match = re.search(hm_pattern, resp1.text)
45
+ if not hm_match:
46
+ # 尝试备用正则模式
47
+ hm_match = re.search(r'//hm\.baidu\.com/hm\.js\?\w+', resp1.text)
48
+ if not hm_match:
49
+ raise ValueError("Failed to extract hm.js URL from response")
50
+
51
+ hm_url = "https:" + hm_match.group() if hm_match.group().startswith("//") else hm_match.group()
52
+
53
+ # 第二步请求 (自动携带第一步的Cookie)
54
+ resp2 = session.get(hm_url, impersonate="chrome110", timeout=10)
55
+ resp2.raise_for_status()
56
+
57
+ # 验证必要Cookie
58
+ hmac_count = resp2.cookies.get("HMACCOUNT")
59
+ hmac_count_bfess = resp2.cookies.get("HMACCOUNT_BFESS")
60
+ if not all([hmac_count, hmac_count_bfess]):
61
+ raise ValueError("Missing HMACCOUNT cookies in second response")
62
+
63
+ # 安全拼接Cookie
64
+ return (
65
+ f"BAIDUID={baiduid}; "
66
+ f"BAIDUID_BFESS={baiduid_bfess}; "
67
+ f"HMACCOUNT={hmac_count}; "
68
+ f"HMACCOUNT_BFESS={hmac_count_bfess}"
69
+ )
70
+
71
+ except requests.exceptions.RequestException as e:
72
+ raise ConnectionError(f"Network request failed: {str(e)}") from e
73
+ except re.error as e:
74
+ raise ValueError(f"Regex pattern error: {str(e)}") from e
75
+
76
+
77
+ def _baidu_finance_calendar(
78
+ date: str,
79
+ cate: str,
80
+ process_func,
81
+ cookie: str = None
82
+ ) -> pd.DataFrame:
83
+ """
84
+ 百度股市通日历数据基础函数(支持分页)
85
+ :param date: 查询日期 (格式: YYYYMMDD)
86
+ :param cate: 数据类别 ("economic_data" 或 "notify_suspend")
87
+ :param process_func: 数据处理函数
88
+ :param cookie: cookie
89
+ :return: 处理后的DataFrame
90
+ """
91
+ # 日期格式转换
92
+ formatted_date = "-".join([date[:4], date[4:6], date[6:]])
93
+
94
+ # 构建请求参数
95
+ base_params = {
96
+ "start_date": formatted_date,
97
+ "end_date": formatted_date,
98
+ "pn": "0",
99
+ "rn": "100", # 每页100条
100
+ "cate": cate,
36
101
  "finClientType": "pc",
37
102
  }
38
- r = requests.get(url, params=params)
39
- data_json = r.json()
103
+
104
+ # 构建请求头
105
+ headers = {
106
+ "accept": "application/vnd.finance-web.v1+json",
107
+ "accept-encoding": "gzip, deflate, br, zstd",
108
+ "accept-language": "en,zh-CN;q=0.9,zh;q=0.8",
109
+ "cache-control": "no-cache",
110
+ "origin": "https://gushitong.baidu.com",
111
+ "pragma": "no-cache",
112
+ "priority": "u=1, i",
113
+ "referer": "https://gushitong.baidu.com/",
114
+ "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
115
+ "Chrome/142.0.0.0 Safari/537.36"
116
+ }
117
+
118
+ # 在_baidu_finance_calendar函数中替换原代码块
119
+ if cookie is None:
120
+ try:
121
+ cookie = _get_baidu_cookie(headers.copy()) # 保护原始headers
122
+ except Exception as e:
123
+ # 可降级处理或保留原始行为
124
+ raise RuntimeError(f"Failed to obtain Baidu cookies: {str(e)}") from e
125
+ headers["cookie"] = cookie
126
+
127
+ url = "https://finance.pae.baidu.com/sapi/v1/financecalendar"
40
128
  big_df = pd.DataFrame()
41
- for item in data_json["Result"]:
42
- if not item["list"] == []:
43
- temp_df = pd.DataFrame(item["list"])
44
- temp_df.columns = [
45
- "日期",
46
- "时间",
47
- "-",
48
- "事件",
49
- "重要性",
50
- "前值",
51
- "预期",
52
- "公布",
53
- "-",
54
- "-",
55
- "地区",
56
- "-",
57
- ]
58
- temp_df = temp_df[
59
- [
60
- "日期",
61
- "时间",
62
- "地区",
63
- "事件",
64
- "公布",
65
- "预期",
66
- "前值",
67
- "重要性",
68
- ]
69
- ]
70
- temp_df["公布"] = pd.to_numeric(temp_df["公布"], errors="coerce")
71
- temp_df["预期"] = pd.to_numeric(temp_df["预期"], errors="coerce")
72
- temp_df["前值"] = pd.to_numeric(temp_df["前值"], errors="coerce")
73
- temp_df["重要性"] = pd.to_numeric(temp_df["重要性"], errors="coerce")
74
- temp_df["日期"] = pd.to_datetime(temp_df["日期"], errors="coerce").dt.date
75
- big_df = pd.concat([big_df, temp_df], ignore_index=True)
76
- else:
77
- continue
129
+
130
+ # 获取指定日期的总记录数
131
+ target_date = formatted_date
132
+ total_records = 0
133
+
134
+ # 第一次请求
135
+ params = base_params.copy()
136
+ response = requests.get(url=url, params=params, headers=headers)
137
+ response.raise_for_status()
138
+ data_json = response.json()
139
+
140
+ # 从JSON中提取指定日期的总记录数
141
+ if "Result" in data_json and "calendarInfo" in data_json["Result"]:
142
+ calendar_info = data_json["Result"]["calendarInfo"]
143
+
144
+ # 查找目标日期的记录
145
+ for item in calendar_info:
146
+ if item.get("date") == target_date:
147
+ total_records = item.get("total", 0)
148
+ break
149
+
150
+ # 计算总页数 (每页100条)
151
+ total_pages = math.ceil(total_records / 100) if total_records > 0 else 1
152
+
153
+ # 处理所有页码
154
+ for page in range(total_pages):
155
+ if page > 0: # 第一页已在前面获取
156
+ params = base_params.copy()
157
+ params["pn"] = str(page)
158
+ response = requests.get(url=url, params=params, headers=headers)
159
+ response.raise_for_status()
160
+ data_json = response.json()
161
+
162
+ # 提取并处理指定日期的数据
163
+ if "Result" in data_json and "calendarInfo" in data_json["Result"]:
164
+ for item in data_json["Result"]["calendarInfo"]:
165
+ if item.get("date") == target_date and item.get("list"):
166
+ processed_df = process_func(item["list"])
167
+ big_df = pd.concat([big_df, processed_df], ignore_index=True)
168
+
78
169
  return big_df
79
170
 
80
171
 
81
- def news_trade_notify_suspend_baidu(date: str = "20220513") -> pd.DataFrame:
172
+ def _process_economic_data(data_list: list) -> pd.DataFrame:
173
+ """处理经济数据"""
174
+ if not data_list:
175
+ return pd.DataFrame()
176
+
177
+ temp_df = pd.DataFrame(data_list)
178
+ rename_dict = {
179
+ "date": "日期",
180
+ "time": "时间",
181
+ "title": "事件",
182
+ "star": "重要性",
183
+ "formerVal": "前值",
184
+ "pubVal": "公布",
185
+ "region": "地区",
186
+ "indicateVal": "预期",
187
+ "country": "国家",
188
+ "timePeriod": "统计周期"
189
+ }
190
+ temp_df.rename(columns=rename_dict, inplace=True)
191
+
192
+ # 确保必要列存在
193
+ required_cols = ["公布", "预期", "前值", "重要性"]
194
+ for col in required_cols:
195
+ if col not in temp_df.columns:
196
+ temp_df[col] = None
197
+
198
+ # 选择并排序列 (根据实际存在的列)
199
+ available_cols = []
200
+ for col in ["日期", "时间", "国家", "地区", "事件", "统计周期", "公布", "预期", "前值", "重要性"]:
201
+ if col in temp_df.columns:
202
+ available_cols.append(col)
203
+
204
+ if available_cols:
205
+ temp_df = temp_df[available_cols]
206
+
207
+ # 类型转换
208
+ for col in ["公布", "预期", "前值", "重要性"]:
209
+ if col in temp_df.columns:
210
+ temp_df[col] = pd.to_numeric(temp_df[col], errors="coerce")
211
+
212
+ if "日期" in temp_df.columns:
213
+ temp_df["日期"] = pd.to_datetime(temp_df["日期"], errors="coerce").dt.date
214
+
215
+ return temp_df
216
+
217
+
218
+ def _process_suspend_data(data_list: list) -> pd.DataFrame:
219
+ """处理停复牌数据 - 根据实际JSON结构精确修正"""
220
+ if not data_list:
221
+ return pd.DataFrame()
222
+
223
+ # 创建DataFrame
224
+ temp_df = pd.DataFrame(data_list)
225
+
226
+ # 精确字段映射 (根据实际JSON结构)
227
+ rename_dict = {
228
+ "code": "股票代码",
229
+ "name": "股票简称",
230
+ "exchange": "交易所代码",
231
+ "start": "停牌时间", # 实际停牌开始时间字段
232
+ "reason": "停牌事项说明",
233
+ "marketValue": "市值", # 使用marketValue而非capitalization
234
+ "date": "公告日期",
235
+ "time": "公告时间",
236
+ "type": "证券类型",
237
+ "market": "市场类型",
238
+ "isSkip": "是否跳过",
239
+ "end": "复牌时间"
240
+ }
241
+ temp_df.rename(columns=rename_dict, inplace=True)
242
+ if "复牌时间" not in temp_df.columns:
243
+ temp_df['复牌时间'] = '-'
244
+ temp_df = temp_df[[
245
+ "股票代码",
246
+ "股票简称",
247
+ "交易所代码",
248
+ "停牌时间", # 实际停牌开始时间字段
249
+ "复牌时间", # 实际停牌开始时间字段
250
+ "停牌事项说明",
251
+ "市值", # 使用marketValue而非capitalization
252
+ "公告日期",
253
+ "公告时间",
254
+ "证券类型",
255
+ "市场类型",
256
+ "是否跳过"
257
+ ]]
258
+ return temp_df
259
+
260
+
261
+ def news_economic_baidu(date: str = "20251126", cookie: str = None) -> pd.DataFrame:
262
+ """
263
+ 百度股市通-经济数据
264
+ https://gushitong.baidu.com/calendar
265
+ :param date: 查询日期 (格式: YYYYMMDD)
266
+ :param cookie: cookie
267
+ :return: 经济数据DataFrame
268
+ """
269
+ return _baidu_finance_calendar(
270
+ date=date,
271
+ cate="economic_data",
272
+ process_func=_process_economic_data,
273
+ cookie=cookie
274
+ )
275
+
276
+
277
+ def news_trade_notify_suspend_baidu(date: str = "20251126", cookie: str = None) -> pd.DataFrame:
82
278
  """
83
279
  百度股市通-交易提醒-停复牌
84
280
  https://gushitong.baidu.com/calendar
85
- :param date: 查询日期
86
- :type date: str
87
- :return: 交易提醒-停复牌
88
- :rtype: pandas.DataFrame
281
+ :param date: 查询日期 (格式: YYYYMMDD)
282
+ :param cookie: cookie
283
+ :return: 停复牌数据DataFrame
89
284
  """
90
- start_date = "-".join([date[:4], date[4:6], date[6:]])
91
- end_date = "-".join([date[:4], date[4:6], date[6:]])
92
- url = "https://finance.pae.baidu.com/api/financecalendar"
93
- params = {
94
- "start_date": start_date,
95
- "end_date": end_date,
96
- "market": "",
97
- "cate": "notify_suspend",
285
+ return _baidu_finance_calendar(
286
+ date=date,
287
+ cate="notify_suspend",
288
+ process_func=_process_suspend_data,
289
+ cookie=cookie
290
+ )
291
+
292
+
293
+ def _process_dividend_data(data_list: list) -> pd.DataFrame:
294
+ """处理分红派息数据"""
295
+ if not data_list:
296
+ return pd.DataFrame()
297
+
298
+ temp_df = pd.DataFrame(data_list)
299
+
300
+ # 字段映射
301
+ rename_dict = {
302
+ "code": "股票代码",
303
+ "market": "-", # 这个字段在最终结果中会被删除
304
+ "exchange": "交易所",
305
+ "name": "股票简称",
306
+ "diviDate": "除权日",
307
+ "date": "报告期",
308
+ "diviCash": "分红",
309
+ "shareDivide": "送股",
310
+ "transfer": "转增",
311
+ "physical": "实物",
98
312
  }
99
- r = requests.get(url, params=params)
100
- data_json = r.json()
101
- big_df = pd.DataFrame()
102
- for item in data_json["Result"]:
103
- if not item["list"] == []:
104
- temp_df = pd.DataFrame(item["list"])
105
- temp_df.columns = [
106
- "股票代码",
107
- "-",
108
- "交易所",
109
- "股票简称",
110
- "停牌时间",
111
- "复牌时间",
112
- "-",
113
- "停牌事项说明",
114
- ]
115
- temp_df = temp_df[
116
- [
117
- "股票代码",
118
- "股票简称",
119
- "交易所",
120
- "停牌时间",
121
- "复牌时间",
122
- "停牌事项说明",
123
- ]
124
- ]
125
- temp_df["停牌时间"] = pd.to_datetime(
126
- temp_df["停牌时间"], errors="coerce"
127
- ).dt.date
128
- temp_df["复牌时间"] = pd.to_datetime(
129
- temp_df["复牌时间"], errors="coerce"
130
- ).dt.date
131
- big_df = pd.concat([big_df, temp_df], ignore_index=True)
132
- else:
133
- continue
134
- return big_df
313
+ temp_df.rename(columns=rename_dict, inplace=True)
314
+
315
+ # 确保必要列存在
316
+ if "实物" not in temp_df.columns:
317
+ temp_df["实物"] = "-"
318
+ if "送股" not in temp_df.columns:
319
+ temp_df["送股"] = "-"
320
+ if "转增" not in temp_df.columns:
321
+ temp_df["转增"] = "-"
322
+
323
+ # 选择需要的列
324
+ temp_df = temp_df[
325
+ [
326
+ "股票代码",
327
+ "除权日",
328
+ "分红",
329
+ "送股",
330
+ "转增",
331
+ "实物",
332
+ "交易所",
333
+ "股票简称",
334
+ "报告期",
335
+ ]
336
+ ]
337
+
338
+ # 日期格式转换
339
+ if "除权日" in temp_df.columns:
340
+ temp_df["除权日"] = pd.to_datetime(temp_df["除权日"], errors="coerce").dt.date
341
+ if "报告期" in temp_df.columns:
342
+ temp_df["报告期"] = pd.to_datetime(temp_df["报告期"], errors="coerce").dt.date
135
343
 
344
+ return temp_df
136
345
 
137
- def news_trade_notify_dividend_baidu(date: str = "20240621") -> pd.DataFrame:
346
+
347
+ def news_trade_notify_dividend_baidu(date: str = "20251126", cookie: str = None) -> pd.DataFrame:
138
348
  """
139
349
  百度股市通-交易提醒-分红派息
140
350
  https://gushitong.baidu.com/calendar
141
- :param date: 查询日期
142
- :type date: str
143
- :return: 交易提醒-分红派息
144
- :rtype: pandas.DataFrame
351
+ :param date: 查询日期 (格式: YYYYMMDD)
352
+ :param cookie: cookie
353
+ :return: 交易提醒-分红派息DataFrame
145
354
  """
146
- start_date = "-".join([date[:4], date[4:6], date[6:]])
147
- end_date = "-".join([date[:4], date[4:6], date[6:]])
148
- conn = http.client.HTTPSConnection("finance.pae.baidu.com")
149
- params = {
150
- "start_date": start_date,
151
- "end_date": end_date,
152
- "market": "",
153
- "cate": "notify_divide",
154
- "rn": 500,
155
- "pn": 0,
355
+ return _baidu_finance_calendar(
356
+ date=date,
357
+ cate="notify_divide",
358
+ process_func=_process_dividend_data,
359
+ cookie=cookie
360
+ )
361
+
362
+
363
+ def _process_report_data(data_list: list) -> pd.DataFrame:
364
+ """处理财报发行数据 - 根据实际JSON结构精确修正"""
365
+ if not data_list:
366
+ return pd.DataFrame()
367
+
368
+ # 创建DataFrame
369
+ temp_df = pd.DataFrame(data_list)
370
+
371
+ # 精确字段映射 (根据提供的JSON结构)
372
+ rename_dict = {
373
+ "code": "股票代码",
374
+ "name": "股票简称",
375
+ "exchange": "交易所",
376
+ "reportType": "财报类型",
377
+ "time": "发布时间",
378
+ "marketValue": "市值",
379
+ "capitalization": "总市值",
380
+ "date": "发布日期"
156
381
  }
157
- query_string = urlencode(params)
158
- url = "/api/financecalendar" + "?" + query_string
159
- conn.request(method="GET", url=url)
160
- r = conn.getresponse()
161
- data = r.read()
162
- data_json = json.loads(data)
163
- big_df = pd.DataFrame()
164
- for item in data_json["Result"]:
165
- if not item["list"] == []:
166
- temp_df = pd.DataFrame(item["list"])
167
- temp_df.rename(
168
- columns={
169
- "code": "股票代码",
170
- "market": "-",
171
- "exchange": "交易所",
172
- "name": "股票简称",
173
- "diviDate": "除权日",
174
- "date": "报告期",
175
- "diviCash": "分红",
176
- "shareDivide": "送股",
177
- "transfer": "转增",
178
- "physical": "实物",
179
- },
180
- inplace=True,
181
- )
182
- if "实物" not in temp_df.columns:
183
- temp_df["实物"] = pd.NA
184
- temp_df = temp_df[
185
- [
186
- "股票代码",
187
- "除权日",
188
- "分红",
189
- "送股",
190
- "转增",
191
- "实物",
192
- "交易所",
193
- "股票简称",
194
- "报告期",
195
- ]
196
- ]
197
- temp_df["除权日"] = pd.to_datetime(
198
- temp_df["除权日"], errors="coerce"
199
- ).dt.date
200
- temp_df["报告期"] = pd.to_datetime(
201
- temp_df["报告期"], errors="coerce"
202
- ).dt.date
203
- big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
204
- else:
205
- continue
206
- return big_df
382
+ temp_df.rename(columns=rename_dict, inplace=True)
383
+
384
+ # 确保必要列存在
385
+ if "财报类型" not in temp_df.columns:
386
+ temp_df["财报类型"] = "-"
387
+ if "发布时间" not in temp_df.columns:
388
+ temp_df["发布时间"] = "-"
389
+ if "市值" not in temp_df.columns and "总市值" in temp_df.columns:
390
+ temp_df["市值"] = temp_df["总市值"]
207
391
 
392
+ # 选择并排序列
393
+ available_cols = []
394
+ for col in ["股票代码", "股票简称", "交易所", "财报类型", "发布时间", "市值", "发布日期"]:
395
+ if col in temp_df.columns:
396
+ available_cols.append(col)
208
397
 
209
- def news_report_time_baidu(date: str = "20220514") -> pd.DataFrame:
398
+ if available_cols:
399
+ temp_df = temp_df[available_cols]
400
+ else:
401
+ # 如果没有匹配的列,返回空DataFrame
402
+ return pd.DataFrame()
403
+
404
+ # 类型转换
405
+ if "市值" in temp_df.columns:
406
+ temp_df["市值"] = pd.to_numeric(temp_df["市值"], errors="coerce")
407
+
408
+ if "发布日期" in temp_df.columns:
409
+ temp_df["发布日期"] = pd.to_datetime(temp_df["发布日期"], errors="coerce").dt.date
410
+
411
+ return temp_df
412
+
413
+
414
+ def news_report_time_baidu(date: str = "20251126", cookie: str = None) -> pd.DataFrame:
210
415
  """
211
416
  百度股市通-财报发行
212
417
  https://gushitong.baidu.com/calendar
213
- :param date: 查询日期
214
- :type date: str
215
- :return: 财报发行
216
- :rtype: pandas.DataFrame
418
+ :param date: 查询日期 (格式: YYYYMMDD)
419
+ :param cookie: cookie
420
+ :return: 财报发行DataFrame
217
421
  """
218
- start_date = "-".join([date[:4], date[4:6], date[6:]])
219
- end_date = "-".join([date[:4], date[4:6], date[6:]])
220
- url = "https://finance.pae.baidu.com/api/financecalendar"
221
- params = {
222
- "start_date": start_date,
223
- "end_date": end_date,
224
- "market": "",
225
- "cate": "report_time",
226
- "finClientType": "pc",
227
- }
228
- r = requests.get(url, params=params)
229
- data_json = r.json()
230
- big_df = pd.DataFrame()
231
- for item in data_json["Result"]:
232
- if not item["list"] == []:
233
- temp_df = pd.DataFrame(item["list"])
234
- temp_df.columns = [
235
- "股票代码",
236
- "-",
237
- "交易所",
238
- "-",
239
- "股票简称",
240
- "-",
241
- "财报期",
242
- ]
243
- temp_df = temp_df[
244
- [
245
- "股票代码",
246
- "交易所",
247
- "股票简称",
248
- "财报期",
249
- ]
250
- ]
251
- big_df = pd.concat(objs=[big_df, temp_df], ignore_index=True)
252
- else:
253
- continue
254
- return big_df
422
+ return _baidu_finance_calendar(
423
+ date=date,
424
+ cate="report_time",
425
+ process_func=_process_report_data,
426
+ cookie=cookie
427
+ )
255
428
 
256
429
 
257
430
  if __name__ == "__main__":
258
- news_economic_baidu_df = news_economic_baidu(date="20240326")
431
+ news_economic_baidu_df = news_economic_baidu(date="20251126")
259
432
  print(news_economic_baidu_df)
260
433
 
261
434
  news_trade_notify_suspend_baidu_df = news_trade_notify_suspend_baidu(
262
- date="20240327"
435
+ date="20251126"
263
436
  )
264
437
  print(news_trade_notify_suspend_baidu_df)
265
438
 
266
439
  news_trade_notify_dividend_baidu_df = news_trade_notify_dividend_baidu(
267
- date="20240621"
440
+ date="20251126"
268
441
  )
269
442
  print(news_trade_notify_dividend_baidu_df)
270
443
 
271
- news_report_time_baidu_df = news_report_time_baidu(date="20240326")
444
+ news_report_time_baidu_df = news_report_time_baidu(date="20251126")
272
445
  print(news_report_time_baidu_df)