Je joue en essayant d'écrire du code pour utiliser les API tr.im pour raccourcir une URL.
Après avoir lu http://docs.python.org/library/urllib2.html , j'ai essayé:
TRIM_API_URL = 'http://api.tr.im/api'
auth_handler = urllib2.HTTPBasicAuthHandler()
auth_handler.add_password(realm='tr.im',
uri=TRIM_API_URL,
user=USERNAME,
passwd=PASSWORD)
opener = urllib2.build_opener(auth_handler)
urllib2.install_opener(opener)
response = urllib2.urlopen('%s/trim_simple?url=%s'
% (TRIM_API_URL, url_to_trim))
url = response.read().strip()
response.code est 200 (je pense qu'il devrait être 202). url est valide, mais l'authentification HTTP de base ne semble pas avoir fonctionné, car l'URL raccourcie ne figure pas dans ma liste d'URL (sur http://tr.im/?page=1 ).
Après avoir lu http://www.voidspace.org.uk/python/articles/authentication.shtml#doing-it-properly, j'ai également essayé:
TRIM_API_URL = 'api.tr.im/api'
password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
password_mgr.add_password(None, TRIM_API_URL, USERNAME, PASSWORD)
auth_handler = urllib2.HTTPBasicAuthHandler(password_mgr)
opener = urllib2.build_opener(auth_handler)
urllib2.install_opener(opener)
response = urllib2.urlopen('http://%s/trim_simple?url=%s'
% (TRIM_API_URL, url_to_trim))
url = response.read().strip()
Mais j'obtiens les mêmes résultats. (response.code est 200 et l'URL est valide, mais pas enregistrée dans mon compte à http://tr.im/ .)
Si j'utilise des paramètres de chaîne de requête au lieu de l'authentification HTTP de base, comme ceci:
TRIM_API_URL = 'http://api.tr.im/api'
response = urllib2.urlopen('%s/trim_simple?url=%s&username=%s&password=%s'
% (TRIM_API_URL,
url_to_trim,
USERNAME,
PASSWORD))
url = response.read().strip()
... alors non seulement l'URL est valide mais elle est enregistrée dans mon compte tr.im. (Bien que response.code soit toujours 200.)
Il doit y avoir quelque chose qui ne va pas avec mon code (et pas l'API de tr.im), car
$ curl -u yacitus:xxxx http://api.tr.im/api/trim_url.json?url=http://www.google.co.uk
...Retour:
{"trimpath":"hfhb","reference":"nH45bftZDWOX0QpVojeDbOvPDnaRaJ","trimmed":"11\/03\/2009","destination":"http:\/\/www.google.co.uk\/","trim_path":"hfhb","domain":"google.co.uk","url":"http:\/\/tr.im\/hfhb","visits":0,"status":{"result":"OK","code":"200","message":"tr.im URL Added."},"date_time":"2009-03-11T10:15:35-04:00"}
... et l'URL apparaît dans ma liste d'URL sur http://tr.im/?page=1 .
Et si je cours:
$ curl -u yacitus:xxxx http://api.tr.im/api/trim_url.json?url=http://www.google.co.uk
... encore une fois, je reçois:
{"trimpath":"hfhb","reference":"nH45bftZDWOX0QpVojeDbOvPDnaRaJ","trimmed":"11\/03\/2009","destination":"http:\/\/www.google.co.uk\/","trim_path":"hfhb","domain":"google.co.uk","url":"http:\/\/tr.im\/hfhb","visits":0,"status":{"result":"OK","code":"201","message":"tr.im URL Already Created [yacitus]."},"date_time":"2009-03-11T10:15:35-04:00"}
Le code de note est 201 et le message est "URL tr.im déjà créée [yacitus]".
Je ne dois pas faire correctement l'authentification HTTP de base (dans les deux tentatives). Pouvez-vous repérer mon problème? Peut-être que je devrais regarder et voir ce qui est envoyé sur le fil? Je n'ai jamais fait ça avant. Y a-t-il des API Python que je peux utiliser (peut-être dans pdb)? Ou y a-t-il un autre outil (de préférence pour Mac OS X) que je peux utiliser?
la source
"WWW-Authenticate"
et le code 401 avant que urllib2 (ou httplib2) envoie vos identifiants. Voir ma réponse ci-dessous .Réponses:
Cela semble très bien fonctionner (tiré d'un autre fil)
import urllib2, base64 request = urllib2.Request("http://api.foursquare.com/v1/user") base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '') request.add_header("Authorization", "Basic %s" % base64string) result = urllib2.urlopen(request)
la source
request.add_header('Authorization', b'Basic ' + base64.b64encode(username + b':' + password))
Solution vraiment bon marché:
urllib.urlopen('http://user:[email protected]/api')
(ce que vous pouvez décider ne convient pas pour un certain nombre de raisons, comme la sécurité de l'url)
Exemple d'API Github :
>>> import urllib, json >>> result = urllib.urlopen('https://personal-access-token:[email protected]/repos/:owner/:repo') >>> r = json.load(result.fp) >>> result.close()
la source
Jetez un œil à cette réponse post SO et regardez également ce didacticiel d'authentification de base du manuel manquant urllib2 .
Pour que l'authentification de base urllib2 fonctionne, la réponse http doit contenir le code HTTP 401 Unauthorized et une clé
"WWW-Authenticate"
avec la valeur"Basic"
sinon, Python n'enverra pas vos informations de connexion, et vous devrez soit utiliser Requests , soiturllib.urlopen(url)
avec votre login dans le url, ou ajoutez un en-tête comme dans la réponse de @ Flowpoke .Vous pouvez afficher votre erreur en mettant votre
urlopen
dans un bloc try:try: urllib2.urlopen(urllib2.Request(url)) except urllib2.HTTPError, e: print e.headers print e.headers.has_key('WWW-Authenticate')
la source
La méthode recommandée est d'utiliser le
requests
module :#!/usr/bin/env python import requests # $ python -m pip install requests ####from pip._vendor import requests # bundled with python url = 'https://httpbin.org/hidden-basic-auth/user/passwd' user, password = 'user', 'passwd' r = requests.get(url, auth=(user, password)) # send auth unconditionally r.raise_for_status() # raise an exception if the authentication fails
Voici une
urllib2
variante basée sur la compatibilité Python 2/3 à source unique :#!/usr/bin/env python import base64 try: from urllib.request import Request, urlopen except ImportError: # Python 2 from urllib2 import Request, urlopen credentials = '{user}:{password}'.format(**vars()).encode() urlopen(Request(url, headers={'Authorization': # send auth unconditionally b'Basic ' + base64.b64encode(credentials)})).close()
Python 3.5+ introduit
HTTPPasswordMgrWithPriorAuth()
qui permet:#!/usr/bin/env python3 import urllib.request as urllib2 password_manager = urllib2.HTTPPasswordMgrWithPriorAuth() password_manager.add_password(None, url, user, password, is_authenticated=True) # to handle 404 variant auth_manager = urllib2.HTTPBasicAuthHandler(password_manager) opener = urllib2.build_opener(auth_manager) opener.open(url).close()
Il est facile de remplacer
HTTPBasicAuthHandler()
avecProxyBasicAuthHandler()
si nécessaire dans ce cas.la source
Je suggérerais que la solution actuelle soit d'utiliser mon package urllib2_prior_auth qui résout ce problème assez bien (je travaille sur l' inclusion dans la bibliothèque standard.
la source
urrlib.request.HTTPBasicPriorAuthHandler
Les mêmes solutions que Python urllib2 Basic Auth Problem s'appliquent.
voir https://stackoverflow.com/a/24048852/1733117 ; vous pouvez sous-classer
urllib2.HTTPBasicAuthHandler
pour ajouter l'en-Authorization
tête à chaque demande qui correspond à l'url connue.class PreemptiveBasicAuthHandler(urllib2.HTTPBasicAuthHandler): '''Preemptive basic auth. Instead of waiting for a 403 to then retry with the credentials, send the credentials if the url is handled by the password manager. Note: please use realm=None when calling add_password.''' def http_request(self, req): url = req.get_full_url() realm = None # this is very similar to the code from retry_http_basic_auth() # but returns a request object. user, pw = self.passwd.find_user_password(realm, url) if pw: raw = "%s:%s" % (user, pw) auth = 'Basic %s' % base64.b64encode(raw).strip() req.add_unredirected_header(self.auth_header, auth) return req https_request = http_request
la source
strip
redondant aprèsb64encode
?Essayez python-request ou python-grab
la source