#c# #winforms #button #httpclient #http-status-code-429
#c# #winforms #кнопка #httpclient #http-status-code-429
Вопрос:
исследовал эту тему и пытался реализовать различные решения, но я не могу ее решить. У меня есть функция plotmyChartAsync(), которая получает значения из Google trends. Использование этой функции в консольном приложении работает нормально, и я получаю желаемые результаты. Но когда я пытаюсь выполнить эту функцию с помощью кнопки из формы Windows, она всегда терпит неудачу. С помощью этого » HttpResponseMessage secondResponse = await clientUsed.GetAsync(secondRequestStr);» Я всегда получаю сбой 429 от API. Это означает, что я отправляю много запросов. Как я мог этого избежать?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Globalization;
using System.Threading;
namespace GoogleTrendsAnalysis
{
public partial class Form1 : Form
{
private SemaphoreSlim _mutex = new SemaphoreSlim(1);
public Form1()
{
InitializeComponent();
}
public async Task plotmyChartAsync()
{
await _mutex.WaitAsync();
try
{
const string searchKeyWord = "bmw";
const string firstTimePeriodString = "2021-01-10T00";
const string secondTimePeriodString = " 2021-01-15T00";
const string httprequestStr = "https://trends.google.de/trends/api/explore?hl=deamp;tz=-60amp;req={"comparisonItem":[{"keyword":"" searchKeyWord "","geo":"DE","time":"" firstTimePeriodString secondTimePeriodString ""}],"category":0,"property":""}amp;tz=-60";
CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
HttpClient client = new HttpClient(handler);
HttpResponseMessage response = await client.GetAsync(httprequestStr, HttpCompletionOption.ResponseHeadersRead);
Uri uri = new Uri(httprequestStr);
Console.WriteLine(cookies.GetCookies(uri));
IEnumerable<Cookie> responseCookies = cookies.GetCookies(uri).Cast<Cookie>();
Console.WriteLine(responseCookies.First());
string cookieused = responseCookies.First().Name "=" responseCookies.First().Value;
client.CancelPendingRequests();
client.Dispose();
handler.Dispose();
using (var clientUsed = new HttpClient())
{
clientUsed.BaseAddress = new Uri("https://trends.google.de/trends/api/");
clientUsed.DefaultRequestHeaders.Add("cookie", cookieused);
Console.WriteLine(clientUsed.DefaultRequestHeaders);
HttpResponseMessage responseUsed = await clientUsed.GetAsync(httprequestStr);
responseUsed.EnsureSuccessStatusCode();
Console.WriteLine(responseUsed);
if (responseUsed.IsSuccessStatusCode)
{
string result = responseUsed.Content.ReadAsStringAsync().Resu<
result = result.Substring(4, result.Length - 4);
Console.WriteLine("Result: " result);
dynamic data = JObject.Parse(result);
Console.WriteLine("TOKEN: " data.widgets[0]["token"]);
string myToken = data.widgets[0]["token"];
string secondRequestStr = "https://trends.google.de/trends/api/widgetdata/multiline?hl=deamp;tz=-60amp;req={"time":"" firstTimePeriodString "\:00\:00" secondTimePeriodString "\:00\:00","resolution":"HOUR","locale":"de","comparisonItem":[{"geo":{"country":"DE"},"complexKeywordsRestriction":{"keyword":[{"type":"BROAD","value":"" searchKeyWord ""}]}}],"requestOptions":{"property":"","backend":"CM","category":0}}amp;token=" myToken "amp;tz=-60";
HttpResponseMessage secondResponse = await clientUsed.GetAsync(secondRequestStr);
secondResponse.EnsureSuccessStatusCode();
string secondResult = secondResponse.Content.ReadAsStringAsync().Resu<
List<DateTime> dateTimes = new List<DateTime>();
List<double> values = new List<double>();
secondResult = secondResult.Substring(5, secondResult.Length - 5);
dynamic secondData = JObject.Parse(secondResult);
foreach (var t in secondData)
{
foreach (var x in t)
{
foreach (var s in x.timelineData)
{
bool ifhasDataStr = s.hasData[0];
if (ifhasDataStr == true)
{
string formattedValueStr = s.formattedValue[0];
string formattedTimeStr = s.formattedTime;
double myValue = Convert.ToDouble(formattedValueStr);
formattedTimeStr = formattedTimeStr.Replace(" um ", " ");
DateTime dt = DateTime.ParseExact(formattedTimeStr, "dd.MM.yyyy HH:mm", CultureInfo.InvariantCulture);
dateTimes.Add(dt);
values.Add(myValue);
Console.WriteLine("Die ZEIT: " formattedTimeStr " / DER WERT: " myValue);
}
}
}
}
double numberOfPeriods = dateTimes.Count;
double[] valuesArr = values.ToArray();
double[] xs = new double[valuesArr.Length];
for (int i = 0; i < valuesArr.Length; i )
{
xs[i] = dateTimes[i].ToOADate();
}
formsPlot1.Reset();
formsPlot1.plt.PlotScatter(xs, valuesArr);
formsPlot1.plt.Ticks(dateTimeX: true);
formsPlot1.Render();
}
}
}
finally
{
_mutex.Release();
}
}
protected async void button1_Click(object sender, EventArgs e)
{
await plotmyChartAsync();
}
}
}
Комментарии:
1. » Как я мог этого избежать » — не отправляйте так много….
2. Я не совсем понимаю, как это можно сделать. На данный момент я также не могу понять, почему is выполняется, как и ожидалось, с консольным приложением, но здесь происходит сбой.. я буду повторять больше..
Ответ №1:
После исследования я обнаружил, что проблема заключалась в cookie… Вот корректировки, которые необходимо внести в приведенный выше код…
var baseAddress = new Uri("https://trends.google.de/trends/api/");
using (var firstHandler = new HttpClientHandler() { UseCookies = false })
using (var clientUsed = new HttpClient(firstHandler) { BaseAddress = baseAddress })
{
clientUsed.BaseAddress = baseAddress;
clientUsed.DefaultRequestHeaders.Accept.Clear();
//clientUsed.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//clientUsed.DefaultRequestHeaders.Add("cookie", cookieused);
var firstRequest = new HttpRequestMessage(HttpMethod.Get, httprequestStr);
firstRequest.Headers.Add("cookie", cookieused);
Console.WriteLine(httprequestStr);
HttpResponseMessage responseUsed = await clientUsed.SendAsync(firstRequest);
Console.WriteLine(responseUsed);
string result = responseUsed.Content.ReadAsStringAsync().Resu<
Console.WriteLine(result);