Intentos máximos superados con URL en las solicitudes

151

Estoy tratando de obtener el contenido de App Store> Negocios :

import requests
from lxml import html

page = requests.get("https://itunes.apple.com/in/genre/ios-business/id6000?mt=8")
tree = html.fromstring(page.text)

flist = []
plist = []
for i in range(0, 100):
    app = tree.xpath("//div[@class='column first']/ul/li/a/@href")
    ap = app[0]
    page1 = requests.get(ap)

Cuando trato de la rangecon (0,2)que funciona, pero cuando pongo el rangede 100s que muestra este error:

Traceback (most recent call last):
  File "/home/preetham/Desktop/eg.py", line 17, in <module>
    page1 = requests.get(ap)
  File "/usr/local/lib/python2.7/dist-packages/requests/api.py", line 55, in get
    return request('get', url, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/api.py", line 44, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 383, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 486, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/adapters.py", line 378, in send
    raise ConnectionError(e)
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='itunes.apple.com', port=443): Max retries exceeded with url: /in/app/adobe-reader/id469337564?mt=8 (Caused by <class 'socket.gaierror'>: [Errno -2] Name or service not known)
usuario3446000
fuente
1
¿No deberías usar ivariable en algún lugar del for?
Laurent S.
eres como solicitar la misma aplicación 100 veces. para que es eso ?
njzk2
Estoy usando i en el resto del código. No he publicado el código completo
user3446000
No estoy solicitando la misma aplicación 100 veces. Estoy solicitando 100 aplicaciones diferentes en la misma categoría.
user3446000
3
Parece que su solucionador de DNS no puede resolver itunes.apple.com. ¿Puedes correr dig itunes.apple.comen tu línea de comando y publicar los resultados aquí?
Thomas Orozco

Respuestas:

141

Lo que sucedió aquí es que el servidor de iTunes rechaza su conexión (está enviando demasiadas solicitudes desde la misma dirección IP en un corto período de tiempo)

Intentos máximos excedidos con url: / in / app / adobe-reader / id469337564? Mt = 8

el rastreo de error es engañoso, debería ser algo así como "No se pudo establecer conexión porque la máquina de destino lo rechazó activamente" .

Hay un problema en python.requests lib en Github, échale un vistazo aquí

Para superar este problema (no tanto un problema como un seguimiento de depuración engañoso), debe detectar excepciones relacionadas con la conexión de esta manera:

try:
    page1 = requests.get(ap)
except requests.exceptions.ConnectionError:
    r.status_code = "Connection refused"

Otra forma de superar este problema es que si usa el intervalo de tiempo suficiente para enviar solicitudes al servidor, esto se puede lograr mediante la sleep(timeinsec)función en Python (no olvide importar el modo de suspensión)

from time import sleep

En general, todas las solicitudes son una increíble lib python, espero que resuelva su problema.

djra
fuente
2
El ciclo de suspensión solucionó mi problema, un poco hackeo, pero al repetir un par de veces mientras manejaba la respuesta de error, pude forzar una solución por fuerza bruta.
elPastor
14
Esta respuesta es realmente incorrecta. Este es un problema de búsqueda de resolución, como lo indica la (Caused by <class 'socket.gaierror'>: [Errno -2] Name or service not known)parte. "gai" significa getaddrinfo, y el probable error relacionado es: EAI_NONAME El nodo o servicio no se conoce; o tanto el nodo como el servicio son NULL; o AI_NUMERICSERV se especificó en hints.ai_flags y el servicio no era una cadena numérica de número de puerto. Probablemente parecía que el sueño lo solucionó, pero probablemente solo dormiste a través de un problema transitorio de resolución de DNS.
lingfish
44
Esta respuesta no parece tener sentido ya que en 'r' es el objeto que proviene de request.get (), por lo que, con la excepción, esto solo conduce a otro error.
mikkokotila
Esta respuesta no tiene sentido. El error de OP no dice "Conexión rechazada", dice "Nombre o servicio desconocido". Esta respuesta parece suponer que todos los ConnectionError se deben a "Conexión rechazada".
erjiang
1
Para mí, esto tiene que ser exactamente correcto, un límite de velocidad establecido por el servidor. Puedo hacer 80 llamadas y luego me aparecerá este mensaje. Luego, después de un corto tiempo, el servidor está disponible para otras 80 llamadas y el ciclo se repite. Es demasiado regular para ser otra cosa.
demongolem
122

Solo use las requests'funciones:

import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry


session = requests.Session()
retry = Retry(connect=3, backoff_factor=0.5)
adapter = HTTPAdapter(max_retries=retry)
session.mount('http://', adapter)
session.mount('https://', adapter)

session.get(url)

Esta será GETla URL y volverá a intentarlo 3 veces en caso de requests.exceptions.ConnectionError. backoff_factorayudará a aplicar demoras entre los intentos para evitar fallar nuevamente en caso de una cuota de solicitud periódica

Echa un vistazo a requests.packages.urllib3.util.retry.Retry , tiene muchas opciones para simplificar los reintentos.

zulú
fuente
Por alguna razón, esto no funciona en Windows 10. Comencé el shell con python manage.py shelly estoy usando session.get('http://localhost:8000/api/'). ¿Alguna ayuda? @Zulu
MwamiTovi
Tengo mi problema resuelto. Había olvidado iniciar el dev-servery mantenerlo funcionando primero.
MwamiTovi el
¿Por qué todavía no es la mejor respuesta?
Pavel Druzhinin
Intenté esto, pero no volvería a intentarlo mientras recibía las solicitudes.excepciones.ConnectionError Read agotó el tiempo de espera. pero establecí un tiempo de espera para la solicitud de obtención.
Zagfai
34

