爬虫技术选股:Python 自动化筛选潜力股

一、核心技术栈与前期准备

1. 核心技术工具说明

本次自动化选股项目依赖 Python 的三大核心库,各自承担关键职责:

  • Requests:轻量高效的 HTTP 请求库,负责向金融数据网站发送请求,获取公开的个股行情与财务数据,是爬虫实现的核心工具。
  • BeautifulSoup4:强大的网页解析库,能够将 Requests 获取的杂乱 HTML 页面解析为结构化数据,方便提取我们需要的股票代码、营收、净利润等核心信息。
  • Pandas:高性能的数据处理与分析库,负责对提取的金融数据进行清洗、整理、指标计算与筛选,是实现选股逻辑的关键支撑。

2. 前期环境搭建

其中<font style="color:rgb(0, 0, 0);background-color:rgba(0, 0, 0, 0);">lxml</font>是 BeautifulSoup4 的高效解析器,能够提升网页解析速度,建议一并安装。

同时需要说明:本文选取东方财富网公开的股票数据作为抓取来源(公开非付费数据),仅用于技术学习与研究,不构成任何投资建议。金融数据具有实时性与波动性,实际投资中需结合更多专业信息进行判断。

二、项目实现流程概述

本次 Python 自动化选股的核心流程分为四步:

  1. 爬虫搭建:抓取 A 股市场个股的基础信息(股票代码、名称)与核心财务 / 行情数据(每股收益、净利润增长率、市盈率、市净率等);
  2. 数据清洗:处理抓取到的缺失值、异常值、格式错误等问题,形成标准化数据集;
  3. 选股逻辑实现:基于价值投资与成长投资的核心指标,预设筛选规则,利用 Pandas 完成自动化筛选;
  4. 结果输出:将筛选出的潜力股整理为表格,保存为本地文件方便查阅。

三、完整代码实现与分步解析

步骤 1:导入所需库

首先导入项目依赖的所有 Python 库,并进行基础配置(如请求头设置,避免被网站反爬拦截)。

python

运行

plain 复制代码
import requests
from bs4 import BeautifulSoup
import pandas as pd

# 配置请求头,模拟浏览器访问,避免被网站反爬
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
}

步骤 2:抓取股票基础数据与核心指标

本次我们抓取东方财富网的 A 股列表数据,提取核心选股指标。为了保证代码可运行性,我们先抓取个股列表页面,再批量提取关键数据(注:因网站反爬机制限制,本文采用简化版抓取逻辑,避免高频请求触发拦截)。

python

运行

plain 复制代码
import requests
from bs4 import BeautifulSoup
import pandas as pd

# 配置请求头,模拟浏览器访问,避免被网站反爬
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
}

def get_stock_data():
    """
    抓取A股个股核心数据,返回结构化列表
    """
    # 配置代理信息(指定的代理参数)
    proxyHost = "www.16yun.cn"
    proxyPort = "5445"
    proxyUser = "16QMSOML"
    proxyPass = "280651"
    
    # 构建代理认证字符串,格式:用户名:密码@代理地址:端口
    proxy_auth = f"{proxyUser}:{proxyPass}@{proxyHost}:{proxyPort}"
    
    # 配置proxies字典,支持http和https协议(金融网站可能同时存在两种协议)
    proxies = {
        "http": f"http://{proxy_auth}",
        "https": f"https://{proxy_auth}"
    }
    
    # 东方财富网A股列表简化页面(仅用于技术演示,实际可扩展为全量个股)
    url = 'http://quote.eastmoney.com/stock/list.html'
    try:
        # 发送GET请求,添加proxies参数配置代理
        response = requests.get(url, headers=headers, proxies=proxies, timeout=10)
        response.raise_for_status()  # 抛出请求异常(4xx/5xx)
        response.encoding = 'utf-8'  # 统一编码格式,避免中文乱码
        
        # 利用BeautifulSoup解析网页内容
        soup = BeautifulSoup(response.text, 'lxml')
        
        # 初始化存储股票数据的列表
        stock_list = []
        
        # 定位股票数据节点(根据网页结构调整,此处为简化版)
        stock_items = soup.find_all('li', class_='stock-item')
        
        for item in stock_items[:100]:  # 截取前100只股票,避免高频请求
            try:
                # 提取股票代码与名称
                stock_code = item.find('a').get('data-code', '')
                stock_name = item.find('a').get_text(strip=True, separator='').split()[0]
                
                # 跳转到个股详情页,抓取核心财务/行情指标
                detail_url = f'http://quote.eastmoney.com/{stock_code}.html'
                # 详情页请求同样添加proxies参数,使用相同代理
                detail_response = requests.get(detail_url, headers=headers, proxies=proxies, timeout=8)
                detail_response.encoding = 'utf-8'
                detail_soup = BeautifulSoup(detail_response.text, 'lxml')
                
                # 提取关键指标:每股收益(EPS)、净利润增长率、市盈率(PE)、市净率(PB)
                eps = detail_soup.find('span', class_='eps').get_text(strip=True, default='0.00')
                profit_growth = detail_soup.find('span', class_='profit-growth').get_text(strip=True, default='0.00')
                pe = detail_soup.find('span', class_='pe').get_text(strip=True, default='0.00')
                pb = detail_soup.find('span', class_='pb').get_text(strip=True, default='0.00')
                
                # 整理单只股票数据
                stock_info = {
                    '股票代码': stock_code,
                    '股票名称': stock_name,
                    '每股收益(EPS)': float(eps.replace('%', '').replace('-', '0')),
                    '净利润增长率(%)': float(profit_growth.replace('%', '').replace('-', '0')),
                    '市盈率(PE)': float(pe.replace('%', '').replace('-', '0')),
                    '市净率(PB)': float(pb.replace('%', '').replace('-', '0'))
                }
                
                stock_list.append(stock_info)
                
            except Exception as e:
                # 忽略单只股票抓取异常,继续处理下一只
                continue
        
        return stock_list
        
    except Exception as e:
        print(f'数据抓取失败:{str(e)}')
        return []

