Przekroczono maksymalną liczbę ponownych prób z adresem URL w żądaniach

151

Próbuję pobrać zawartość App Store> Business :

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)

Kiedy próbuję rangez (0,2)nim pracuje, ale kiedy umieścić rangew 100s to pokazuje ten błąd:

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
źródło
1
Nie powinieneś używać izmiennej gdzieś w for?
Laurent S.,
chcesz prosić o tę samą aplikację 100 razy. po co to ?
njzk2
W pozostałej części kodu używam i. Nie
wysłałem
Nie żądam tej samej aplikacji 100 razy. Proszę o 100 różnych aplikacji w tej samej kategorii.
user3446000
3
Wygląda na to, że Twój resolver DNS nie może rozwiązać problemu itunes.apple.com. Czy możesz uruchomić dig itunes.apple.comswój wiersz poleceń i opublikować tutaj wyniki?
Thomas Orozco,

Odpowiedzi:

141

Tutaj zdarzyło się, że serwer itunes odmawia połączenia (wysyłasz zbyt wiele żądań z tego samego adresu IP w krótkim czasie)

Przekroczono maksymalną liczbę ponownych prób z adresem URL: / in / app / adobe-reader / id469337564? Mt = 8

śledzenie błędów jest mylące, powinno to być coś w stylu „Nie można nawiązać połączenia, ponieważ maszyna docelowa aktywnie odmówiła” .

Wystąpił problem na stronie about python.requests lib na Github, sprawdź tutaj

Aby rozwiązać ten problem (nie tyle problem, ile wprowadzający w błąd ślad debugowania), powinieneś złapać wyjątki związane z połączeniem, takie jak:

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

Innym sposobem rozwiązania tego problemu jest wykorzystanie wystarczającej ilości czasu do wysyłania żądań do serwera, można to osiągnąć za pomocą sleep(timeinsec)funkcji w Pythonie (nie zapomnij zaimportować uśpienia)

from time import sleep

W sumie wszystkie żądania są niesamowitą biblioteką Pythona, mam nadzieję, że rozwiąże Twój problem.

djra
źródło
2
Pętla uśpienia naprawiła mój problem - trochę włamania, ale kilkakrotnie zapętlając odpowiedź na błąd, byłem w stanie brutalnie wymusić rozwiązanie.
elPastor
14
Ta odpowiedź jest faktycznie błędna. Jest to problem z wyszukiwaniem resolvera, na co wskazuje (Caused by <class 'socket.gaierror'>: [Errno -2] Name or service not known)część. „gai” oznacza getaddrinfo, a prawdopodobny powiązany błąd to: EAI_NONAME Węzeł lub usługa nie są znane; lub zarówno węzeł, jak i usługa mają wartość NULL; lub AI_NUMERICSERV został określony w hints.ai_flags, a usługa nie jest ciągiem numerycznym numeru portu. Prawdopodobnie wyglądało na to, że sen naprawił to, ale prawdopodobnie przespałeś przejściowy problem z programem rozpoznawania nazw DNS.
lingfish
4
Ta odpowiedź nie wydaje się mieć sensu, ponieważ w 'r' jest obiekt pochodzący z request.get (), więc z wyjątkiem tego prowadzi to po prostu do kolejnego błędu.
mikkokotila
Ta odpowiedź nie ma sensu. Błąd OP nie mówi „Odmowa połączenia”, ale „Nieznana nazwa lub usługa”. Ta odpowiedź wydaje się zakładać, że wszystkie błędy ConnectionError są spowodowane komunikatem „Odmowa połączenia”.
erjiang
1
Dla mnie musi to być dokładnie poprawne, ograniczenie prędkości narzucone przez serwer. Mogę wykonać 80 połączeń i wtedy pojawi się ten komunikat. Następnie po krótkim czasie serwer jest dostępny dla kolejnych 80 wywołań i cykl się powtarza. to jest zbyt regularne, aby być czymkolwiek innym.
demongolem
122

Po prostu użyj requests'funkcji:

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)

Spowoduje to GETwyświetlenie adresu URL i spróbuj ponownie 3 razy w przypadku requests.exceptions.ConnectionError.backoff_factorpomoże zastosować opóźnienia między próbami, aby uniknąć ponownej porażki w przypadku okresowego limitu wniosków.

Spójrz requests.packages.urllib3.util.retry.Retry, ma wiele opcji upraszczających ponawianie.

Zulus
źródło
Z jakiegoś powodu to nie działa w systemie Windows 10. Uruchomiono powłokę z python manage.py shelli używam session.get('http://localhost:8000/api/'). Jakaś pomoc? @Zulu
MwamiTovi
mój problem został rozwiązany. Zapomniał dev-servernajpierw uruchomić i uruchomić go.
MwamiTovi
Dlaczego nadal nie jest to najlepsza odpowiedź?
Pavel Druzhinin
Próbowałem tego, ale nie próbowałem ponownie, gdy otrzymałem request.exceptions.ConnectionError Read przekroczono limit czasu. ale ustawiłem limit czasu dla żądania get.
Zagfai
34

