Java量化系列(五):实现股票详细信息实时获取

在第四篇文章中,我们完成了自选股票维护功能,用户已能便捷管理核心关注标的。但对量化交易者而言,仅维护自选列表远远不够------还需实时掌握单只股票的关键信息,比如当前价格、涨跌幅度、成交量、市盈率等,这些数据是判断标的短期走势、执行策略信号的核心依据。

本文作为Java量化系列的第五篇,将聚焦"股票详细信息获取"模块,基于SpringBoot技术栈,实现两大核心目标:一是定义统一的股票详情数据模型(StockShowInfoDto),兼容不同数据源的字段映射;二是对接财联社、腾讯两大公开数据源,实现股票详情信息的实时爬取、解析与封装。同时会复用系列第三篇中的历史数据爬取基础代码,保证系统代码的复用性与一致性,适合有一定Java爬虫与量化开发基础的工程师参考。

一、核心需求与数据模型设计

1.1 核心需求边界

股票详细信息获取的核心诉求是"实时性""完整性""兼容性",结合量化交易场景,明确需求边界如下:

  • 数据完整性:覆盖股票基础信息(代码、名称、全代码、交易所类型)、行情数据(开盘价、收盘价、最高价、最低价、当前价)、交易数据(成交量、成交金额、换手率、量比)、估值数据(市盈率)、辅助判断数据(涨跌幅度、是否涨停);
  • 多数据源兼容:对接财联社、腾讯两大数据源,支持数据源切换(避免单一数据源失效导致功能不可用);
  • 实时性保障:通过HTTP请求实时爬取数据源接口,确保获取的是最新行情数据(非历史缓存);
  • 自动计算与封装:部分字段(如涨停状态、涨跌幅度百分比)需基于原始数据自动计算,简化上层调用;
  • 异常兼容:爬取失败时返回null并记录日志,支持后续降级处理(如切换备用数据源)。

1.2 核心数据模型:StockShowInfoDto

为统一不同数据源的返回格式,定义StockShowInfoDto作为股票详细信息的标准输出模型,包含基础信息、行情数据、交易数据等全量字段,并通过自定义getter方法实现部分字段的自动计算(如涨停状态、涨跌幅度百分比转换)。

核心代码实现:

复制代码
@Data
@Schema(description = "股票展示信息")
public class StockShowInfoDto implements Serializable {
    /** 股票的代码(如001318) */
    @Schema(description = "股票的代码")
    private String code;

    /** 股票的名称(如三峡能源) */
    @Schema(description = "股票的名称")
    private String name;

    /** 当前查询日期 */
    @Schema(description = "日期")
    private String currDate;

    /** 股票的全代码(如sz001318、sh600000) */
    @Schema(description = "股票的全代码")
    private String fullCode;

    /** 交易所类型(0-未知/1-深交所/2-上交所,可自定义) */
    @Schema(description = "交易所类型")
    private Integer exchange;

    /** 行情日期(当日) */
    @Schema(description = "当前天")
    private String date;

    /** 开盘价 */
    @Schema(description = "开盘价")
    private BigDecimal openingPrice;

    /** 昨天的收盘价 */
    @Schema(description = "昨天的收盘价")
    private BigDecimal yesClosingPrice;

    /** 最高价格 */
    @Schema(description = "最高价格")
    private BigDecimal highestPrice;

    /** 最低价格 */
    @Schema(description = "最低价格")
    private BigDecimal lowestPrice;

    /** 收盘价(盘后有效,盘中取当前价) */
    @Schema(description = "收盘价")
    private BigDecimal closingPrice;

    /** 当前的价格(盘中实时价格) */
    @Schema(description = "当前的价格")
    private BigDecimal nowPrice;

    /** 成交量(股) */
    @Schema(description = "成交量(股)")
    private long tradingVolume;

    /** 成交量金额(元) */
    @Schema(description = "成交量金额")
    private BigDecimal tradingValue;

    /** 涨跌幅度(当前价-昨日收盘价) */
    @Schema(description = "涨跌幅度")
    private BigDecimal amplitude;

    /** 涨跌幅度百分比(带%符号,如+2.35%) */
    @Schema(description = "涨跌幅度百分比")
    private String amplitudeProportion;

    /** 换手率(%) */
    @Schema(description = "换手率")
    private BigDecimal changingProportion;

    /** 量比 */
    @Schema(description = "量比")
    private BigDecimal than;

