即使第一次发出请求,Pytends api 也会抛出 429 错误

问题描述 投票:0回答:2

我正在使用非常简单的代码按地区查找关键字的数据。但每次我运行它时,它都会给我429错误,提示发出了太多请求,但实际上该请求是第一次发出,以前从未发出过。下面提到了我收到的错误。

引发异常。TooManyRequestsError.from_response(response) pytrends.exceptions.TooManyRequestsError:请求失败:Google 返回了代码 429 的响应

这是代码,我正在运行。

import pandas as pd                        
from pytrends.request import TrendReq





pytrend = TrendReq()
kw_list = ["Blockchain"]
pytrend.build_payload(kw_list, cat=0, timeframe='today 12-m', geo='', gprop='')
# Interest by Region
df = pytrend.interest_by_region()
df.head(10)
python api google-trends http-status-code-429
2个回答
1
投票

好吧,tprogrammer,我想我可能已经找到了你的答案,尽管我是从当前的 github 线程中得到的:发生异常:请求失败:Google 返回了代码为 429 的响应

///编辑(21.03.23): 用户“jesvinc”提供了一个更简洁的解决方案,将请求限制提升到之前的水平。 显然这与

GetGoogleCookie
方法有关,需要稍微改变一下。如果您进入 python 模块文件夹(我的位于
User\AppData\Roaming\Python\Python39\site-packages
),在 pytrends 中您将找到该文件
request.py
。打开它并将第 88 行中的“get”更改为“post”,如下所示:

