Maximale Wiederholungsversuche mit URL in Anfragen überschritten

151

Ich versuche, den Inhalt von App Store> Business abzurufen :

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)

Wenn ich das rangemit versuche (0,2), funktioniert es, aber wenn ich das rangein 100s setze , zeigt es diesen Fehler:

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)
user3446000
quelle
1
Sollten Sie nicht iirgendwo in der eine Variable verwenden for?
Laurent S.
Sie möchten dieselbe App 100 Mal anfordern. Wofür ist das ?
njzk2
Ich benutze i im Rest des Codes. Ich habe nicht den gesamten Code gepostet
user3446000
Ich fordere nicht 100 Mal dieselbe App an. Ich fordere 100 verschiedene Apps in derselben Kategorie an.
user3446000
3
Ihr DNS-Resolver kann anscheinend nicht aufgelöst werden itunes.apple.com. Können Sie dig itunes.apple.coman Ihrer Kommandozeile laufen und die Ergebnisse hier veröffentlichen?
Thomas Orozco

Antworten:

139

Was hier passiert ist, ist, dass der iTunes Server Ihre Verbindung ablehnt (Sie senden in kurzer Zeit zu viele Anfragen von derselben IP-Adresse).

Maximale Wiederholungsversuche mit URL überschritten: / in / app / adobe-reader / id469337564? Mt = 8

Die Fehlersuche ist irreführend und sollte etwa "Es konnte keine Verbindung hergestellt werden, da der Zielcomputer sie aktiv abgelehnt hat" lauten .

Es gibt ein Problem bei etwa python.requests lib bei Github. Überprüfen Sie es hier

Um dieses Problem zu beheben (weniger ein Problem als vielmehr eine irreführende Debug-Ablaufverfolgung), sollten Sie verbindungsbezogene Ausnahmen wie die folgenden abfangen:

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

Eine andere Möglichkeit, dieses Problem zu beheben, besteht darin, dass Sie eine ausreichende Zeitlücke zum Senden von Anforderungen an den Server verwenden. Dies kann durch die sleep(timeinsec)Funktion in Python erreicht werden (vergessen Sie nicht, den Ruhezustand zu importieren).

from time import sleep

Alles in allem ist Anfragen fantastisch Python Lib, hoffe, das löst Ihr Problem.

djra
quelle
2
Die Schlafschleife hat mein Problem behoben - ein bisschen wie ein Hack, aber durch ein paar Schleifen während der Behandlung der Fehlerantwort konnte ich eine Lösung brutal erzwingen.
elPastor
14
Diese Antwort ist eigentlich falsch. Dies ist ein Resolver-Suchproblem, wie im (Caused by <class 'socket.gaierror'>: [Errno -2] Name or service not known)Teil angegeben. "gai" steht für getaddrinfound der wahrscheinliche Fehler ist: EAI_NONAME Der Knoten oder Dienst ist nicht bekannt; oder sowohl Knoten als auch Dienst sind NULL; oder AI_NUMERICSERV wurde in hints.ai_flags angegeben und service war keine numerische Portnummernzeichenfolge. Es sah wahrscheinlich so aus, als hätte der Schlaf das Problem behoben, aber Sie haben wahrscheinlich nur ein vorübergehendes DNS-Resolver-Problem durchgeschlafen.
Lingfish
4
Diese Antwort scheint nicht sinnvoll zu sein, da 'r' das Objekt ist, das von request.get () stammt. Mit der Ausnahme führt dies nur zu einem weiteren Fehler.
Mikkokotila
Diese Antwort macht keinen Sinn. Der OP-Fehler lautet nicht "Verbindung abgelehnt", sondern "Name oder Dienst nicht bekannt". Diese Antwort scheint davon auszugehen, dass alle ConnectionError auf "Verbindung abgelehnt" zurückzuführen sind.
Erjiang
1
Für mich muss dies genau richtig sein, ein vom Server festgelegtes Ratenlimit. Ich kann 80 Anrufe tätigen und dann erscheint diese Nachricht für mich. Nach kurzer Zeit steht der Server für weitere 80 Anrufe zur Verfügung und der Zyklus wird wiederholt. es ist zu regelmäßig, um etwas anderes zu sein.
Demongolem
121

Verwenden Sie einfach requests'Funktionen:

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)

Dies wird GETdie URL und versuchen 3 Mal im Fall von requests.exceptions.ConnectionError. backoff_factorDies hilft dabei, Verzögerungen zwischen den Versuchen anzuwenden, um zu vermeiden, dass bei einem regelmäßigen Anforderungskontingent erneut ein Fehler auftritt.

Schauen Sie sich an requests.packages.urllib3.util.retry.Retry, es gibt viele Möglichkeiten, um Wiederholungsversuche zu vereinfachen.

Zulu-
quelle
Aus irgendeinem Grund funktioniert dies unter Windows 10 nicht. Die Shell wurde mit gestartet python manage.py shellund wird verwendet session.get('http://localhost:8000/api/'). Irgendeine Hilfe? @ Zulu
MwamiTovi
habe mein Problem gelöst. Hatte vergessen, das zu starten dev-serverund es zuerst am Laufen zu halten.
MwamiTovi
Warum ist es immer noch nicht die beste Antwort?
Pavel Druzhinin
Ich habe dies versucht, aber es wurde nicht wiederholt, während ich das Zeitlimit für das Lesen von request.exceptions.ConnectionError Read erhielt. Ich habe jedoch eine Zeitüberschreitung für die Get-Anfrage festgelegt.
Zagfai
34

