如何用SPARQL从Wikidata提取某国城镇乡村及详细信息?
解决Wikidata中提取德城乡镇邮编、州省及官网的SPARQL问题
问题背景
我需要提取德国的城市、城镇、村庄的邮政编码、州/省以及官方主页信息,这些数据大多存在于Wikidata中,但没法用SPARQL正确提取。
我的尝试及问题
第一个查询
SELECT ?city ?cityLabel WHERE { ?city wdt:P17 wd:Q183; (wdt:P31/(wdt:P279*)) wd:Q515; SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } } ORDER BY ?cityLabel
问题:返回大量无标签记录,还包含非城镇乡村的条目(比如Q436183这类行政区)。
第二个查询
SELECT DISTINCT ?cityLabel ?countyLabel ?officialHomepage WHERE { ?city wdt:P31 wd:Q515. ?city wdt:P17 wd:Q183. ?city wdt:P131 ?county. OPTIONAL { ?city wdt:P856 ?officialHomepage. } SERVICE wikibase:label { bd:serviceParam wikibase:language "de". } }
问题:结果中的城镇数量极少,很多符合条件的聚落没被抓取到。
优化后的SPARQL查询
SELECT DISTINCT ?city ?cityLabel ?postalCode ?stateLabel ?officialHomepage WHERE { # 匹配德国的城市、城镇、村庄及其子类 ?city wdt:P17 wd:Q183; (wdt:P31/wdt:P279*) ?settlementType. VALUES ?settlementType { wd:Q515 wd:Q3957 wd:Q486972 } # 对应城市、城镇、村庄 # 可选获取邮政编码(部分聚落可能无记录) OPTIONAL { ?city wdt:P281 ?postalCode } # 递归查找所属联邦州 ?city wdt:P131* ?state. ?state wdt:P31 wd:Q1221156. # 德国联邦州的Wikidata ID # 可选获取官方主页 OPTIONAL { ?city wdt:P856 ?officialHomepage } # 加载标签,优先德语,无德语则用英语 SERVICE wikibase:label { bd:serviceParam wikibase:language "de,en". } # 过滤掉没有标签的无效条目 FILTER (BOUND(?cityLabel)) } ORDER BY ?cityLabel
查询逻辑解释
- 精准匹配聚落类型:用
VALUES明确指定要抓取的三类聚落,结合(wdt:P31/wdt:P279*)匹配它们的所有子类,避免误抓行政区这类非居住实体。 - 灵活获取属性:用
OPTIONAL包裹邮编和官网字段,确保不会因为部分聚落缺少这些信息而被过滤掉。 - 正确关联联邦州:通过
wdt:P131*递归查找上级行政区域,直到找到类型为德国联邦州的实体,避免只抓取到区县层级的信息。 - 标签处理:设置多语言标签优先级,同时用
FILTER (BOUND(?cityLabel))直接剔除无标签的无效条目。 - 去重处理:
DISTINCT避免同一聚落因多条邮编或行政路径重复出现在结果中。
如果需要合并同一聚落的多个邮政编码,可以修改查询为:
SELECT ?city ?cityLabel (GROUP_CONCAT(DISTINCT ?postalCode; separator=", ") AS ?postalCodes) ?stateLabel ?officialHomepage WHERE { ?city wdt:P17 wd:Q183; (wdt:P31/wdt:P279*) ?settlementType. VALUES ?settlementType { wd:Q515 wd:Q3957 wd:Q486972 } OPTIONAL { ?city wdt:P281 ?postalCode } ?city wdt:P131* ?state. ?state wdt:P31 wd:Q1221156. OPTIONAL { ?city wdt:P856 ?officialHomepage } SERVICE wikibase:label { bd:serviceParam wikibase:language "de,en". } FILTER (BOUND(?cityLabel)) } GROUP BY ?city ?cityLabel ?stateLabel ?officialHomepage ORDER BY ?cityLabel
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