步骤 3:数据清洗与标准化处理

抓取到的原始数据可能存在缺失值、格式异常等问题,需要通过 Pandas 进行清洗,确保后续筛选逻辑的准确性。

python

运行

plain 复制代码
def clean_stock_data(stock_list):
    """
    数据清洗:处理缺失值、异常值,标准化数据集
    """
    # 将列表转换为Pandas DataFrame,方便数据处理
    df = pd.DataFrame(stock_list)
    
    if df.empty:
        print('无有效股票数据可供清洗')
        return pd.DataFrame()
    
    # 1. 处理缺失值:删除完全缺失的行,填充部分缺失值为0
    df = df.dropna(how='all')
    df = df.fillna(0.0)
    
    # 2. 处理异常值:过滤指标明显不合理的数据(如PE为负数、PB过大)
    df = df[df['市盈率(PE)'] > 0]  # 过滤亏损或异常市盈率个股
    df = df[df['市盈率(PE)'] < 100]  # 过滤超高市盈率个股,避免泡沫标的
    df = df[df['市净率(PB)'] < 10]  # 过滤超高市净率个股
    
    # 3. 重置索引,方便后续查看
    df = df.reset_index(drop=True)
    
    print(f'数据清洗完成,剩余有效股票数量:{len(df)}')
    return df

步骤 4:预设选股逻辑,实现自动化筛选

选股逻辑是自动化选股的核心,本文结合价值投资的经典指标,预设以下筛选规则(可根据个人投资风格调整):

  1. 每股收益(EPS)> 0.3 元(反映个股盈利能力较强);
  2. 净利润增长率 > 10%(反映个股具备持续成长潜力);
  3. 市盈率(PE)在 0-50 之间(估值合理,无明显泡沫);
  4. 市净率(PB)在 0-5 之间(资产估值合理,风险较低)。

python

运行

plain 复制代码
def screen_potential_stocks(df):
    """
    基于预设指标筛选潜力股
    """
    if df.empty:
        print('无有效数据可供筛选')
        return pd.DataFrame()
    
    # 应用预设筛选规则,进行条件筛选
    potential_stocks = df[
        (df['每股收益(EPS)'] > 0.3) &
        (df['净利润增长率(%)'] > 10.0) &
        (df['市盈率(PE)'] > 0) &
        (df['市盈率(PE)'] < 50) &
        (df['市净率(PB)'] > 0) &
        (df['市净率(PB)'] < 5)
    ].copy()
    
    # 按净利润增长率降序排序,优先展示成长能力更强的个股
    potential_stocks = potential_stocks.sort_values(by='净利润增长率(%)', ascending=False)
    
    # 重置索引
    potential_stocks = potential_stocks.reset_index(drop=True)
    
    return potential_stocks

步骤 5:结果输出与本地保存

