
当 API 要求查询参数以 eq(field,value)、ne(field,value) 等函数式语法传递时,直接将键值对传入 requests.get(params=...) 会导致 500 错误;必须将嵌套字典结构手动序列化为符合服务端解析规则的查询字符串。
当 api 要求查询参数以 `eq(field,value)`、`ne(field,value)` 等函数式语法传递时,直接将键值对传入 `requests.get(params=...)` 会导致 500 错误;必须将嵌套字典结构手动序列化为符合服务端解析规则的查询字符串。
在调用类似 https://www.produktdatenbank-get.at/api/products 这类基于函数式查询语法(如 eq(), ne(), select(), sort())的 REST API 时,不能依赖 requests 默认的 URL 编码逻辑。requests 对字典参数的处理是标准的 key=value&key2=value2 形式,而该接口期望的是形如 eq(group,337)&ne(custom.field_28,R-407C) 的结构化查询字符串——这本质上是一种自定义 DSL,而非标准键值对。
因此,需手动构建符合其语义的查询字符串。推荐采用结构化字典 + 自定义序列化函数的方式,兼顾可读性与可维护性:
def make_query_string(params_dict):
"""
将嵌套字典转换为函数式查询字符串(如 eq(group,337)&ne(field,val))
支持:eq、ne、select、sort 等操作符,支持单值/多值字段
"""
parts = []
for op, payload in params_dict.items():
if isinstance(payload, dict):
# 处理 eq(...)、ne(...) 等带字段名和值的操作
for field, value in payload.items():
if isinstance(value, list):
# 多值:ne(custom.field_28,R-407C)&ne(custom.field_28,R-410A)
for v in value:
parts.append(f"{op}({field},{v})")
else:
# 单值:eq(group,337)
parts.append(f"{op}({field},{value})")
elif isinstance(payload, list):
# 处理 select(id,name,...) 或 sort(+name)
values_joined = ",".join(payload) if op != "sort" else payload[0]
parts.append(f"{op}({values_joined})")
else:
# 基础字段(如 sort=+name),但本例中 sort 也需括号语法
parts.append(f"{op}({payload})")
return "&".join(parts)
# 定义结构化参数(语义清晰、易于维护)
params = {
"eq": {
"group": 337,
"instock": 1,
"custom.field_133": 1,
},
"ne": {
"custom.field_28": ["R-404A", "R-407C", "R-417A", "R-410A"],
},
"select": [
"id", "name", "custom.field_22", "custom.field_28",
"custom.field_133", "subsidable", "custom.field_78"
],
"sort": "+name"
}
# 序列化为合法查询字符串
query_str = make_query_string(params)
# → 'eq(group,337)&eq(instock,1)&eq(custom.field_133,1)&ne(custom.field_28,R-404A)&...&select(id,name,...)&sort(+name)'
# 发送请求(注意:此时 params 是字符串,非字典)
response = requests.get(
url="https://www.produktdatenbank-get.at/api/products",
params=query_str, # ✅ 关键:传入已构造好的字符串
headers={
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"Accept": "application/json",
"X-Requested-With": "XMLHttpRequest",
"Referer": "https://www.produktdatenbank-get.at/",
}
)
print("Status:", response.status_code)
if response.status_code == 200:
data = response.json()
print("Total items:", len(data.get("data", [])))
else:
print("Error:", response.text[:200])
✅ 关键要点总结:
- ❌ 不要直接传 params={...} 字典——requests 会错误地编码为 eq=%7B%27group%27%3A+337%7D,服务端无法识别;
- ✅ 必须先将逻辑参数转为服务端能解析的原始查询字符串(含括号、逗号、函数名);
- ⚠️ 注意 select 和 sort 等操作符同样需遵循 select(...) 语法,不可当作普通键值对;
- ? 若字段名含特殊字符(如 .、-),确保服务端允许——本例中 custom.field_28 是合法字段标识;
- ?️ 建议封装 make_query_string() 并增加输入校验(如空值跳过、字符串转义),提升健壮性。
通过该方法,你既能保持代码逻辑清晰(参数按语义分组),又能严格满足后端接口的协议要求,避免 500 Internal Server Error。











