用Python爬取A股股票代码与名称并存储到Excel的实战指南1. 环境准备与工具选择在开始爬取A股数据之前我们需要准备好Python开发环境和必要的第三方库。对于金融数据采集Python凭借其丰富的生态库成为首选工具。以下是核心工具链的选择依据Requests库轻量级HTTP请求库适合处理简单的网页抓取BeautifulSoup4HTML解析利器适合处理静态页面Pandas数据处理的瑞士军刀内置Excel读写功能Openpyxl专业处理Excel文件的库支持高级格式设置安装所需库的命令如下pip install requests beautifulsoup4 pandas openpyxl提示建议使用虚拟环境管理项目依赖避免与其他项目产生冲突2. 数据源分析与爬取策略2.1 目标网站选择A股股票数据可以从多个公开渠道获取常见的数据源包括数据源优点缺点东方财富网数据全面更新及时反爬机制较强新浪财经接口稳定结构清晰需要处理动态加载雪球网数据质量高需要登录获取完整数据交易所官网官方权威数据格式不够友好2.2 网页结构分析以东方财富网为例股票列表页通常具有以下特征分页显示每页约30条记录表格结构规整包含股票代码、名称等关键信息采用常规HTML结构无复杂动态加载示例页面结构分析table classtable-list tr td000001/td tda href/stock/000001.html平安银行/a/td !-- 其他数据列 -- /tr !-- 更多行数据 -- /table2.3 反爬应对方案金融网站通常会有基本的反爬措施我们需要做好以下准备请求头设置模拟浏览器访问访问频率控制添加合理延迟代理IP池应对IP封锁异常处理保证程序健壮性3. 核心代码实现3.1 基础爬取函数首先实现一个通用的网页抓取函数包含基本的反爬策略import requests from bs4 import BeautifulSoup import time import random def fetch_page(url, retry3): headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Accept-Language: zh-CN,zh;q0.9, } for attempt in range(retry): try: response requests.get(url, headersheaders, timeout10) response.raise_for_status() return response.text except requests.exceptions.RequestException as e: print(f请求失败: {e}, 重试 {attempt 1}/{retry}) time.sleep(random.uniform(1, 3)) raise Exception(f无法获取页面: {url}) def parse_stock_list(html): soup BeautifulSoup(html, html.parser) stocks [] # 根据实际网页结构调整选择器 rows soup.select(table.table-list tr) for row in rows[1:]: # 跳过表头 cols row.find_all(td) if len(cols) 2: code cols[0].text.strip() name cols[1].text.strip() stocks.append((code, name)) return stocks3.2 分页爬取逻辑A股股票数量超过4000只需要处理分页def crawl_all_stocks(base_url, max_pages50): all_stocks [] for page in range(1, max_pages 1): url f{base_url}?page{page} print(f正在抓取第 {page} 页...) try: html fetch_page(url) stocks parse_stock_list(html) if not stocks: break all_stocks.extend(stocks) time.sleep(random.uniform(0.5, 1.5)) # 随机延迟 except Exception as e: print(f第 {page} 页抓取失败: {e}) continue return all_stocks3.3 数据存储实现将爬取结果保存到Excel文件import pandas as pd def save_to_excel(stocks, filenamea_stocks.xlsx): df pd.DataFrame(stocks, columns[股票代码, 股票名称]) # 设置Excel写入参数 writer pd.ExcelWriter(filename, engineopenpyxl) df.to_excel(writer, indexFalse, sheet_nameA股列表) # 调整列宽 worksheet writer.sheets[A股列表] worksheet.column_dimensions[A].width 15 worksheet.column_dimensions[B].width 20 writer.save() print(f数据已保存到 {filename})4. 完整流程与异常处理4.1 主程序流程整合各模块形成完整工作流def main(): base_url http://quote.eastmoney.com/stock_list.html # 示例URL try: print(开始爬取A股股票列表...) start_time time.time() stocks crawl_all_stocks(base_url) if not stocks: raise Exception(未获取到任何股票数据) print(f共获取 {len(stocks)} 只股票数据) save_to_excel(stocks) elapsed time.time() - start_time print(f任务完成耗时 {elapsed:.2f} 秒) except KeyboardInterrupt: print(\n用户中断操作) except Exception as e: print(f程序运行出错: {e}) finally: print(程序结束) if __name__ __main__: main()4.2 常见问题解决方案在实际爬取过程中可能会遇到以下问题及对策IP被封禁解决方案使用代理IP轮换实现代码proxies { http: http://your_proxy:port, https: https://your_proxy:port } response requests.get(url, proxiesproxies)动态加载内容解决方案使用Selenium模拟浏览器示例from selenium import webdriver driver webdriver.Chrome() driver.get(url) html driver.page_source验证码识别解决方案使用第三方OCR服务或手动处理5. 数据清洗与增强5.1 基础数据清洗原始数据可能需要以下处理def clean_stock_data(stocks): cleaned [] for code, name in stocks: # 去除股票名称中的特殊标记 clean_name name.split(()[0].strip() # 验证股票代码格式 if len(code) 6 and code.isdigit(): cleaned.append((code, clean_name)) return cleaned5.2 数据增强实践可以为数据集添加更多有用信息股票类型分类沪市/深市def classify_stock(code): if code.startswith(6): return 沪市A股 elif code.startswith(0) or code.startswith(3): return 深市A股 return 其他行业分类信息可从其他接口获取行业数据并合并添加数据爬取时间戳df[更新时间] pd.Timestamp.now().strftime(%Y-%m-%d %H:%M)6. 项目优化与扩展6.1 性能优化技巧多线程爬取from concurrent.futures import ThreadPoolExecutor def crawl_page(page): url f{base_url}?page{page} return parse_stock_list(fetch_page(url)) with ThreadPoolExecutor(max_workers5) as executor: results list(executor.map(crawl_page, range(1, max_pages1)))增量更新机制记录上次爬取时间只抓取有变动的数据6.2 功能扩展方向定时自动更新使用APScheduler设置定时任务from apscheduler.schedulers.blocking import BlockingScheduler scheduler BlockingScheduler() scheduler.scheduled_job(cron, hour18) def daily_update(): main()数据可视化使用Matplotlib/Pyecharts生成股票分布图表对接数据库将数据存储到MySQL/MongoDB等数据库7. 完整代码示例以下是整合后的完整实现import requests from bs4 import BeautifulSoup import pandas as pd import time import random from typing import List, Tuple class AStockCrawler: def __init__(self): self.headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64), Accept: text/html,application/xhtmlxml, } def fetch_page(self, url: str) - str: try: response requests.get(url, headersself.headers, timeout15) response.raise_for_status() return response.text except requests.exceptions.RequestException as e: print(f请求失败: {e}) raise def parse_stocks(self, html: str) - List[Tuple[str, str]]: soup BeautifulSoup(html, html.parser) stocks [] # 示例选择器需根据实际网页调整 for row in soup.select(table.stock-table tbody tr): cols row.find_all(td) if len(cols) 2: code cols[0].text.strip() name cols[1].text.strip() stocks.append((code, name)) return stocks def crawl_all(self, base_url: str, max_pages: int 50) - List[Tuple[str, str]]: all_stocks [] for page in range(1, max_pages 1): url f{base_url}page{page} print(fProcessing page {page}...) try: html self.fetch_page(url) stocks self.parse_stocks(html) if not stocks: break all_stocks.extend(stocks) time.sleep(random.uniform(1, 2)) except Exception as e: print(fError on page {page}: {e}) continue return all_stocks def save_excel(self, stocks: List[Tuple[str, str]], filename: str stocks.xlsx): df pd.DataFrame(stocks, columns[代码, 名称]) df[交易所] df[代码].apply(lambda x: 沪市 if x.startswith(6) else 深市) with pd.ExcelWriter(filename, engineopenpyxl) as writer: df.to_excel(writer, indexFalse) # 设置单元格格式 workbook writer.book worksheet writer.sheets[Sheet1] # 设置列宽 worksheet.column_dimensions[A].width 12 worksheet.column_dimensions[B].width 20 worksheet.column_dimensions[C].width 10 print(f数据已保存到 {filename}) if __name__ __main__: crawler AStockCrawler() base_url http://example.com/stock_list try: print(开始爬取股票数据...) stocks crawler.crawl_all(base_url) if stocks: print(f共获取 {len(stocks)} 条股票数据) crawler.save_excel(stocks) else: print(未获取到有效数据) except Exception as e: print(f程序运行出错: {e})8. 实际应用建议合规性注意事项遵守网站的robots.txt规定控制请求频率避免对服务器造成压力考虑使用官方API替代爬虫如有提供维护建议定期检查选择器是否仍然有效建立监控机制及时发现爬取失败情况保留历史版本数据以便比对异常处理增强添加网络异常重试机制实现断点续爬功能记录详细的运行日志9. 替代方案比较当Python爬虫方案遇到困难时可以考虑以下替代方案方案优点缺点金融数据API稳定可靠数据规范通常有调用限制或收费现成数据集省时省力可能不是最新数据浏览器插件绕过部分反爬难以规模化专业爬虫框架功能强大学习成本高对于A股数据推荐优先考虑以下免费数据源Tushare Pro提供丰富的金融数据APIAKShare开源金融数据接口库Baostock无需注册的金融数据服务10. 项目结构优化对于长期维护的项目建议采用以下目录结构astock_crawler/ ├── core/ # 核心功能模块 │ ├── crawler.py # 爬虫主逻辑 │ ├── parser.py # 页面解析 │ └── storage.py # 数据存储 ├── config/ # 配置文件 │ └── settings.py # 全局配置 ├── utils/ # 工具函数 │ ├── logger.py # 日志处理 │ └── network.py # 网络请求 ├── data/ # 数据存储目录 ├── tests/ # 单元测试 └── main.py # 程序入口这种结构有利于代码的模块化和后期维护也方便团队协作开发。
用Python爬取A股股票代码与名称,并存入Excel的保姆级教程
用Python爬取A股股票代码与名称并存储到Excel的实战指南1. 环境准备与工具选择在开始爬取A股数据之前我们需要准备好Python开发环境和必要的第三方库。对于金融数据采集Python凭借其丰富的生态库成为首选工具。以下是核心工具链的选择依据Requests库轻量级HTTP请求库适合处理简单的网页抓取BeautifulSoup4HTML解析利器适合处理静态页面Pandas数据处理的瑞士军刀内置Excel读写功能Openpyxl专业处理Excel文件的库支持高级格式设置安装所需库的命令如下pip install requests beautifulsoup4 pandas openpyxl提示建议使用虚拟环境管理项目依赖避免与其他项目产生冲突2. 数据源分析与爬取策略2.1 目标网站选择A股股票数据可以从多个公开渠道获取常见的数据源包括数据源优点缺点东方财富网数据全面更新及时反爬机制较强新浪财经接口稳定结构清晰需要处理动态加载雪球网数据质量高需要登录获取完整数据交易所官网官方权威数据格式不够友好2.2 网页结构分析以东方财富网为例股票列表页通常具有以下特征分页显示每页约30条记录表格结构规整包含股票代码、名称等关键信息采用常规HTML结构无复杂动态加载示例页面结构分析table classtable-list tr td000001/td tda href/stock/000001.html平安银行/a/td !-- 其他数据列 -- /tr !-- 更多行数据 -- /table2.3 反爬应对方案金融网站通常会有基本的反爬措施我们需要做好以下准备请求头设置模拟浏览器访问访问频率控制添加合理延迟代理IP池应对IP封锁异常处理保证程序健壮性3. 核心代码实现3.1 基础爬取函数首先实现一个通用的网页抓取函数包含基本的反爬策略import requests from bs4 import BeautifulSoup import time import random def fetch_page(url, retry3): headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Accept-Language: zh-CN,zh;q0.9, } for attempt in range(retry): try: response requests.get(url, headersheaders, timeout10) response.raise_for_status() return response.text except requests.exceptions.RequestException as e: print(f请求失败: {e}, 重试 {attempt 1}/{retry}) time.sleep(random.uniform(1, 3)) raise Exception(f无法获取页面: {url}) def parse_stock_list(html): soup BeautifulSoup(html, html.parser) stocks [] # 根据实际网页结构调整选择器 rows soup.select(table.table-list tr) for row in rows[1:]: # 跳过表头 cols row.find_all(td) if len(cols) 2: code cols[0].text.strip() name cols[1].text.strip() stocks.append((code, name)) return stocks3.2 分页爬取逻辑A股股票数量超过4000只需要处理分页def crawl_all_stocks(base_url, max_pages50): all_stocks [] for page in range(1, max_pages 1): url f{base_url}?page{page} print(f正在抓取第 {page} 页...) try: html fetch_page(url) stocks parse_stock_list(html) if not stocks: break all_stocks.extend(stocks) time.sleep(random.uniform(0.5, 1.5)) # 随机延迟 except Exception as e: print(f第 {page} 页抓取失败: {e}) continue return all_stocks3.3 数据存储实现将爬取结果保存到Excel文件import pandas as pd def save_to_excel(stocks, filenamea_stocks.xlsx): df pd.DataFrame(stocks, columns[股票代码, 股票名称]) # 设置Excel写入参数 writer pd.ExcelWriter(filename, engineopenpyxl) df.to_excel(writer, indexFalse, sheet_nameA股列表) # 调整列宽 worksheet writer.sheets[A股列表] worksheet.column_dimensions[A].width 15 worksheet.column_dimensions[B].width 20 writer.save() print(f数据已保存到 {filename})4. 完整流程与异常处理4.1 主程序流程整合各模块形成完整工作流def main(): base_url http://quote.eastmoney.com/stock_list.html # 示例URL try: print(开始爬取A股股票列表...) start_time time.time() stocks crawl_all_stocks(base_url) if not stocks: raise Exception(未获取到任何股票数据) print(f共获取 {len(stocks)} 只股票数据) save_to_excel(stocks) elapsed time.time() - start_time print(f任务完成耗时 {elapsed:.2f} 秒) except KeyboardInterrupt: print(\n用户中断操作) except Exception as e: print(f程序运行出错: {e}) finally: print(程序结束) if __name__ __main__: main()4.2 常见问题解决方案在实际爬取过程中可能会遇到以下问题及对策IP被封禁解决方案使用代理IP轮换实现代码proxies { http: http://your_proxy:port, https: https://your_proxy:port } response requests.get(url, proxiesproxies)动态加载内容解决方案使用Selenium模拟浏览器示例from selenium import webdriver driver webdriver.Chrome() driver.get(url) html driver.page_source验证码识别解决方案使用第三方OCR服务或手动处理5. 数据清洗与增强5.1 基础数据清洗原始数据可能需要以下处理def clean_stock_data(stocks): cleaned [] for code, name in stocks: # 去除股票名称中的特殊标记 clean_name name.split(()[0].strip() # 验证股票代码格式 if len(code) 6 and code.isdigit(): cleaned.append((code, clean_name)) return cleaned5.2 数据增强实践可以为数据集添加更多有用信息股票类型分类沪市/深市def classify_stock(code): if code.startswith(6): return 沪市A股 elif code.startswith(0) or code.startswith(3): return 深市A股 return 其他行业分类信息可从其他接口获取行业数据并合并添加数据爬取时间戳df[更新时间] pd.Timestamp.now().strftime(%Y-%m-%d %H:%M)6. 项目优化与扩展6.1 性能优化技巧多线程爬取from concurrent.futures import ThreadPoolExecutor def crawl_page(page): url f{base_url}?page{page} return parse_stock_list(fetch_page(url)) with ThreadPoolExecutor(max_workers5) as executor: results list(executor.map(crawl_page, range(1, max_pages1)))增量更新机制记录上次爬取时间只抓取有变动的数据6.2 功能扩展方向定时自动更新使用APScheduler设置定时任务from apscheduler.schedulers.blocking import BlockingScheduler scheduler BlockingScheduler() scheduler.scheduled_job(cron, hour18) def daily_update(): main()数据可视化使用Matplotlib/Pyecharts生成股票分布图表对接数据库将数据存储到MySQL/MongoDB等数据库7. 完整代码示例以下是整合后的完整实现import requests from bs4 import BeautifulSoup import pandas as pd import time import random from typing import List, Tuple class AStockCrawler: def __init__(self): self.headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64), Accept: text/html,application/xhtmlxml, } def fetch_page(self, url: str) - str: try: response requests.get(url, headersself.headers, timeout15) response.raise_for_status() return response.text except requests.exceptions.RequestException as e: print(f请求失败: {e}) raise def parse_stocks(self, html: str) - List[Tuple[str, str]]: soup BeautifulSoup(html, html.parser) stocks [] # 示例选择器需根据实际网页调整 for row in soup.select(table.stock-table tbody tr): cols row.find_all(td) if len(cols) 2: code cols[0].text.strip() name cols[1].text.strip() stocks.append((code, name)) return stocks def crawl_all(self, base_url: str, max_pages: int 50) - List[Tuple[str, str]]: all_stocks [] for page in range(1, max_pages 1): url f{base_url}page{page} print(fProcessing page {page}...) try: html self.fetch_page(url) stocks self.parse_stocks(html) if not stocks: break all_stocks.extend(stocks) time.sleep(random.uniform(1, 2)) except Exception as e: print(fError on page {page}: {e}) continue return all_stocks def save_excel(self, stocks: List[Tuple[str, str]], filename: str stocks.xlsx): df pd.DataFrame(stocks, columns[代码, 名称]) df[交易所] df[代码].apply(lambda x: 沪市 if x.startswith(6) else 深市) with pd.ExcelWriter(filename, engineopenpyxl) as writer: df.to_excel(writer, indexFalse) # 设置单元格格式 workbook writer.book worksheet writer.sheets[Sheet1] # 设置列宽 worksheet.column_dimensions[A].width 12 worksheet.column_dimensions[B].width 20 worksheet.column_dimensions[C].width 10 print(f数据已保存到 {filename}) if __name__ __main__: crawler AStockCrawler() base_url http://example.com/stock_list try: print(开始爬取股票数据...) stocks crawler.crawl_all(base_url) if stocks: print(f共获取 {len(stocks)} 条股票数据) crawler.save_excel(stocks) else: print(未获取到有效数据) except Exception as e: print(f程序运行出错: {e})8. 实际应用建议合规性注意事项遵守网站的robots.txt规定控制请求频率避免对服务器造成压力考虑使用官方API替代爬虫如有提供维护建议定期检查选择器是否仍然有效建立监控机制及时发现爬取失败情况保留历史版本数据以便比对异常处理增强添加网络异常重试机制实现断点续爬功能记录详细的运行日志9. 替代方案比较当Python爬虫方案遇到困难时可以考虑以下替代方案方案优点缺点金融数据API稳定可靠数据规范通常有调用限制或收费现成数据集省时省力可能不是最新数据浏览器插件绕过部分反爬难以规模化专业爬虫框架功能强大学习成本高对于A股数据推荐优先考虑以下免费数据源Tushare Pro提供丰富的金融数据APIAKShare开源金融数据接口库Baostock无需注册的金融数据服务10. 项目结构优化对于长期维护的项目建议采用以下目录结构astock_crawler/ ├── core/ # 核心功能模块 │ ├── crawler.py # 爬虫主逻辑 │ ├── parser.py # 页面解析 │ └── storage.py # 数据存储 ├── config/ # 配置文件 │ └── settings.py # 全局配置 ├── utils/ # 工具函数 │ ├── logger.py # 日志处理 │ └── network.py # 网络请求 ├── data/ # 数据存储目录 ├── tests/ # 单元测试 └── main.py # 程序入口这种结构有利于代码的模块化和后期维护也方便团队协作开发。