Po prostu zrób to,

Wklej następujący kod w miejsce 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

Nie ma za co :)

jatin
źródło
3
pamiętaj, aby to zrobić import time
Yuan Tao
3
requestsma własny kod do obsługi błędu i ponownej próby
Zulu
5
Nigdy nie wychodzi z pętli. @jatin
alper
10
Ponadto, nie jest to dobry pomysł, aby tylko złapać dowolny typ wyjątku (z except: ...) z requestsi sleep()w odpowiedzi. Zamiast tego powinny przechwytywać requests.exceptions.ConnectionErrori sleep()tylko wtedy, gdy wystąpi ten wyjątek. (Lub jeszcze lepiej, po prostu użyj wbudowanej Retry()klasy, która jest dołączona requests, zgodnie z sugestią @Zulu).
J. Taylor,
32

pip install pyopenssl wydawało się, że rozwiązuje to za mnie.

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

Akshar
źródło
1
Pomogło mi dowiedzieć się, że SSL jest moim problemem
MilaDroid
To samo tutaj =) Dzięki!
Rodrigo E. Principe
15

Mam podobny problem, ale poniższy kod zadziałał.

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

„verify = False” wyłącza weryfikację SSL. Try and catch można dodać jak zwykle.

Raj Stha
źródło
5

Zawsze dobrze jest zaimplementować obsługę wyjątków. Pomaga to nie tylko uniknąć nieoczekiwanego wyjścia ze skryptu, ale może również pomóc w rejestrowaniu błędów i powiadomieniach. Korzystając z żądań Pythona wolę wychwytywać takie wyjątki:

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

Tutaj renewIPadress () jest funkcją definiowaną przez użytkownika, która może zmienić adres IP, jeśli zostanie zablokowany. Możesz obejść się bez tej funkcji.

Tanmoy Datta
źródło
Twoje rozwiązanie jest fajne, ale jak zmienić ip-adrressw Pythonie, czy wiesz coś o tym, to daj mi znać
Haritsinh Gohil
1
Skorzystałem z usługi VPN IPVanish i Hide My Ass. Są konfigurowane za pomocą open-vpn i open-vpn mają wiersz poleceń powłoki odnawiający adres IP. Możesz wywołać polecenie powłoki lub bash z Pythona. W ten sposób możesz to zaimplementować.
Tanmoy Datta
5

Określenie proxy w środowisku korporacyjnym rozwiązało to za mnie.

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

Pełny błąd to:

request.exceptions.ConnectionError: HTTPSConnectionPool (host = 'www.google.com', port = 80): Przekroczono maksymalną liczbę ponownych prób z adresem url: / (Spowodowane przez NewConnectionError (': Nie udało się nawiązać nowego połączenia: [WinError 10060] Połączenie próba nie powiodła się, ponieważ połączona strona nie odpowiedziała poprawnie po pewnym czasie lub nawiązane połączenie nie powiodło się, ponieważ podłączony host nie odpowiedział '))

Jeremy Thompson
źródło
2

nie byłem w stanie sprawić, by działał w systemie Windows nawet po zainstalowaniu pyopenssl i wypróbowaniu różnych wersji Pythona (chociaż działał dobrze na Macu), więc przełączyłem się na urllib i działa na Pythonie 3.6 (z python .org) i 3.7 (anaconda )

import urllib 
from urllib.request import urlopen
html = urlopen("http://pythonscraping.com/pages/page1.html")
contents = html.read()
print(contents)
Alex
źródło
Jestem dość zirytowany, że rzeczy działają tylko wtedy, gdy są uruchamiane z zachętą Anacondy.
BingLi224
1

Kiedy pisałem skrypt testowy przeglądarki selenium, napotkałem ten błąd podczas wywoływania driver.quit()przed użyciem wywołania JS API. Pamiętaj, że opuszczenie webdrivera jest ostatnią rzeczą do zrobienia!

Saleh
źródło
1

Dodam własne doświadczenie dla tych, którzy będą tego doświadczać w przyszłości. Mój konkretny błąd to

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

Okazuje się, że było to spowodowane tym, że osiągnąłem maksymalną liczbę otwartych plików w systemie. Nie miało to nic wspólnego z nieudanymi połączeniami lub nawet błędem DNS, jak wskazano.

Oded
źródło
0

Dodając własne doświadczenie:

r = requests.get(download_url)

kiedy próbowałem pobrać plik określony w adresie URL.

Błąd był

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

Poprawiłem to, dodając verify = Falsefunkcję w następujący sposób:

r = requests.get(download_url + filename)
open(filename, 'wb').write(r.content)
Suraj Subramanian
źródło
-1

Dodaj nagłówki dla tego żądania.

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
źródło