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

Python请求DBpedia SPARQL含特殊字符实体返回400错误的解决方法

问题根因

返回400状态码、后续JSON解析报Expecting value: line 1 column 1 (char 0)的核心原因,是你通过字符串格式化直接拼接SPARQL语句时,没有对实体名中的特殊字符做IRI合规转义:括号、星号、撇号、特殊破折号、感叹号这类字符要么会直接破坏SPARQL语法结构,要么会生成不符合规范的非法IRI,DBpedia端点无法解析非法查询就会返回400错误,此时响应内容是HTML格式的错误提示而非JSON,后续调用json()解析就会触发你看到的报错。

修复方案

核心是两点:一是对传入的实体名做标准IRI编码,不要直接裸拼;二是优化请求逻辑,减少额外报错可能。

  • 用Python标准库urllib.parse.quote对实体名做百分号编码,自动处理所有特殊字符,生成符合RFC规范的合法IRI
  • 直接使用完整IRI(用尖括号包裹)查询,不要依赖前缀拼接减少转义遗漏
  • 改用POST方法提交SPARQL查询,避免GET请求的URL长度限制、参数转义混乱问题
  • 增加HTTP状态码校验,在请求阶段就捕获错误,不要等到JSON解析阶段才发现问题
修复后可直接运行的代码
import requests
from urllib.parse import quote

def get_dbpedia_triples(ent: str):
    # 对实体名做全字符合规编码,不保留任何不安全字符
    encoded_entity = quote(ent, safe="")
    # 直接写入编码后的完整合法IRI,避免前缀拼接的转义问题
    sparql_query = f"""
    PREFIX dbo: <http://dbpedia.org/ontology/>
    PREFIX dbp: <http://dbpedia.org/property/>
    SELECT DISTINCT ?sub ?predicate
    WHERE {{
        ?sub ?predicate <http://dbpedia.org/resource/{encoded_entity}>.
    }}
    """

    endpoint = "https://dbpedia.org/sparql/"
    req_params = {
        "query": sparql_query,
        "format": "json",
        "default-graph-uri": "http://dbpedia.org"
    }

    try:
        # 用POST提交查询,规避GET的长度、编码问题
        resp = requests.post(endpoint, data=req_params)
        # 主动校验HTTP状态,4xx/5xx直接抛错
        resp.raise_for_status()
        return resp.json()
    except Exception as e:
        print(f"查询实体[{ent}]失败: {str(e)}")
        # 打印部分响应内容方便定位问题
        if 'resp' in locals():
            print(f"状态码: {resp.status_code}, 错误片段: {resp.text[:200]}")
        return None

# 测试之前所有报错的实体
error_entities = [
    "Off_Limits_(1988_film)",
    "Faith_of_My_Fathers_(film)",
    "A_Rumor_of_War_(miniseries)",
    "Bat*21",
    "Hearts_and_Minds_(film)",
    "The_Green_Berets_(film)",
    "War_in_Vietnam_(1954–59)",
    "Alice's_Restaurant_(film)",
    "Sir!_No_Sir!",
    "Jacob's_Ladder_(film)",
    "List_of_allied_military_operations_of_the_Vietnam_War_(1973–74)",
    "War_in_Vietnam_(1945–46)",
    "The_War_at_Home_(film)",
    "Missing_in_Action_(film)"
]

for ent in error_entities:
    result = get_dbpedia_triples(ent)
    if result:
        triple_count = len(result.get("results", {}).get("bindings", []))
        print(f"实体[{ent}]查询成功,共获取{triple_count}条三元组")
补充说明

之前的报错里的Expecting value不是JSON格式的问题,是400响应返回的是HTML错误页,不是合法JSON,解析的时候自然会报错。加上resp.raise_for_status()之后,会在状态码异常时直接抛出HTTP错误,能更快定位问题。

内容的提问来源于stack exchange,提问作者zahra mahani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 07:57:27