将筛选出的潜力股整理为表格,并保存为本地 Excel 文件,方便后续查阅与分析。

python

运行

plain 复制代码
def export_stock_result(potential_stocks):
    """
    输出筛选结果,保存为本地Excel文件
    """
    if potential_stocks.empty:
        print('未筛选出符合条件的潜力股')
        return
    
    print(f'本次共筛选出 {len(potential_stocks)} 只潜力股,具体列表如下:')
    print('-' * 80)
    print(potential_stocks)
    
    # 保存为本地Excel文件(需安装openpyxl库,支持xlsx格式)
    try:
        potential_stocks.to_excel('潜力股筛选结果.xlsx', index=False, engine='openpyxl')
        print('-' * 80)
        print('潜力股数据已成功保存为:潜力股筛选结果.xlsx')
    except Exception as e:
        print(f'文件保存失败:{str(e)}')
        # 备选:保存为CSV文件
        potential_stocks.to_csv('潜力股筛选结果.csv', index=False, encoding='utf-8-sig')
        print('潜力股数据已备选保存为:潜力股筛选结果.csv')

四、关键注意事项与优化方向

1. 反爬机制规避

金融网站普遍具备反爬机制,直接高频请求容易被封禁 IP,实际使用中需注意:

  • 增加请求延时:在循环抓取中加入<font style="color:rgb(0, 0, 0);background-color:rgba(0, 0, 0, 0);">time.sleep(1-3)</font>,降低请求频率;
  • 使用代理 IP 池:对于全量个股抓取,可配置代理 IP 轮换,避免单一 IP 被拦截;
  • 尊重网站<font style="color:rgb(0, 0, 0);background-color:rgba(0, 0, 0, 0);">robots.txt</font>协议:不抓取付费数据与禁止爬取的内容,遵守网络爬虫伦理;
  • 缓存已抓取数据:避免重复抓取同一页面,减轻网站服务器压力。

2. 选股逻辑优化

本文预设的选股逻辑为基础版本,实际投资中可根据需求扩展:

  • 增加更多财务指标:资产负债率、毛利率、现金流净额等;
  • 加入行情趋势指标:5 日均线、20 日均线、成交量增长率等;
  • 引入量化模型:结合均线策略、估值模型等,提升筛选准确性;
  • 支持行业细分:按行业筛选龙头股,避免跨行业估值差异带来的误差。

3. 代码功能扩展

  • 实现定时运行:利用<font style="color:rgb(0, 0, 0);background-color:rgba(0, 0, 0, 0);">APScheduler</font>库设置每日收盘后自动抓取数据、筛选个股;
  • 增加数据可视化:利用<font style="color:rgb(0, 0, 0);background-color:rgba(0, 0, 0, 0);">Matplotlib</font>/<font style="color:rgb(0, 0, 0);background-color:rgba(0, 0, 0, 0);">Seaborn</font>绘制个股指标分布图、成长趋势图;
  • 对接金融 API:对于高精度数据需求,可对接合规金融数据 API(如 Tushare、JoinQuant),提升数据质量与稳定性。

五、总结

本文通过 Python 的 Requests、BeautifulSoup4 与 Pandas 三大核心库,实现了一套完整的自动化选股流程,从公开金融数据抓取到标准化清洗,再到基于价值投资指标的潜力股筛选,最终完成结果输出与本地保存。这套流程不仅大幅提升了选股效率,还避免了人工选股的主观疏漏,为普通投资者和量化交易爱好者提供了可行的技术方案。

相关推荐
悟能不能悟2 小时前
jasper里面$F和$P的区别
开发语言·后端
辰风沐阳2 小时前
JavaScript 的 WebSocket 使用指南
开发语言·javascript·websocket
独自破碎E2 小时前
【前序+中序】重建二叉树
java·开发语言
践行见远2 小时前
django之认证与权限
python·django
2301_765715142 小时前
C语言轮子制造
c语言·开发语言·制造
量子炒饭大师2 小时前
【C++入门】Cyber骇客的同名异梦——【C++重载函数】(与C的函数差异)
c语言·开发语言·c++·函数重载
charlie1145141912 小时前
现代嵌入式C++教程:if constexpr——把编译期分支写得像写注释 —— 工程味实战指南
开发语言·c++·笔记·学习·嵌入式·现代c++
冰暮流星2 小时前
javascript如何转换为字符串与布尔型
java·开发语言·javascript
LIZhang20162 小时前
c++ 转化句柄,解决多线程安全释放问题
开发语言·c++