本人多年编程小白,天生编程白痴体质。大家莫见笑。
自己用C#写了一段代码,使用HttpWebRequest,通过SOHU的API接口获取指定股票的交易信息。
该段代码一直运行正常。最近开始报错。
详细信息如下:
System.Net.WebException
HResult=0x80131509
Message=远程服务器返回错误: (503) 服务器不可用。
通过在浏览器地址栏直接输入查询URL的方式可以正常返回数据。
只是通过代码查询的时候会报上面的错误。
可以判定,问题出在代码中。由于以前是正常运行的,应该是网站接口进行了某种升级。
这种情况该如何DEBUG呢?
一直在DEBUG,找不到原因。
发现一个现象,按F11逐语句调试,就可以正常运行。
按F10逐过程调试,就会报503错误。
太奇怪了。
您好!遇到这种问题,可以按照以下步骤进行DEBUG:
对比你的代码请求 和 通过浏览器访问请求 有什么区别
我用Fiddler对比了一下,确实有一个区别:
浏览器访问 Host: q.stock.sohu.com:443
代码访问 Host: q.stock.sohu.com
代码的host没有443端口,不知道代码哪里设置有问题。
@happygogogo: 443是https ,没有443默认是80 http
帮你gpt一下:
出现这种 (503) 服务器不可用
错误时,虽然通过浏览器直接访问API可以正常返回数据,但代码访问时报错,说明可能存在以下几种情况:
User-Agent 相关问题:网站可能对非浏览器的请求进行了限制,部分API会验证请求的 User-Agent
,阻止来自自动脚本或程序的请求。
请求频率限制:某些API会对频繁的请求进行限制,503 错误可能是由于你在短时间内发起了过多的请求。
HTTP/HTTPS 协议不匹配:部分网站可能升级了协议,要求使用 HTTPS 请求,而你的代码可能仍在使用 HTTP。
服务器端限流:API服务器可能对某些请求或IP地址做了限流,导致你的程序访问受阻。
代理或防火墙问题:某些环境中使用代理或防火墙的情况下,可能会拦截你的请求。
检查 User-Agent:
很多时候,API会要求请求头中的 User-Agent
模拟为浏览器的形式。你可以在代码中添加或修改 User-Agent
,模拟浏览器请求。
var request = (HttpWebRequest)WebRequest.Create("http://api.sohu.com/stock");
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36";
增加延时:如果是请求频率过高导致的503错误,尝试在多个请求之间添加延时。
System.Threading.Thread.Sleep(1000); // 每次请求之间延迟1秒
检查 HTTP/HTTPS:确保请求URL使用正确的协议。如果你以前用的是 http
,可以尝试改为 https
,以防服务器升级导致的协议问题。
抓包分析:可以使用抓包工具(如Fiddler或Wireshark)来比较浏览器与代码请求的差异。查看哪些请求头字段在浏览器中存在而在代码中没有设置。
捕获更多异常信息:对代码中的异常进行详细捕获,记录更多信息以便调试。
try
{
// 发送请求代码
}
catch (WebException ex)
{
var response = ex.Response as HttpWebResponse;
if (response != null)
{
Console.WriteLine($"Status Code: {response.StatusCode}");
Console.WriteLine($"Status Description: {response.StatusDescription}");
}
Console.WriteLine(ex.ToString());
}
下面是一个可能的修复示例:
using System;
using System.IO;
using System.Net;
class Program
{
static void Main()
{
try
{
var url = "http://api.sohu.com/stock";
var request = (HttpWebRequest)WebRequest.Create(url);
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36";
request.Timeout = 10000; // 设置超时时间
request.KeepAlive = false; // 禁用 Keep-Alive
using (var response = (HttpWebResponse)request.GetResponse())
using (var stream = response.GetResponseStream())
using (var reader = new StreamReader(stream))
{
var responseText = reader.ReadToEnd();
Console.WriteLine(responseText);
}
}
catch (WebException ex)
{
Console.WriteLine("WebException caught: " + ex.Message);
if (ex.Response != null)
{
using (var errorResponse = (HttpWebResponse)ex.Response)
{
Console.WriteLine("HTTP Status Code: " + (int)errorResponse.StatusCode);
using (var reader = new StreamReader(errorResponse.GetResponseStream()))
{
string errorText = reader.ReadToEnd();
Console.WriteLine("Error response: " + errorText);
}
}
}
}
}
}
通过调整 User-Agent
、限制请求频率、切换协议等方式,通常可以解决此类API请求问题。抓包分析则是更深一步调试的有力工具。
我用Fiddler对比了一下,确实有一个区别:
浏览器访问 Host: q.stock.sohu.com:443
代码访问 Host: q.stock.sohu.com
代码的host没有443端口,不知道代码哪里设置有问题。
我推测可能是API原来是可以接受http请求的,后来服务器升级为只接受https请求了。
我的代码应该是通过HTTP查询的,虽然我代码里的请求地址是https开头的,但是因为某种原因,实际执行时是通过http请求。
我对HttpWebRequest查询https接口操作不熟悉。有没有示例代码啊?
增加容错处理机制:
请求偶尔会有:503错误!
但是不多;所以增加错误重试机制就行了;
private static async Task GetStock() { var url = "http://q.stock.sohu.com/hisHq?code=cn_300228&start=20130930&end=20130931&stat=1&order=D&period=d&callback=&rt=jsonp"; using var client = new HttpClient(); var tryTimes = 10; //失败,重试次数; while (tryTimes > 0) { try { var result = await client.GetStringAsync(url); tryTimes = 10; Console.WriteLine(result); break; } catch (Exception e) { Console.WriteLine(e.Message); Thread.Sleep(1000); tryTimes--; continue; } } }