Advertisement
Guest User

Untitled

a guest
Mar 27th, 2025
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.81 KB | None | 0 0
  1. import pandas as pd
  2. import requests
  3. import os
  4. import time
  5. import json
  6.  
  7.  
  8. # ======================== 用户配置区域 ========================
  9. EXCEL_PATH = r"C:\Users\a\Desktop\沪港通企业列表.xlsx"        # Excel文件路径
  10. CODE_COLUMN = '股票代码'               # 代码列名
  11. START_DATE = '2014-11-27'             # 开始日期(YYYY-MM-DD)
  12. END_DATE = '2015-06-30'               # 结束日期
  13. REPORT_TYPES = {
  14.     '定期报告': ('00', '00'),
  15.     '其他': ('90', '90'),
  16. }
  17. SAVE_PATH = r'D:/SSE_Reports/'  # 路径斜杠方向保持统一       # 存储路径
  18. # ============================================================
  19.  
  20. HEADERS = {
  21.     'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/133.0.0.0',
  22.     'Referer': 'https://www.sse.com.cn/disclosure/listedinfo/announcement/'
  23. }
  24.  
  25. # 新版接口参数模板(网页1)
  26. BASE_PARAMS = {
  27.     'jsonCallBack': 'jsonpCallback',
  28.     'isPagination': 'true',
  29.     'securityType': '0101,120100,020100,020200,120200',  # 证券类型组合(网页1)
  30.     'pageSize': 100,
  31.     'pageNo': 1,
  32.     '_': int(time.time()*1000)
  33. }
  34.  
  35. def load_codes():
  36.     """加载股票代码(带格式校验)"""
  37.     try:
  38.         df = pd.read_excel(EXCEL_PATH)
  39.         df[CODE_COLUMN] = df[CODE_COLUMN].astype(str).str.strip().str.zfill(6)
  40.         valid_codes = df[df[CODE_COLUMN].str.match('^\d{6}$')][CODE_COLUMN].tolist()
  41.         print(f'加载到有效股票代码 {len(valid_codes)} 个')
  42.         return valid_codes
  43.     except Exception as e:
  44.         print(f'文件读取失败: {str(e)}')
  45.         exit()
  46.  
  47. def get_reports(code):
  48.     """获取报告列表(新版分页逻辑)"""
  49.     all_reports = []
  50.     current_page = 1
  51.    
  52.     while True:
  53.         params = {
  54.             **BASE_PARAMS,
  55.             'productId': code,
  56.             'reportType': REPORT_TYPES['定期报告'][0],
  57.             'reportType2': REPORT_TYPES['其他'][1],
  58.             'beginDate': START_DATE.replace('-', ''),
  59.             'endDate': END_DATE.replace('-', ''),
  60.             'pageNo': current_page
  61.         }
  62.        
  63.         try:
  64.             response = requests.get(
  65.                 'http://query.sse.com.cn/security/stock/queryCompanyBulletin.do',
  66.                 headers=HEADERS,
  67.                 params=params,
  68.                 timeout=15
  69.             )
  70.             data_str = response.text.split('jsonpCallback(')[1].strip(')')
  71.             data = json.loads(data_str)
  72.            
  73.             if 'result' in data and data['result']:
  74.                 all_reports.extend(data['result'])
  75.                 if data['pageHelp']['pageNo'] >= data['pageHelp']['pageCount']:
  76.                     break
  77.                 current_page += 1
  78.             else:
  79.                 break
  80.                
  81.         except Exception as e:
  82.             print(f"获取{code}失败: {str(e)}")
  83.             break
  84.            
  85.     return all_reports
  86.  
  87. def download_file(url, save_path):
  88.     """新版文件下载(带SSL验证)"""
  89.     try:
  90.         response = requests.get(
  91.             f'http://static.sse.com.cn{url}',  # PDF路径规则(网页1)
  92.             headers=HEADERS,
  93.             stream=True,
  94.             verify=True  # 启用SSL验证
  95.         )
  96.         with open(save_path, 'wb') as f:
  97.             for chunk in response.iter_content(2048):
  98.                 f.write(chunk)
  99.         return True
  100.     except Exception as e:
  101.         print(f"下载失败: {str(e)}")
  102.         return False
  103.  
  104. def main():
  105.     codes = load_codes()
  106.     os.makedirs(SAVE_PATH, exist_ok=True)
  107.    
  108.     for idx, code in enumerate(codes, 1):
  109.         print(f"\n正在处理 [{idx}/{len(codes)}] {code}")
  110.        
  111.         reports = get_reports(code)
  112.         if not reports:
  113.             print(f"{code} 未找到报告")
  114.             continue
  115.            
  116.         valid_reports = [
  117.             r for r in reports
  118.             if any(r['TITLE'].startswith(rt[0]) for rt in REPORT_TYPES.values())
  119.         ]
  120.        
  121.         print(f"发现 {len(valid_reports)} 份合规报告")
  122.         success = 0
  123.        
  124.         for report in valid_reports:
  125.             file_name = f"{code}_{report['TITLE'].replace(':', '')}.pdf"
  126.             save_path = os.path.join(SAVE_PATH, file_name)
  127.            
  128.             if not os.path.exists(save_path):
  129.                 if download_file(report['URL'], save_path):
  130.                     success += 1
  131.                     time.sleep(1.5)  # 反爬间隔
  132.                 else:
  133.                     print(f"重试下载: {file_name}")
  134.                     time.sleep(3)
  135.                     download_file(report['URL'], save_path)  # 二次重试
  136.             else:
  137.                 print(f"已存在: {file_name}")
  138.                
  139.         print(f"完成下载 {success} 份报告")
  140.  
  141. if __name__ == '__main__':
  142.     main()
  143.  
Tags: Code
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement