Número máximo de tentativas excedido com URL nas solicitações

151

Estou tentando obter o conteúdo da App Store> Empresas :

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)

Quando eu tento o rangecom (0,2)ele funciona, mas quando eu coloco o rangein 100s mostra este erro:

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
fonte
1
Você não deve usar ivariável em algum lugar no for?
Laurent S.
você é como solicitar o mesmo aplicativo 100 vezes. para que é isso?
Njzk2
Estou usando i no restante do código. Eu não
publiquei
Não estou solicitando o mesmo aplicativo 100 vezes. Estou solicitando 100 aplicativos diferentes na mesma categoria.
precisa saber é o seguinte
3
Parece que seu resolvedor de DNS não pode resolver itunes.apple.com. Você pode executar dig itunes.apple.comna sua linha de comando e postar os resultados aqui?
Thomas Orozco

Respostas:

141

O que aconteceu aqui é que o servidor do iTunes recusa sua conexão (você está enviando muitas solicitações do mesmo endereço IP em um curto período de tempo)

Número máximo de tentativas excedidas com o URL: / in / app / adobe-reader / id469337564? Mt = 8

O rastreamento de erro é enganoso, deve ser algo como "Nenhuma conexão pôde ser estabelecida porque a máquina de destino a recusou ativamente" .

Existe um problema em sobre python.requests lib no Github, confira aqui

Para superar esse problema (não apenas um problema, mas um rastreamento de depuração enganoso), você deve capturar exceções relacionadas à conexão da seguinte maneira:

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

Outra maneira de superar esse problema é que, se você usar um intervalo de tempo suficiente para enviar solicitações ao servidor, isso poderá ser alcançado por sleep(timeinsec)função em python (não se esqueça de importar a suspensão)

from time import sleep

No geral, todas as solicitações são incríveis, py py, espero que resolva o seu problema.

djra
fonte
2
O loop de suspensão corrigiu meu problema - um pouco, mas, repetindo algumas vezes enquanto lidava com a resposta de erro, eu era capaz de forçar uma solução bruta.
ElPastor 29/03/19
14
Esta resposta está realmente errada. Esse é um problema de pesquisa do resolvedor, conforme indicado pela (Caused by <class 'socket.gaierror'>: [Errno -2] Name or service not known)peça. "gai" significa getaddrinfoe o provável erro relacionado é: EAI_NONAME O nó ou serviço não é conhecido; ou o nó e o serviço são NULL; ou AI_NUMERICSERV foi especificado em hints.ai_flags e service não era uma sequência numérica de número de porta. Provavelmente parecia que o sono o corrigiu, mas você provavelmente apenas dormiu com um problema temporário de resolução de DNS.
lingfish
4
Esta resposta não parece fazer sentido, pois em 'r' é o objeto que vem de orders.get (), portanto, com a exceção, isso apenas leva a outro erro.
Mikkokotila 18/05/19
Esta resposta não faz sentido. O erro do OP não diz "Conexão recusada", mas "Nome ou serviço desconhecido". Esta resposta parece supor que todos os ConnectionError se devam a "Conexão recusada".
erjiang 8/08/19
1
Para mim, isso tem que estar exatamente correto, um limite de taxa colocado pelo servidor. Posso fazer 80 chamadas e essa mensagem será exibida para mim. Depois de pouco tempo, o servidor está disponível para outras 80 chamadas e o ciclo se repete. é muito regular para ser qualquer outra coisa.
demongolem 15/04
122

Basta usar os requests'recursos:

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)

Este será GETo URL e tente novamente 3 vezes em caso de requests.exceptions.ConnectionError. backoff_factorajudará a aplicar atrasos entre tentativas para evitar falhas novamente em caso de cota de solicitação periódica.

Dê uma olhada requests.packages.urllib3.util.retry.Retry, ele tem muitas opções para simplificar novas tentativas.

zulu
fonte
Por qualquer motivo, isso não funciona no Windows 10. Iniciou o shell com python manage.py shelle estou usando session.get('http://localhost:8000/api/'). Qualquer ajuda? @Zulu
MwamiTovi
resolvi meu problema. Tinha esquecido de iniciar o dev-servere mantê-lo funcionando primeiro.
MwamiTovi 23/11/19
Por que ainda não é a melhor resposta?
Pavel Druzhinin
Eu tentei isso, mas ele não tentaria novamente enquanto eu recebia orders.exceptions.ConnectionError A leitura expirou. mas defini um tempo limite para a solicitação de obtenção.
Zagfai 24/04
34

Apenas faça isso,

Cole o seguinte código no 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
fonte
3
lembre-se de fazer import time
Yuan Tao
3
requeststem o seu próprio código para lidar com seu erro e repetição
Zulu
5
Ele nunca sai do loop. @jatin
alper 15/01/18
10
Além disso, não é uma boa ideia capturar qualquer tipo de exceção (com except: ...) de requestse sleep()em resposta. Em vez disso, eles devem capturar requests.exceptions.ConnectionErrore sleep()somente se essa exceção ocorrer. (Ou melhor ainda, basta usar a Retry()classe requestsinterna fornecida , como sugerido pelo @Zulu).
J. Taylor
32

pip install pyopenssl pareceu resolver isso para mim.

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

Akshar
fonte
1
Me ajudou a descobrir o SSL é problema meu
MilaDroid
O mesmo aqui =) Obrigado!
Rodrigo E. Principe
15

Eu tenho um problema semelhante, mas o código a seguir funcionou para mim.

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

"confirm = False" desativa a verificação SSL. Tentar e capturar pode ser adicionado como de costume.

Raj Stha
fonte
5

É sempre bom implementar o tratamento de exceções. Isso não apenas ajuda a evitar a saída inesperada do script, mas também ajuda a registrar erros e notificação de informações. Ao usar solicitações Python, prefiro capturar exceções 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")

Aqui renewIPadress () é uma função de definição do usuário que pode alterar o endereço IP se ele for bloqueado. Você pode ir sem essa função.

Tanmoy Datta
fonte
sua solução é bom, mas como alterar ip-adrressem python, você sabe alguma coisa sobre isso, então deixe-me saber
Haritsinh Gohil
1
Eu tinha usado algum serviço VPN IPVanish e Hide My Ass. Eles são configurados usando open-vpn e open-vpn have row command command, renovando o endereço IP. Você pode chamar o comando shell ou bash do python. Dessa forma, você pode implementá-lo.
Tanmoy Datta 03/09/19
5

A especificação do proxy em um ambiente corporativo resolveu isso para mim.

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

O erro completo é:

orders.exceptions.ConnectionError: HTTPSConnectionPool (host = 'www.google.com', porta = 80): Número máximo de tentativas excedidas com url: / (Causado por NewConnectionError (': falha ao estabelecer uma nova conexão: [WinError 10060]) tentativa falhou porque a parte conectada não respondeu adequadamente após um período de tempo ou a conexão estabelecida falhou porque o host conectado falhou ao responder '))

Jeremy Thompson
fonte
2

Eu não era capaz de fazê-lo funcionar no Windows, mesmo depois de instalar o pyopenssl e tentar várias versões do python (enquanto funcionava bem no mac), então mudei para o urllib e funciona no python 3.6 (do python .org) e 3.7 (anaconda )

import urllib 
from urllib.request import urlopen
html = urlopen("http://pythonscraping.com/pages/page1.html")
contents = html.read()
print(contents)
alex
fonte
Estou bastante irritado que as coisas funcionem apenas se executadas com o prompt do Anaconda.
BingLi224
1

Quando eu estava escrevendo um script de teste do navegador selênio, encontrei esse erro ao ligar driver.quit()antes de usar uma chamada de API JS. Lembre-se de que sair do webdriver é a última coisa a fazer!

Saleh
fonte
1

Adicionando minha própria experiência para aqueles que estão enfrentando isso no futuro. Meu erro específico foi

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

Acontece que isso foi realmente porque eu tinha atingido o número máximo de arquivos abertos no meu sistema. Não tinha nada a ver com conexões com falha ou mesmo com um erro de DNS, conforme indicado.

Oded
fonte
0

Adicionando minha própria experiência:

r = requests.get(download_url)

quando tentei baixar um arquivo especificado no URL.

O erro foi

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

Eu o corrigi adicionando verify = Falsea função da seguinte maneira:

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

Adicione cabeçalhos para esta solicitação.

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
fonte