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

为何Python urllib3向Wikidata SPARQL端点发POST请求失败,而requests可行?

解决urllib3调用Wikidata SPARQL接口返回405 "Not writable"的问题

当用urllib3以POST方式调用Wikidata Query Service的SPARQL接口时出现405错误,返回"Not writable",但相同逻辑的requests代码可正常运行,核心原因是urllib3的fields参数会自动把请求编码为multipart/form-data格式,而非预期的application/x-www-form-urlencoded——即便手动设置了Content-Type头,urllib3也会覆盖该值,导致服务端无法识别查询请求格式,误判为写入操作从而返回错误。

修正后的urllib3代码

需手动将查询参数编码为URL格式字符串,通过body参数传递,同时保留正确请求头:

import urllib3
import urllib.parse

query_string = 'SELECT ?item WHERE {?item wdt:P31 wd:Q146.}LIMIT 10'
# 手动编码查询参数为application/x-www-form-urlencoded格式
encoded_data = urllib.parse.urlencode({'query': query_string})

http = urllib3.PoolManager()

requestheader = {
    'User-Agent': 'TestAgent/0.1 (mailto:email@domain.com)', 
    'Accept': 'application/sparql-results+json',
    'Content-Type': 'application/x-www-form-urlencoded'
}

# 使用body参数传递编码后的数据,替代原fields参数
response = http.request('POST', 'https://query.wikidata.org/sparql', body=encoded_data, headers=requestheader)
print(response.status)
print(response.headers)
print(response.data.decode('utf-8'))

关键修改说明

  • 用urllib.parse.urlencode()将查询参数编码为符合要求的URL格式字符串
  • 替换fields参数为body参数传递数据,避免urllib3强制使用multipart/form-data编码
  • 确保Content-Type头保持为application/x-www-form-urlencoded,此时urllib3不会覆盖该头

内容的提问来源于stack exchange,提问作者Steve Baskauf

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 07:47:33