You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python过滤API值?巴西政府采购API字段扩展需求

嘿,很高兴帮你解决这个扩展需求!你已经搞定了cnpj_contratada字段的处理,现在要扩展valor_inicial的处理,还想知道怎么过滤API返回的数据对吧?下面我一步步给你拆解:

1. 扩展valor_inicial字段的处理

巴西政府采购API返回的valor_inicial通常是带格式的字符串(比如R$ 1.234,56),直接用的话不方便计算,所以我们需要把它转换成数值类型。这里推荐用Decimal来处理金额,避免浮点精度问题,同时兼容巴西的数值格式。

先看完整的代码示例:

import requests
import locale
from decimal import Decimal

# 兼容系统是否安装巴西本地化环境,两种方式解析金额字符串
try:
    locale.setlocale(locale.LC_ALL, 'pt_BR.UTF-8')
    def parse_valor(valor_str):
        if not valor_str:
            return None
        # 用locale工具解析格式化的金额字符串
        try:
            return Decimal(locale.atof(valor_str.replace('R$', '').strip()))
        except ValueError:
            print(f"警告:无法解析金额字符串 {valor_str}")
            return None
except locale.Error:
    # 系统未安装pt_BR locale时,手动处理格式
    def parse_valor(valor_str):
        if not valor_str:
            return None
        # 移除货币符号、空格,替换千分位点为空,逗号换为点
        cleaned = valor_str.replace('R$', '').strip().replace('.', '').replace(',', '.')
        try:
            return Decimal(cleaned)
        except ValueError:
            print(f"警告:无法解析金额字符串 {valor_str}")
            return None

def fetch_and_process_contratos(uasg_id):
    # 构造API请求URL
    url = f"http://compras.dados.gov.br/contratos/v1/contratos.json?uasg={uasg_id}"
    response = requests.get(url)
    response.raise_for_status()  # 主动抛出请求错误,方便排查问题
    data = response.json()

    processed_contratos = []
    # 遍历返回的合同列表(注意API的嵌套结构:_embedded -> contratos)
    for contrato in data.get('_embedded', {}).get('contratos', []):
        processed_item = {
            # 保留你已实现的cnpj_contratada处理逻辑
            'cnpj_contratada': contrato.get('cnpj_contratada'),
            # 新增valor_inicial的处理
            'valor_inicial': parse_valor(contrato.get('valor_inicial'))
            # 其他需要处理的字段可以在这里继续添加
        }
        processed_contratos.append(processed_item)
    
    return processed_contratos

这段代码的核心是:

  • 兼容不同系统的本地化环境,确保金额解析正常
  • 把valor_inicial转换成Decimal类型,方便后续计算和过滤
2. 过滤API中的值

过滤数据有两种思路,优先用第一种,效率更高:

2.1 利用API参数直接过滤(推荐)

巴西政府采购API支持通过URL参数提前过滤数据,这样返回的结果已经是你需要的,不需要下载全部数据再处理。比如:

  • 按金额范围过滤:如果API支持valor_inicial_min或valor_inicial_max参数,直接加在URL里
    # 示例:获取uasg=153229且初始金额大于10000的合同
    url = f"http://compras.dados.gov.br/contratos/v1/contratos.json?uasg=153229&valor_inicial_min=10000"
    
  • 按CNPJ过滤:如果需要特定供应商的合同,可以用cnpj_contratada参数
    url = f"http://compras.dados.gov.br/contratos/v1/contratos.json?uasg=153229&cnpj_contratada=12345678000199"
    

具体支持哪些参数,可以参考合同模块的官方文档找“Filtros”相关说明。

2.2 在Python中过滤已获取的数据

如果API不支持你需要的过滤条件,那就先获取全部数据,再用列表推导或filter函数过滤:

示例1:过滤初始金额大于10000的合同

contratos = fetch_and_process_contratos(153229)
filtered_contratos = [
    item for item in contratos 
    if item['valor_inicial'] is not None and item['valor_inicial'] > Decimal('10000')
]

示例2:多条件过滤(金额在5000-50000之间,且CNPJ不为空)

filtered_contratos = [
    item for item in contratos 
    if item['valor_inicial'] is not None 
    and Decimal('5000') <= item['valor_inicial'] <= Decimal('50000')
    and item['cnpj_contratada'] is not None
]

示例3:用filter函数过滤(适合复杂逻辑)

def filter_contrato(item):
    if item['valor_inicial'] is None:
        return False
    # 自定义过滤逻辑:金额大于10000且CNPJ以"123"开头
    return item['valor_inicial'] > Decimal('10000') and item['cnpj_contratada'].startswith('123')

filtered_contratos = list(filter(filter_contrato, contratos))
额外提醒:处理分页数据

如果返回的合同很多,API会分页返回,你需要遍历所有分页才能拿到全部数据。这里给你加个分页处理的版本:

def fetch_all_contratos(uasg_id):
    url = f"http://compras.dados.gov.br/contratos/v1/contratos.json?uasg={uasg_id}"
    all_contratos = []

    while url:
        response = requests.get(url)
        response.raise_for_status()
        data = response.json()
        
        # 添加当前页的合同
        all_contratos.extend(data.get('_embedded', {}).get('contratos', []))
        
        # 获取下一页的URL(API返回的_links.next.href)
        url = data.get('_links', {}).get('next', {}).get('href')
    
    # 处理所有合同的字段
    processed = []
    for contrato in all_contratos:
        processed.append({
            'cnpj_contratada': contrato.get('cnpj_contratada'),
            'valor_inicial': parse_valor(contrato.get('valor_inicial'))
        })
    
    return processed

这样就能拿到某个UASG的所有合同数据啦!

内容的提问来源于stack exchange,提问作者Reinaldo Chaves

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 06:43:35