Tu das einfach,

Fügen Sie anstelle von den folgenden Code ein 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

Bitte :)

Jatin
quelle
3
Denken Sie daran zu tun import time
Yuan Tao
3
requestshat seinen eigenen Code, um seinen Fehler zu behandeln und erneut zu versuchen
Zulu
5
Es verlässt nie die Schleife. @ Jatin
Alper
10
Es ist auch keine gute Idee, einfach irgendeine Art von Ausnahme (mit except: ...) von requestsund sleep()als Antwort abzufangen. Stattdessen sollten sie abfangen requests.exceptions.ConnectionErrorund sleep()nur, wenn diese Ausnahme auftritt. (Oder noch besser, verwenden Sie einfach die mitgelieferte integrierte Retry()Klasse requests, wie von @Zulu vorgeschlagen).
J. Taylor
32

pip install pyopenssl schien es für mich zu lösen.

https://github.com/requests/requests/issues/4246

Akshar
quelle
1
Hat mir geholfen herauszufinden, dass SSL mein Problem ist
MilaDroid
Gleich hier =) Danke!
Rodrigo E. Principe
15

Ich habe ein ähnliches Problem, aber der folgende Code hat bei mir funktioniert.

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

"verify = False" deaktiviert die SSL-Überprüfung. Try and Catch kann wie gewohnt hinzugefügt werden.

Raj Stha
quelle
5

Es ist immer gut, die Ausnahmebehandlung zu implementieren. Dies hilft nicht nur, ein unerwartetes Beenden des Skripts zu vermeiden, sondern kann auch helfen, Fehler und Info-Benachrichtigungen zu protokollieren. Wenn ich Python-Anfragen verwende, bevorzuge ich Ausnahmen wie diese:

    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")

Hier ist erneuerIPadress () eine benutzerdefinierte Funktion, die die IP-Adresse ändern kann, wenn sie blockiert wird. Sie können auf diese Funktion verzichten.

Tanmoy Datta
quelle
Ihre Lösung ist schön, aber wie man ip-adrressin Python ändert , wissen Sie etwas darüber, dann lassen Sie es mich wissen
Haritsinh Gohil
1
Ich hatte einen VPN-Dienst IPVanish und Hide My Ass verwendet. Sie werden mit open-vpn konfiguriert und open-vpn verfügt über eine Shell-Befehlszeile, mit der die IP-Adresse erneuert wird. Sie können den Shell- oder Bash-Befehl von Python aus aufrufen. Auf diese Weise können Sie es implementieren.
Tanmoy Datta
5

Die Angabe des Proxys in einer Unternehmensumgebung hat das Problem für mich gelöst.

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

Der vollständige Fehler ist:

request.exceptions.ConnectionError: HTTPSConnectionPool (host = 'www.google.com', port = 80): Maximale Wiederholungsversuche mit URL überschritten: / (verursacht durch NewConnectionError (': Fehler beim Herstellen einer neuen Verbindung: [WinError 10060] Eine Verbindung Versuch fehlgeschlagen, weil die verbundene Partei nach einer bestimmten Zeit nicht richtig geantwortet hat, oder die hergestellte Verbindung fehlgeschlagen ist, weil der verbundene Host nicht geantwortet hat '))

Jeremy Thompson
quelle
2

Ich war nicht in der Lage, es unter Windows zum Laufen zu bringen, selbst nachdem ich pyopenssl installiert und verschiedene Python-Versionen ausprobiert hatte (während es auf dem Mac gut funktionierte), also wechselte ich zu urllib und es funktionierte unter Python 3.6 (von Python .org) und 3.7 (Anaconda) )

import urllib 
from urllib.request import urlopen
html = urlopen("http://pythonscraping.com/pages/page1.html")
contents = html.read()
print(contents)
Alex
quelle
Ich bin ziemlich genervt, dass die Dinge nur funktionieren, wenn sie mit der Anaconda-Eingabeaufforderung ausgeführt werden.
BingLi224
1

Beim Schreiben eines Selenium-Browser- driver.quit()Testskripts ist dieser Fehler beim Aufrufen vor der Verwendung eines JS-API-Aufrufs aufgetreten. Denken Sie daran, dass das Beenden des Web-Treibers das letzte ist, was zu tun ist!

Saleh
quelle
1

Hinzufügen meiner eigenen Erfahrung für diejenigen, die dies in Zukunft erleben. Mein spezifischer Fehler war

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

Es stellt sich heraus, dass dies tatsächlich daran lag, dass ich die maximale Anzahl geöffneter Dateien auf meinem System erreicht hatte. Es hatte nichts mit fehlgeschlagenen Verbindungen oder sogar einem DNS-Fehler wie angegeben zu tun.

Oded
quelle
0

Meine eigene Erfahrung hinzufügen:

r = requests.get(download_url)

als ich versuchte, eine in der URL angegebene Datei herunterzuladen.

Der Fehler war

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')])")))

Ich habe es korrigiert, indem ich verify = Falsedie Funktion wie folgt hinzugefügt habe :

r = requests.get(download_url + filename)
open(filename, 'wb').write(r.content)
Suraj Subramanian
quelle
-1

Fügen Sie Header für diese Anforderung hinzu.

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
quelle