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

如何用Pywikibot批量匹配Geonames ID与Wikidata ID?

批量通过Geonames ID查询对应Wikidata ID(Pywikibot实现)

问题背景

已有大量Geonames ID列表,需要批量查询对应的Wikidata ID,当前仅能实现单个ID的SPARQL查询,希望将查询中的固定ID替换为变量,遍历列表完成批量查询。

单个查询的SPARQL语句:

SELECT DISTINCT ?item ?itemLabel WHERE {
  SERVICE wikibase:label { bd:serviceParam wikibase:language "de". }
  {
    SELECT DISTINCT ?item WHERE {
      ?item p:P1566 ?statement0.
      ?statement0 (ps:P1566) "2867714".
    }
  }
}

单个查询的Pywikibot脚本可正常返回结果,但需扩展为批量处理。


解决方案

方法一:逐ID替换查询模板(适合小批量)

通过定义SPARQL模板,将固定ID替换为占位符,遍历ID列表时动态生成查询语句:

import pywikibot
from pywikibot import pagegenerators as pg

# 定义SPARQL模板,用占位符{geonames_id}代替固定ID
SPARQL_TEMPLATE = """
SELECT DISTINCT ?item ?itemLabel WHERE {
  SERVICE wikibase:label { bd:serviceParam wikibase:language "de". }
  {
    SELECT DISTINCT ?item WHERE {
      ?item p:P1566 ?statement0.
      ?statement0 (ps:P1566) "{geonames_id}".
    }
  }
}
"""

# 你的Geonames ID列表,可从文件读取(示例:慕尼黑、柏林、维也纳的ID)
geonames_ids = ["2867714", "2950159", "3067696"]

wikidata_site = pywikibot.Site("wikidata", "wikidata")

# 遍历每个ID执行查询
for gid in geonames_ids:
    query = SPARQL_TEMPLATE.format(geonames_id=gid)
    generator = pg.WikidataSPARQLPageGenerator(query, site=wikidata_site)
    for item in generator:
        print(f"Geonames ID {gid} → Wikidata ID: {item}")

方法二:SPARQL VALUES批量查询(适合大批量,效率更高)

利用SPARQL的VALUES子句一次性传入所有ID,减少请求次数,提升效率:

import pywikibot
from pywikibot import pagegenerators as pg

# 批量查询的SPARQL模板
BATCH_SPARQL_TEMPLATE = """
SELECT DISTINCT ?geonamesId ?item ?itemLabel WHERE {
  SERVICE wikibase:label { bd:serviceParam wikibase:language "de". }
  VALUES ?geonamesId { {geonames_id_list} }
  ?item p:P1566 ?statement0.
  ?statement0 ps:P1566 ?geonamesId.
}
"""

# Geonames ID列表
geonames_ids = ["2867714", "2950159", "3067696"]

# 将ID转换为SPARQL VALUES要求的格式:"id1" "id2" "id3"
formatted_ids = ' '.join([f'"{gid}"' for gid in geonames_ids])
query = BATCH_SPARQL_TEMPLATE.format(geonames_id_list=formatted_ids)

wikidata_site = pywikibot.Site("wikidata", "wikidata")
generator = pg.WikidataSPARQLPageGenerator(query, site=wikidata_site)

# 解析查询结果
for result in generator:
    # 提取绑定的变量值
    bindings = result.get('binding', [])
    gid = next(b['value'] for b in bindings if b['name'] == 'geonamesId')
    wikidata_id = f"wikidata:{next(b['value'].split('/')[-1] for b in bindings if b['name'] == 'item')}"
    print(f"Geonames ID {gid} → Wikidata ID: {wikidata_id}")

注意事项

  • 若ID数量极大(上千级),建议分批次处理,避免SPARQL语句过长被服务器拒绝
  • 从文件读取ID可使用以下代码:
    with open('geonames_ids.txt', 'r', encoding='utf-8') as f:
        geonames_ids = [line.strip() for line in f if line.strip()]
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 08:13:24