return dict(filter(lambda i: i[0] == 'NID', requests.get(

return dict(filter(lambda i: i[0] == 'NID', requests.post(

经过此更改,甚至偶尔遗留的问题也消失了,并且它也再次开始与 VPN 配合使用。此修复很可能会以某种形式包含在下一个 pytrends 更新中,但在那之前,它可以正常工作。


0
投票

我们通过增加尝试次数解决了这个问题。

import time
import pandas as pd
from pytrends.request import TrendReq
from pytrends.exceptions import TooManyRequestsError, ResponseError
from requests.exceptions import ReadTimeout
from unidecode import unidecode
import warnings

 
# Filtrar pero no ignorar las advertencias FutureWarning
warnings.simplefilter(action='ignore', category=FutureWarning)
 
# Configuración de Google Trends
pytrends = TrendReq(hl='es', tz=360, timeout=(10, 25))  # Aumentar el tiempo de espera
 
# Palabras clave a buscar por categoría
keywords_pain = ['Dengue', 'Gripe', 'Fiebre', 'Ibuprofeno', 'Paracetamol']
keywords_nutri = ['Complejo B', 'Sueño', 'Sistema inmune', 'Magnesio', 'Redoxitos']
keywords_derma = ['Piel seca', 'Heridas', 'Cicaplast', 'Bepanthol', 'Vitamina B5']
keywords_ped = ['Ibuprofeno para chicos', 'Paracetamol para chicos', 'Ibuprofeno 2 %', 'Gripe en chicos', 'Dolor en chicos']
 
# Lista de países a consultar
paises = ['AR', 'PY', 'CL', 'BO', 'UY']
 
# DataFrame vacío para almacenar todos los datos combinados
all_data_combined = pd.DataFrame()
 
def obtener_datos(pytrends, keywords, pais, categoria, intento=1, max_intentos=2000):
    try:
        # Construir la carga útil con los parámetros especificados
        pytrends.build_payload(kw_list=keywords, timeframe='today 1-m', geo=pais)  # Cambiado a 'today 1-m' para últimos 30 días
        # Obtener datos de tendencias
        trend_data = pytrends.interest_over_time()
        if trend_data.empty:
            print(f"No se encontraron datos de tendencias para {pais} en la categoría {categoria}")
            return
        # Eliminar la columna 'isPartial'
        if 'isPartial' in trend_data.columns:
            trend_data = trend_data.drop(columns=['isPartial'])
        # Transformar el DataFrame de tendencias
        trend_data.reset_index(inplace=True)  # Resetear el índice para tener la fecha como columna
        trend_data_melted = pd.melt(trend_data, id_vars=['date'], var_name='keyword', value_name='value')
        # Añadir la columna del país
        trend_data_melted['country'] = pais
        # Obtener datos de interés por región
        region_data = pytrends.interest_by_region(resolution='REGION', inc_low_vol=True, inc_geo_code=True)
        if region_data.empty:
            print(f"No se encontraron datos de interés por región para {pais} en la categoría {categoria}")
            return
        # Transformar el DataFrame de interés por región
        region_data.reset_index(inplace=True)  # Resetear el índice para tener la provincia como columna
        region_data['geoName'] = region_data['geoName'].apply(unidecode)  # Aplicar unidecode a los nombres de las regiones
        region_data_melted = pd.melt(region_data, id_vars=['geoName'], var_name='keyword', value_name='region_value')
        region_data_melted.rename(columns={'geoName': 'province'}, inplace=True)
        # Añadir la columna del país
        region_data_melted['country'] = pais
        # Convertir region_value a numérico, ignorando errores
        region_data_melted['region_value'] = pd.to_numeric(region_data_melted['region_value'], errors='coerce')
        # Obtener la keyword con el valor más alto por provincia
        idx = region_data_melted.groupby(['country', 'province'])['region_value'].idxmax()
        top_keywords_per_province = region_data_melted.loc[idx, ['country', 'province', 'keyword']].rename(columns={'keyword': 'top_keyword'})
        # Combinar los dos DataFrames
        combined_data = trend_data_melted.merge(region_data_melted, on=['keyword', 'country'], how='left')
        # Añadir la columna de la categoría
        combined_data['category'] = categoria
        # Añadir la keyword con el valor más alto por provincia
        combined_data = combined_data.merge(top_keywords_per_province, on=['country', 'province'], how='left')
        # Añadir los datos combinados al DataFrame global
        global all_data_combined
        all_data_combined = pd.concat([all_data_combined, combined_data], ignore_index=True)
        print(f"Datos agregados correctamente para {pais} en la categoría {categoria}")
    except TooManyRequestsError:
        if intento <= max_intentos:
            print(f"Error 429: Demasiadas solicitudes. Esperando antes de reintentar para {pais}... (Intento {intento}/{max_intentos})")
            # time.sleep(2)  # Esperar más tiempo con cada reintento
            obtener_datos(pytrends, keywords, pais, categoria, intento + 1)
        else:
            print(f"Error 429: Demasiadas solicitudes. Superado el número máximo de intentos para {pais}.")
    except ReadTimeout:
        if intento <= max_intentos:
            print(f"ReadTimeout: La solicitud para {pais} en la categoría {categoria} ha tardado demasiado. Reintentando... (Intento {intento}/{max_intentos})")
            # time.sleep(2)  # Esperar más tiempo con cada reintento
            obtener_datos(pytrends, keywords, pais, categoria, intento + 1)
        else:
            print(f"ReadTimeout: Superado el número máximo de intentos para {pais} en la categoría {categoria}.")
    except ResponseError as e:
        print(f"ResponseError: {e}. Verifica los parámetros y vuelve a intentarlo.")
 
# Iterar sobre cada país y categoría
for pais in paises:
    obtener_datos(pytrends, keywords_pain, pais, 'Pain')
    time.sleep(1)  # Esperar 30 segundos antes de la siguiente solicitud
    obtener_datos(pytrends, keywords_nutri, pais, 'Nutri')
    time.sleep(1)
    obtener_datos(pytrends, keywords_derma, pais, 'Derma')
    time.sleep(1)
    obtener_datos(pytrends, keywords_ped, pais, 'Ped')
    time.sleep(1)  # Esperar 30 segundos antes de realizar la siguiente consulta para otro país
 
# Guardar el DataFrame combinado en un único archivo Excel
all_data_combined.to_excel('C:\\Users\\XXXXXXX\\OneDrive - XXXXX\\Desktop\\GoogleTrends.xlsx', index=False)
 
print("Datos guardados correctamente en GoogleTrends.xlsx")
© www.soinside.com 2019 - 2024. All rights reserved.