Получение слишком большого количества запросов 429 от API при вызове его нажатием кнопки

#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);