0
votes

UnboundLocalError: variable locale 'req' référencée avant affectation

J'ai regardé une vidéo et j'ai essayé d'appliquer le code suivant

# pip install html5lib
import requests
from bs4 import BeautifulSoup
from random import choice

def get_proxy():
    url = "https://www.sslproxies.org/"
    r = requests.get(url)
    soup = BeautifulSoup(r.content, 'html5lib')
    return {'https': 'https://' + choice(list(map(lambda x:x[0]+':'+x[1], list(zip(map(lambda x:x.text, soup.findAll('td')[::8]), map(lambda x:x.text, soup.findAll('td')[1::8]))))))}

def proxy_request(request_type, url, **kwargs):
    proxy = get_proxy()
    req = requests.request(request_type, url, proxies=proxy, timeout=5, **kwargs)
    return req

for __ in range(10):
    try:
        r = proxy_request('get', "https://api.ipify.org")
    except (TimeoutError, OSError) as e:
        print("Exception:", e)
        continue

    print(r.status_code)
    print(r.content)
    break

J'ai eu l'erreur de traceback suivante et je n'ai aucune idée

Traceback (most recent call last):
  File "C:\Users\Future\Desktop\Spyder\Demo.py", line 16, in proxy_request
    req = requests.request(request_type, url, proxies=proxy, timeout=5, **kwargs)
  File "C:\Users\Future\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\api.py", line 61, in request
    return session.request(method=method, url=url, **kwargs)
  File "C:\Users\Future\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\sessions.py", line 530, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Users\Future\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\sessions.py", line 643, in send
    r = adapter.send(request, **kwargs)
  File "C:\Users\Future\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\adapters.py", line 412, in send
    conn = self.get_connection(request.url, proxies)
  File "C:\Users\Future\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\adapters.py", line 309, in get_connection
    proxy_manager = self.proxy_manager_for(proxy)
  File "C:\Users\Future\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\adapters.py", line 193, in proxy_manager_for
    manager = self.proxy_manager[proxy] = proxy_from_url(
  File "C:\Users\Future\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\poolmanager.py", line 492, in proxy_from_url
    return ProxyManager(proxy_url=url, **kw)
  File "C:\Users\Future\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\poolmanager.py", line 429, in __init__
    raise ProxySchemeUnknown(proxy.scheme)
urllib3.exceptions.ProxySchemeUnknown: Not supported proxy scheme None

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Future\Desktop\Spyder\Demo.py", line 22, in <module>
    r = proxy_request('get', "https://youtube.com")
  File "C:\Users\Future\Desktop\Spyder\Demo.py", line 20, in proxy_request
    return req
UnboundLocalError: local variable 'req' referenced before assignment
[Finished in 1.4s]

Le code final.

# pip install html5lib
import requests
from bs4 import BeautifulSoup
from random import choice

def get_proxy():
    url = "https://www.sslproxies.org/"
    r = requests.get(url)
    soup = BeautifulSoup(r.content, 'html5lib')
    return {'https': choice(list(map(lambda x:x[0]+':'+x[1], list(zip(map(lambda x:x.text, soup.findAll('td')[::8]), map(lambda x:x.text, soup.findAll('td')[1::8]))))))}

def proxy_request(request_type, url, **kwargs):
    while 1:
        try:
            proxy = get_proxy()
            req = requests.request(request_type, url, proxies=proxy, timeout=5, **kwargs)
            break
        except:
            pass
            return req

r = proxy_request('get', "https://youtube.com")
print(r)


1 commentaires

Quelle valeur attendez-vous pour req si une exception est levée dans le bloc try?


5 Réponses :


0
votes

Il semble que votre paramètre proxy soit égal à None. De cette façon, lorsque vous essayez de créer une demande, il y a une erreur et l'objet de demande n'est pas affecté.

Si vous voulez résoudre ce problème, vous pouvez faire 2 choses différentes:

  1. Après proxy = get_proxy() vous pouvez vérifier si ce n'est pas None et si c'est le cas, vous pouvez configurer vous-même un proxy par défaut.
  2. Vous pouvez essayer d'assigner une nouvelle demande dans la section except et renvoyer l'objet crated.

J'espère que cela a aidé!


0 commentaires

0
votes

Dans votre fonction proxy_request() , définissez req avant d' try ... except , par exemple:

def proxy_request(request_type, url, **kwargs):
    req = None  # <------------------------------- Here
    while 1:
        try:
            proxy = get_proxy()
            req = requests.request(request_type, url, proxies=proxy, timeout=5, **kwargs)
            break
        except:
            pass
            return req

L'explication:

Vous try branche a échoué avant l' req = requests.request(...) commande a été atteinte, de sorte que la branche , except a été réalisée et son return req commande voulait retour inconnue req .


3 commentaires

Merci beaucoup. Il n'y a plus d'erreurs maintenant. Mais j'ai essayé le code plusieurs fois et tout ce que j'ai est None. Y aura-t-il une chance d'obtenir une réponse?


@Yasser, ce n'était qu'un correctif. Maintenant je suis occupé, mais si personne ne le résout, je vais essayer de vous aider.


@Yasser, votre problème est maintenant résolu, voyez mon autre réponse .



2
votes
        try:
            proxy = get_proxy()
            req = requests.request(request_type, url, proxies=proxy, timeout=5, **kwargs)
            break
        except:
            pass
            return req
The return req statement is inside the exception handler, which means it's executed only if an exception is raised during the call to get_proxy or requests.request. Either way, these will lead to req never being bound, hence UnboundLocalError.I expect you wanted to put the return req outside the while loop, though I would just replace the break with it, doing so leads to more straightforward and resilient behaviour.Also:
A bare except is a very bad idea as it's going to catch things like keyboard interruption (Ctrl-C), meaning you'll have to go through the task manager when (not if!) your program fucks up.
When an exception is raised, you just busy loop without even notifying the user of what's happening, without the UnboundLocalError it could just keep looping around calling sslproxies as fast as it can, that's a good way to get banned for abuse, especially when sslproxies clearly advertises that its proxy list is updated every 10 minutes.
Picking a random proxy in the list is fine, but why are you not storing the list of proxies to pick from? See point above, the list is updated at most every 10 minutes and you're not doing any sort of pagination, you're going to get the same list every time. Just fetch the proxies list once outside the loop, then randomly pick a proxy to try from within.

1 commentaires

Merci beaucoup monsieur. Je suis tellement novice en python. Pouvez-vous m'aider à saisir les procurations sous forme de liste, puis m'apprendre à tester cette liste?



1
votes

Si vous souhaitez utiliser un proxy, je peux vous recommander d'utiliser une approche un peu différente et peut-être d'essayer d'utiliser un package python qui essaie de faire ce dont vous avez besoin.

Installez simplement les requêtes proxy et lisez la documentation pour plus d'aide

Installez-le en faisant -> pip install proxy-requests

et envoyer une demande de proxy par

r = ProxyRequests('https://api.ipify.org')
r.get()

bien sûr, il existe un moyen d'envoyer une demande de publication et même de modifier les en-têtes de la demande comme vous le souhaitez


7 commentaires

Merci beaucoup. J'ai essayé from proxy_requests import ProxyRequests et from proxy_requests import ProxyRequests essayé les lignes et je from proxy_requests import ProxyRequests rien obtenu du tout. Est-ce que tu l'as essayé?


Je viens de regarder sa documentation de code et cela a fonctionné pour moi. github.com/rootVIII/proxy_requests En bas de page, vous verrez un exemple qu'il a fait et que j'ai trouvé très utile! C'est une bonne chose car vous pouvez jouer avec les en-têtes et envoyer une demande de publication et voir également le proxy qui était utilisé (peut être pratique parfois)


Pouvez-vous poster un exemple qui a fonctionné avec vous pour essayer de mon côté ??


Vous pouvez essayer ceci par exemple: à partir de proxy_requests import ProxyRequests h = {'User-Agent': 'NCSA Mosaic / 3.0 (Windows 95)'} r = ProxyRequests (' postman-echo.com/headers' ) r.set_headers (h ) r.get_with_headers () print (r.get_proxy_used ())


Merci beaucoup. J'ai exécuté le code et attendu environ deux minutes sans aucune réponse. C'est ce dont je parle.


Mon code n'a pas non plus renvoyé de sortie? parce que cela a fonctionné pour moi ...


Je veux dire que la ligne d'impression ne fonctionnait pas du tout. Cela signifie pour moi que cela n'a pas fonctionné. Ou que voulez-vous dire exactement?



1
votes

Votre code ne fonctionne pas en raison d'un schéma manquant ( https:// ) dans votre proxy renvoyé par votre fonction get_proxy() - par exemple, il renvoie

for __ in range(10):
    try:
        r = proxy_request('get', "https://youtube.com")
    except (TimeoutError, OSError) as e:
        print("Exception:", e)
        continue

    print(r.status_code)
    print(r.content)
    break

au lieu du correct

r = proxy_request('get', "https://youtube.com")
print(r)

Veuillez donc corriger votre déclaration de return dans cette fonction - au lieu de votre

def proxy_request(request_type, url, **kwargs):
    proxy = get_proxy()
    req = requests.request(request_type, url, proxies=proxy, timeout=5, **kwargs)
    return req

utilisation

return {'https': 'https://' + choice(...)}

Note 1:

Vous pouvez simplifier votre autre fonction en déplaçant votre boucle et try ... except bloc dans le niveau module (voir Note 2 ):

return {'https':              choice(...)}

(Vous pouvez inclure print(proxy) et print(req.status_code) à des fins de test.)


Note 2:

Vous pouvez déplacer votre boucle et try ... except bloquer de cette fonction dans le niveau du module, c'est-à-dire lorsque vous appelez cette fonction - au lieu de votre

{'https': 'https://183.89.96.57:8080'}

utiliser par exemple

{'https': '183.89.96.57:8080'}

Note 3:

Je l'ai testé et ça marche - parfois timeout, parfois refus de connexion, mais parfois OK.
(Dans tous les cas, le problème était dans le serveur distant ou dans ma connexion lente.)


5 commentaires

Merci beaucoup. J'ai mis à jour le code pendant que vous m'avez guidé. Veuillez jeter un œil à l'article principal. Maintenant, j'ai essayé le code trois fois sans succès pour obtenir un proxy fonctionnel. Est-il impossible d'obtenir un proxy fonctionnel gratuit?


@Yasser, avez-vous essayé d'augmenter le délai d'attente? Il est possible d'obtenir un proxy fonctionnel gratuit, j'ai eu une telle chance (mais pas très souvent avec ma connexion lente).


@Yasser, par exemple, ce proxy a fonctionné pour moi: 183.89.96.57:8080


J'ai augmenté le délai à 20 et pareil ... Je n'ai pas eu de chance d'obtenir des procurations gratuites.


@Yasser, j'ai utilisé timeout = 150 ;-)