    /** 市盈率(TTM) */
    @Schema(description = "市盈率")
    private BigDecimal peRatio;

    /** 是否涨停(1-涨停/0-不涨停,自动计算) */
    @Schema(description = "是否涨停 1为涨停 0为不涨停")
    private Integer zt = 0;

    /** 涨跌幅度百分比(double形式,用于计算,如2.35) */
    @Schema(description = "涨幅 double形式")
    private Double amplitudeProportionDouble;

    /** 数据源网页地址(辅助信息) */
    @Schema(description = "webUrl地址信息")
    private String webUrl;

    /**
     * 自动计算是否涨停:调用StockUtil工具类判断
     * 核心逻辑:根据股票代码(区分主板/创业板/科创板)、当前涨幅判断
     */
    public Integer getZt() {
        return StockUtil.isZt(this.code, this.name, this.amplitudeProportion) ? 1 : 0;
    }

    /**
     * 自动转换涨跌幅度百分比为double:去除%符号,转为数值型
     * 示例:"2.35%" → 2.35,空值返回0.0
     */
    public Double getAmplitudeProportionDouble() {
        if (StrUtil.isBlank(amplitudeProportion)) {
            return 0.0d;
        }
        String substring = amplitudeProportion.replace("%", "");
        return Double.parseDouble(substring);
    }
}

关键设计亮点:

  • 自动计算字段:通过自定义getter方法实现zt(涨停状态)和amplitudeProportionDouble(涨跌幅度double值)的自动计算,无需上层代码处理,简化调用;
  • 字段兼容性:兼顾不同数据源的字段差异(如财联社返回"last_px"表示当前价,腾讯返回"nowPrice"),通过DTO统一封装,屏蔽底层差异;
  • 辅助信息字段:fullCode(全代码)用于数据源接口调用,webUrl用于记录数据源地址,便于问题排查。

二、核心设计:多数据源架构与流程

2.1 多数据源架构设计

为避免单一数据源失效导致功能不可用,设计"主备数据源"架构:以财联社作为主数据源(数据字段更完整,包含市盈率、量比等关键估值数据),腾讯作为备用数据源(接口稳定性高,适合降级使用)。核心架构如下:

复制代码
上层调用 → 数据源选择器 → 主数据源(财联社)爬取 → 解析封装 → 结果返回;主数据源失败 → 自动切换备用数据源(腾讯) → 解析封装 → 结果返回;均失败 → 返回null+日志记录

2.2 核心流程拆解

无论主备数据源,核心流程均遵循"参数校验 → 构建请求(URL+请求头) → 发送HTTP请求 → 解析响应数据 → DTO封装 → 自动计算字段 → 结果返回",差异仅在于请求URL、请求头、响应数据格式的解析逻辑。

三、核心实现:多数据源爬取与封装

下面分别拆解财联社(主数据源)和腾讯(备用数据源)的完整实现逻辑,包含请求构建、数据爬取、解析封装等关键步骤,同时说明代码复用要点(如复用第三篇的腾讯历史数据爬取基础方法)。

3.1 主数据源:财联社股票详情爬取实现

