You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

基于经纬度调用OpenStreetMap Nominatim反向地理编码接口时的C#请求异常与XML解析问题

问题分析与解决方案

我来帮你排查这个请求异常的问题,你的代码主要有两个核心问题导致了WebException,下面逐一说明并给出修复方案:

1. URL中的转义字符错误

你使用的URL里的&是HTML实体转义后的字符,在C#字符串中直接使用会被服务器识别为参数的一部分,而非参数分隔符,导致服务器无法正确解析请求参数。正确的做法是直接用&来分隔URL参数。

原错误URL:

https://nominatim.openstreetmap.org/reverse?format=xml&lat=48.927834&lon=16.861641&zoom=18&addressdetails=1

修正后的URL:

https://nominatim.openstreetmap.org/reverse?format=xml&lat=48.927834&lon=16.861641&zoom=18&addressdetails=1

2. 缺少必填的User-Agent请求头

Nominatim API强制要求所有请求必须包含User-Agent头,用于标识你的应用身份,否则服务器会直接拒绝请求(返回403 Forbidden或断开连接),这是引发WebException的最常见原因。

修正后的完整代码

下面是整合了请求修复、异常捕获和XML解析的完整代码,同时处理了可能的空值问题:

using System;
using System.IO;
using System.Net;
using System.Xml.Linq;
using System.Linq;

class GeoAddressFetcher
{
    static void Main()
    {
        string urlString = "https://nominatim.openstreetmap.org/reverse?format=xml&lat=48.927834&lon=16.861641&zoom=18&addressdetails=1";
        
        try
        {
            HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(urlString);
            myRequest.Method = "GET";
            // 必须设置User-Agent,替换为你的应用名称和联系方式
            myRequest.UserAgent = "MyGeocodingApp/1.0 (your-email@example.com)";
            
            // 使用using语句自动释放资源,避免内存泄漏
            using (WebResponse myResponse = myRequest.GetResponse())
            using (StreamReader sr = new StreamReader(myResponse.GetResponseStream(), System.Text.Encoding.UTF8))
            {
                string result = sr.ReadToEnd();
                
                // 解析XML并提取地址信息
                XDocument xml = XDocument.Parse(result);
                var addressQuery = from parts in xml.Root.Descendants("addressparts")
                                   select new 
                                   {
                                       Road = parts.Element("road")?.Value,
                                       HouseNumber = parts.Element("house_number")?.Value
                                   };
                
                foreach (var address in addressQuery)
                {
                    // 处理可能的空字段,避免拼接空字符串
                    string fullAddress = $"{address.Road} {address.HouseNumber}".Trim();
                    Console.WriteLine("提取到的地址: " + fullAddress);
                }
            }
        }
        catch (WebException ex)
        {
            // 捕获Web异常并打印详细信息,方便排查
            if (ex.Response is HttpWebResponse response)
            {
                Console.WriteLine($"请求失败,状态码: {(int)response.StatusCode} - {response.StatusDescription}");
                // 读取服务器返回的错误详情
                using (StreamReader errorReader = new StreamReader(response.GetResponseStream()))
                {
                    Console.WriteLine("错误响应内容: " + errorReader.ReadToEnd());
                }
            }
            else
            {
                Console.WriteLine("请求异常: " + ex.Message);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("其他异常: " + ex.Message);
        }
    }
}

额外注意事项

  • User-Agent规范:请务必将代码中的User-Agent替换为你的真实应用名称和联系方式,Nominatim会拒绝无明确标识的请求,避免被判定为恶意爬虫。
  • 请求频率限制:Nominatim默认限制每秒1次请求,批量请求时需要添加延迟,否则会被临时封禁IP。
  • 空值处理:使用?.Value运算符避免因某些地址字段缺失(比如house_number)而引发NullReferenceException

这样修改后,应该就能成功获取XML数据并解析出目标地址信息了。

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

火山引擎 最新活动