Solo haz esto

Pegue el siguiente código en lugar de page = requests.get(url):

import time

page = ''
while page == '':
    try:
        page = requests.get(url)
        break
    except:
        print("Connection refused by the server..")
        print("Let me sleep for 5 seconds")
        print("ZZzzzz...")
        time.sleep(5)
        print("Was a nice sleep, now let me continue...")
        continue

De nada :)

jatin
fuente
3
recuerde hacer import time
Yuan Tao
3
requeststiene su propio código para manejar su error y volver a intentarlo
Zulu
55
Nunca sale del bucle. @jatin
Alper
11
Además, no es una buena idea capturar cualquier tipo de excepción (con except: ...) de requestsy sleep()en respuesta. En cambio, deberían atrapar requests.exceptions.ConnectionErrory sleep()solo si se produce esa excepción. (O mejor aún, solo use la Retry()clase integrada que viene con requests, como lo sugiere @Zulu).
J. Taylor
15

Tengo un problema similar pero el siguiente código funcionó para mí.

url = <some REST url>    
page = requests.get(url, verify=False)

"verificar = falso" deshabilita la verificación SSL. Intentar y atrapar se puede agregar como de costumbre.

Raj Stha
fuente
5

Siempre es bueno implementar el manejo de excepciones. No solo ayuda a evitar la salida inesperada del script, sino que también puede ayudar a registrar errores y notificaciones de información. Cuando uso solicitudes de Python, prefiero detectar excepciones como esta:

    try:
        res = requests.get(adress,timeout=30)
    except requests.ConnectionError as e:
        print("OOPS!! Connection Error. Make sure you are connected to Internet. Technical Details given below.\n")
        print(str(e))            
        renewIPadress()
        continue
    except requests.Timeout as e:
        print("OOPS!! Timeout Error")
        print(str(e))
        renewIPadress()
        continue
    except requests.RequestException as e:
        print("OOPS!! General Error")
        print(str(e))
        renewIPadress()
        continue
    except KeyboardInterrupt:
        print("Someone closed the program")

AquínewIPadress () es una función definida por el usuario que puede cambiar la dirección IP si se bloquea. Puedes ir sin esta función.

Tanmoy Datta
fuente
su solución es buena, pero cómo cambiar ip-adrressen Python, ¿sabe algo al respecto y luego hágamelo saber
Haritsinh Gohil
1
Había usado algún servicio VPN IPVanish y Hide My Ass. Se configuran utilizando open-vpn y open-vpn tienen una fila de comandos de shell que renueva la dirección IP. Puede llamar al comando shell o bash desde python. De esta manera, puedes implementarlo.
Tanmoy Datta
5

Especificar el proxy en un entorno corporativo lo resolvió para mí.

page = requests.get("http://www.google.com:80", proxies={"http": "http://111.233.225.166:1234"})

El error completo es:

request.exceptions.ConnectionError: HTTPSConnectionPool (host = 'www.google.com', puerto = 80): Reintentos máximos excedidos con url: / (Causado por NewConnectionError (': Error al establecer una nueva conexión: [WinError 10060] Una conexión intento fallido porque la parte conectada no respondió correctamente después de un período de tiempo, o la conexión establecida falló porque el host conectado no pudo responder '))

Jeremy Thompson
fuente
2

No pude hacerlo funcionar en Windows incluso después de instalar pyopenssl y probar varias versiones de Python (mientras funcionaba bien en Mac), así que cambié a Urllib y funciona en Python 3.6 (de Python .org) y 3.7 (anaconda )

import urllib 
from urllib.request import urlopen
html = urlopen("http://pythonscraping.com/pages/page1.html")
contents = html.read()
print(contents)
alex
fuente
Estoy bastante molesto de que las cosas funcionen solo si se ejecutan con Anaconda prompt.
BingLi224
1

Cuando estaba escribiendo un script de prueba de navegador de selenio, me encontré con este error al llamar driver.quit()antes de usar una llamada de API JS. ¡Recuerde que salir de webdriver es lo último que debe hacer!

Saleh
fuente
1

Agregando mi propia experiencia para aquellos que están experimentando esto en el futuro. Mi error específico fue

Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known'

Resulta que esto fue realmente porque había alcanzado el número máximo de archivos abiertos en mi sistema. No tenía nada que ver con conexiones fallidas, o incluso un error de DNS como se indica.

Oded
fuente
0

Agregando mi propia experiencia:

r = requests.get(download_url)

cuando intenté descargar un archivo especificado en la url.

El error fue

HTTPSConnectionPool(host, port=443): Max retries exceeded with url (Caused by SSLError(SSLError("bad handshake: Error([('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')])")))

Lo corregí agregando verify = Falsela función de la siguiente manera:

r = requests.get(download_url + filename)
open(filename, 'wb').write(r.content)
Suraj Subramanian
fuente
0

Verifica tu conexión de red. Tenía esto y la máquina virtual no tenía una conexión de red adecuada.

Timothy C. Quinn
fuente
-1

Agregue encabezados para esta solicitud.

headers={
'Referer': 'https://itunes.apple.com',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}

requests.get(ap, headers=headers)
Michael Yang
fuente