财联社提供公开的股票详情接口(URL格式: https://x-quote.cls.cn/quote/stock/basic?secu_code={0}\&fields=open_px,av_px,high_px,low_px,change,change_px,down_price,change_3,change_5,qrr,entrust_rate,tr,amp,TotalShares,mc,NetAssetPS,NonRestrictedShares,cmc,business_amount,business_balance,pe,ttm_pe,pb,secu_name,secu_code,trade_status,secu_type,preclose_px,up_price,last_px\&app=CailianpressWeb\&os=web\&sv=8.4.6\&sign=9f8797a1f4de66c2370f7a03990d2737),返回JSON格式数据,包含基础信息、行情数据、交易数据、估值数据等全量字段,适合作为主数据源。

3.1.1 核心依赖与工具类

需依赖HTTP工具类(HttpUtil)发送GET请求、JSON工具类(JSONUtil)解析响应数据、 BigDecimal工具类(BigDecimalUtil)处理数值计算,同时需配置财联社接口地址(通过配置文件注入,便于维护)。

3.1.2 完整代码实现

复制代码
@Service
public class StockDetailServiceImpl implements StockDetailService {

    @Override
    public StockShowInfoDto getByCode(String fullCode) {
        // 1. 参数校验:全代码不能为空(如sz001318、sh600000)
        if (StrUtil.isBlank(fullCode)) {
            log.error("财联社爬取股票详情失败:全代码为空");
            return null;
        }
        try {
            // 2. 构建请求URL:通过MessageFormat格式化占位符 
            String url = MessageFormat.format("https://x-quote.cls.cn/quote/stock/basic?secu_code={0}&fields=open_px,av_px,high_px,low_px,change,change_px,down_price,change_3,change_5,qrr,entrust_rate,tr,amp,TotalShares,mc,NetAssetPS,NonRestrictedShares,cmc,business_amount,business_balance,pe,ttm_pe,pb,secu_name,secu_code,trade_status,secu_type,preclose_px,up_price,last_px&app=CailianpressWeb&os=web&sv=8.4.6&sign=9f8797a1f4de66c2370f7a03990d2737", fullCode);
            // 3. 构建请求头:模拟浏览器请求,避免被反爬(关键:需设置User-Agent等请求头)
            Map<String, String> headerMap = buildDjrHeaderMap();
            // 4. 发送HTTP GET请求:使用无代理的CloseableHttpClient,避免代理失效问题
            String content = HttpUtil.sendGet(HttpClientConfig.proxyNoUseCloseableHttpClient(), url, headerMap);
            // 5. 解析响应数据:JSON格式转为JSONObject
            JSONObject jsonObject = JSONUtil.parseObj(content);
            // 6. 提取核心数据节点:响应数据中"data"字段为股票详情核心数据
            JSONObject data = jsonObject.getJSONObject("data");
            if (data == null) {
                log.error("财联社爬取股票详情失败:响应数据中data节点为空,fullCode={}", fullCode);
                return null;
            }
            // 7. DTO封装:将JSON数据映射到StockShowInfoDto
            StockShowInfoDto stockShowInfoDto = new StockShowInfoDto();
            // 基础信息封装
            stockShowInfoDto.setCode(StrUtil.subSufByLength(fullCode, 6)); // 从全代码中截取后6位作为股票代码(如sz001318→001318)
            stockShowInfoDto.setName(data.getStr("secu_name")); // 股票名称
            stockShowInfoDto.setCurrDate(DateUtil.now()); // 当前查询时间
            stockShowInfoDto.setFullCode(fullCode); // 全代码(保留原始参数)
            stockShowInfoDto.setDate(DateUtil.now()); // 行情日期(当日)
            stockShowInfoDto.setWebUrl("金亥跃江聊量化"); // 辅助信息:数据源标识
            // 行情数据封装(映射财联社响应字段)
            stockShowInfoDto.setOpeningPrice(data.getBigDecimal("open_px")); // 开盘价
            stockShowInfoDto.setYesClosingPrice(data.getBigDecimal("preclose_px")); // 昨日收盘价
            stockShowInfoDto.setHighestPrice(data.getBigDecimal("high_px")); // 最高价
            stockShowInfoDto.setLowestPrice(data.getBigDecimal("low_px")); // 最低价
            stockShowInfoDto.setClosingPrice(data.getBigDecimal("last_px")); // 收盘价(盘中取当前价)
            stockShowInfoDto.setNowPrice(data.getBigDecimal("last_px")); // 当前价
            // 交易数据封装
            stockShowInfoDto.setTradingVolume(data.getLong("business_amount")); // 成交量(股)
            stockShowInfoDto.setTradingValue(data.getBigDecimal("business_balance")); // 成交金额(元)
            stockShowInfoDto.setAmplitude(data.getBigDecimal("change_px")); // 涨跌幅度(当前价-昨日收盘价)
            // 数值计算与格式化:涨跌幅度百分比(乘以100,保留2位小数,加%符号)
            stockShowInfoDto.setAmplitudeProportion(BigDecimalUtil.mul100(data.getBigDecimal("change")));
            // 估值与辅助数据封装
            stockShowInfoDto.setChangingProportion(BigDecimalUtil.mul100B(data.getBigDecimal("tr"))); // 换手率(乘以100,保留2位小数)
            stockShowInfoDto.setThan(BigDecimalUtil.mul100B(data.getBigDecimal("qrr"))); // 量比(乘以100,保留2位小数)
            stockShowInfoDto.setPeRatio(data.getBigDecimal("ttm_pe")); // 市盈率(TTM)
            // 自动计算涨停状态(调用DTO自定义getter方法,无需手动赋值)
            stockShowInfoDto.setZt(stockShowInfoDto.getZt());

            return stockShowInfoDto;
        } catch (Exception e) {
            log.error("财联社爬取股票详情失败,fullCode={}", fullCode, e);
            // 主数据源失败,可在此处自动切换备用数据源(腾讯),此处简化处理,返回null
            return null;
        }
    }

    /**
     * 构建财联社请求头:模拟浏览器请求,避免被反爬
     */
    private Map<String, String> buildDjrHeaderMap() {
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("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");
        headerMap.put("Referer", "https://www.cls.cn/");
        headerMap.put("Accept", "application/json, text/plain, */*");
        return headerMap;
    }
}

3.1.3 关键注意点

  • 请求头构建:必须模拟浏览器请求头(尤其是User-Agent、Referer),否则财联社接口会拒绝返回数据(反爬机制);
  • 全代码处理:财联社接口需要传入全代码(如sz001318),需从全代码中截取后6位作为股票纯代码(如001318),便于后续逻辑处理;
  • 数值计算:涨跌幅度百分比、换手率、量比等字段需乘以100转为百分比格式,使用BigDecimalUtil工具类避免浮点数精度丢失;
  • 异常处理:捕获所有异常(如HTTP请求失败、JSON解析失败、字段缺失等),记录详细日志(包含全代码),便于问题排查,同时为切换备用数据源预留扩展点。

3.2 备用数据源:腾讯股票详情爬取实现

腾讯股票接口(URL格式:http://qt.gtimg.cn/q=sz001318)返回特殊格式字符串(非JSON),需自定义解析逻辑。该接口稳定性高,且无需复杂请求头,适合作为备用数据源。同时,可复用系列第二篇中"腾讯当时数据爬取"的基础方法(parseTxMoneyYesHistory),减少代码冗余。

3.2.1 代码复用要点

复用第三篇中的parseTxMoneyYesHistory方法(用于爬取腾讯股票历史数据),该方法已实现"构建腾讯接口URL、设置请求头、发送HTTP请求、获取响应数据"的核心逻辑,此处仅需新增"响应数据解析为TxStockHistoryInfo列表"和"TxStockHistoryInfo转StockShowInfoDto"的逻辑。

3.2.2 完整代码实现

复制代码
@Service
public class StockDetailServiceImpl implements StockDetailService {

    @Resource
    private DefaultProperties defaultProperties; // 配置文件封装类,包含腾讯接口地址
    @Resource
    private DailyTradingInfoParse dailyTradingInfoParse; // 腾讯数据解析工具类

    @Override
    public StockShowInfoDto getNowInfo(String fullCode) {
        // 1. 参数校验:全代码不能为空
        if (StrUtil.isBlank(fullCode)) {
            log.error("腾讯爬取股票详情失败:全代码为空");
            return null;
        }
        try {
            // 2. 复用第三篇的基础方法:爬取腾讯股票当前行情数据(返回TxStockHistoryInfo列表)
            // 注:DateTime.now()表示获取当日数据,parseTxMoneyYesHistory方法已兼容当日实时数据爬取
            List<TxStockHistoryInfo> txStockHistoryInfos = parseTxMoneyYesHistory(Collections.singletonList(fullCode), DateTime.now());
            // 3. 校验解析结果:列表为空则返回null
            if (CollUtil.isEmpty(txStockHistoryInfos)) {
                log.error("腾讯爬取股票详情失败:解析后数据列表为空,fullCode={}", fullCode);
                return null;
            }
            // 4. 获取单只股票数据(列表仅含一条记录)
            TxStockHistoryInfo txStockHistoryInfo = txStockHistoryInfos.get(0);
            // 5. TxStockHistoryInfo转StockShowInfoDto:字段映射+格式转换
            StockShowInfoDto stockShowInfoDto = new StockShowInfoDto();
            // 基础信息封装
            stockShowInfoDto.setCode(txStockHistoryInfo.getCode()); // 股票代码
            stockShowInfoDto.setName(txStockHistoryInfo.getName()); // 股票名称
            stockShowInfoDto.setFullCode(fullCode); // 全代码
            stockShowInfoDto.setExchange(0); // 交易所类型:腾讯接口未返回,暂设为0(可后续扩展解析逻辑)
            stockShowInfoDto.setDate(DateUtil.now()); // 行情日期(当日)
            // 行情数据封装(映射TxStockHistoryInfo字段)
            stockShowInfoDto.setOpeningPrice(txStockHistoryInfo.getOpeningPrice()); // 开盘价
            stockShowInfoDto.setYesClosingPrice(txStockHistoryInfo.getYesClosingPrice()); // 昨日收盘价
            stockShowInfoDto.setHighestPrice(txStockHistoryInfo.getHighestPrice()); // 最高价
            stockShowInfoDto.setLowestPrice(txStockHistoryInfo.getLowestPrice()); // 最低价
            stockShowInfoDto.setClosingPrice(txStockHistoryInfo.getClosingPrice()); // 收盘价
            stockShowInfoDto.setNowPrice(txStockHistoryInfo.getNowPrice()); // 当前价
            // 交易数据封装
            stockShowInfoDto.setTradingVolume(txStockHistoryInfo.getTradingVolume()); // 成交量(股)
            stockShowInfoDto.setTradingValue(txStockHistoryInfo.getTradingValue()); // 成交金额(元)
            stockShowInfoDto.setAmplitude(txStockHistoryInfo.getAmplitude()); // 涨跌幅度
            // 数值格式化:涨跌幅度百分比转为带%的字符串(如2.35→"2.35%")
            stockShowInfoDto.setAmplitudeProportion(BigDecimalUtil.toShowString2(txStockHistoryInfo.getAmplitudeProportion()));
            stockShowInfoDto.setChangingProportion(txStockHistoryInfo.getChangingProportion()); // 换手率(已为百分比格式)
            stockShowInfoDto.setThan(txStockHistoryInfo.getThan()); // 量比
            stockShowInfoDto.setPeRatio(txStockHistoryInfo.getDynamicPriceRatio()); // 动态市盈率
            // 涨停状态:腾讯数据未直接提供,暂设为0(可复用StockUtil工具类计算,此处简化处理)
            stockShowInfoDto.setZt(0);

            return stockShowInfoDto;
        } catch (Exception e) {
            log.error("腾讯爬取股票详情失败,fullCode={}", fullCode, e);
            return null;
        }
    }

    /**
     * 复用第三篇的腾讯历史数据爬取基础方法:构建URL、发送请求、获取响应数据
     * 核心逻辑:拼接股票代码列表→构建腾讯接口URL→设置Referer请求头→发送GET请求→返回响应数据解析后的列表
     */
    @Override
    public List<TxStockHistoryInfo> parseTxMoneyYesHistory(List<String> codeList, DateTime beforeLastWorking) {
        // 1. 拼接股票代码参数(多个代码用逗号分隔,如"sz001318,sh600000")
        String qParam = StrUtil.join(",", codeList);
        // 2. 构建请求URL(配置文件中接口地址格式:http://qt.gtimg.cn/q={0})
        String url = MessageFormat.format(defaultProperties.getTxMoneyHistoryUrl(), qParam);
        try {
            // 3. 构建请求头:仅需设置Referer为腾讯股票页面,避免反爬
            Map<String, String> header = new HashMap<>();
            header.put("Referer", "http://qt.gtimg.cn");
            // 4. 发送HTTP GET请求:使用无代理客户端,编码设为GBK(腾讯接口响应编码为GBK)
            String content = HttpUtil.sendGet(HttpClientConfig.proxyNoUseCloseableHttpClient(), url, header, "gbk");
            // 5. 解析响应数据:调用专用解析工具类,将特殊格式字符串解析为TxStockHistoryInfo列表
            return dailyTradingInfoParse.parseTxMoneyHistory(content, codeList, beforeLastWorking);
        } catch (Exception e) {
            log.error("parseTxMoneyYesHistory获取股票{}当前信息失败", qParam, e);
            return null;
        }
    }
}

3.2.3 关键注意点

  • 代码复用:复用parseTxMoneyYesHistory方法,减少重复编码,同时保证系统代码风格一致;
  • 响应编码:腾讯接口响应编码为GBK,发送请求时需指定编码为GBK,否则会出现中文乱码问题;
  • 数据格式解析:腾讯接口返回特殊格式字符串(如"v_sz001318="51~三峡能源001318 ...""),需通过dailyTradingInfoParse.parseTxMoneyHistory工具类自定义解析逻辑(按"~"分割字符串,提取对应字段);
  • 字段兼容:腾讯数据部分字段缺失(如涨停状态需手动计算),需在封装时补充处理,确保DTO输出格式统一。

3.3 数据源切换策略实现

为实现"主备数据源自动切换",新增数据源选择器方法,核心逻辑:优先调用财联社接口,若返回null(爬取失败),则自动调用腾讯接口;若均失败,返回null并记录日志。

复制代码
@Service
public class StockDetailServiceImpl implements StockDetailService {

    @Override
    public StockShowInfoDto getStockDetail(String fullCode) {
        // 1. 优先调用主数据源(财联社)
        StockShowInfoDto mainSourceResult = getByCode(fullCode);
        if (mainSourceResult != null) {
            return mainSourceResult;
        }
        // 2. 主数据源失败,切换备用数据源(腾讯)
        log.warn("财联社爬取失败,切换腾讯数据源,fullCode={}", fullCode);
        StockShowInfoDto backupSourceResult = getNowInfo(fullCode);
        if (backupSourceResult != null) {
            return backupSourceResult;
        }
        // 3. 均失败,返回null+记录错误日志
        log.error("主备数据源爬取均失败,fullCode={}", fullCode);
        return null;
    }
}

四、核心优化点与生产环境适配

上述实现已满足股票详情获取的基础需求,但在生产环境中需补充以下优化点,确保系统稳定性、性能与可维护性:

  1. 缓存优化:对股票详情数据添加Redis缓存(缓存key为STOCK_DETAIL + fullCode),缓存过期时间设为5分钟(行情数据实时性要求较高,不宜过长);爬取新数据后同步更新缓存,减少重复爬取,提升响应速度;

  2. 反爬机制适配:

  3. 请求频率控制:通过线程池+计数器限制爬取频率(如单IP每分钟最多爬取60次),避免被数据源封禁IP;

  4. 请求头动态化:维护User-Agent池,每次请求随机选择一个User-Agent,模拟多浏览器请求,降低反爬风险;

  5. 数据源健康监控:记录主备数据源的爬取成功率(成功次数/总次数),通过监控工具(如Prometheus + Grafana)展示,当主数据源成功率低于90%时,自动发送告警(如钉钉/邮件),便于及时处理;

  6. 字段校验增强:对DTO封装后的字段进行非空校验(如核心行情字段openingPrice、nowPrice等),若为空则填充默认值(如0.0),避免上层调用出现空指针异常;

  7. 代码解耦:将HTTP请求、JSON解析、数值计算等通用逻辑抽取为独立工具类(如HttpUtil、JsonUtil、BigDecimalUtil),提升代码复用性与可维护性;

  8. 降级策略:当主备数据源均失败时,返回最近一次缓存的股票详情数据(若存在),而非直接返回null,提升用户体验。

五、系列文章预告

本文完成了量化系统"数据展示层"的核心模块------股票详细信息实时获取,实现了多数据源爬取、自动切换、数据封装的完整逻辑。下一篇文章将聚焦"构建自己的股票实时查看系统",结合本文获取的实时详情数据与第四篇的自选股票。

最后,留一个思考问题:在高并发场景下(如大量用户同时查询不同股票详情),如何设计缓存策略(如缓存穿透、缓存击穿、缓存雪崩的解决方案),才能兼顾性能与数据实时性?欢迎在评论区交流~

相关推荐
么么...2 小时前
掌握 MySQL:数据类型、数据定义语言DDL、数据操作语言DML
数据库·经验分享·sql·mysql
老朱佩琪!3 小时前
快速做事经验分享
经验分享
中屹指纹浏览器3 小时前
2025边缘计算与本地指纹生成技术:浏览器指纹安全与抗检测方案解析
经验分享·笔记
Metaphor6923 小时前
Java 合并 Word 文档:使用 Spire.Doc for Java 实现高效自动化处理
经验分享
GISer_Jing5 小时前
2025年FE_Jinger的年度总结、经验分享与展望
前端·经验分享·面试·前端框架·aigc
Francek Chen5 小时前
【博客之星2025年度总评选】逐梦2026:我的2025博客回溯与AI运营之旅
大数据·人工智能·经验分享·程序人生·csdn·博客之星
么么...6 小时前
掌握 MySQL:约束、范式与视图详解
数据库·经验分享·sql·mysql
机器学习算法与Python实战6 小时前
阿里千问安全审核大模型,本地部署,实测
经验分享
启芯硬件6 小时前
电源XL6009E1的dieshot细节分析-芯片设计干货
大数据·经验分享·硬件工程·1024程序员节