পাইথন urllib2, বেসিক HTTP প্রমাণীকরণ, এবং tr.im


85

আমি প্রায় খেলছি, URL টি ছোট করার জন্য tr.im এপিআই ব্যবহার করতে কিছু কোড লেখার চেষ্টা করছি ।

Http://docs.python.org/library/urllib2.html পড়ার পরে , আমি চেষ্টা করেছি:

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

প্রতিক্রিয়া কোডটি 200 (আমার মনে হয় এটি 202 হওয়া উচিত)। ইউআরএলটি বৈধ, তবে প্রাথমিক HTTP প্রমাণীকরণটি কাজ করেছে বলে মনে হয় না, কারণ সংক্ষিপ্ত URL টি আমার URL গুলির তালিকায় নেই ( http://tr.im/?page=1- এ ))

Http://www.voidspace.org.uk/python/articles/authentication.shtml#doing-it-papererly পড়ার পরে আমি চেষ্টাও করেছি:

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

তবে আমি একই ফলাফল পেতে। (প্রতিক্রিয়া কোডটি 200 এবং url বৈধ, তবে http://tr.im/ এ আমার অ্যাকাউন্টে রেকর্ড করা হয়নি )

আমি যদি বেসিক এইচটিটিপি প্রমাণীকরণের পরিবর্তে কোয়েরি স্ট্রিং প্যারামিটার ব্যবহার করি তবে:

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

... তবে শুধুমাত্র ইউআরএল বৈধ নয় এটি আমার ট্রিম আইনে অ্যাকাউন্টে রেকর্ড করা আছে। (যদিও প্রতিক্রিয়া কোড এখনও 200) is

আমার কোডে অবশ্যই কিছু ভুল থাকতে হবে (এবং ট্রিমিমের এপিআই নয়), কারণ

$ curl -u yacitus:xxxx http://api.tr.im/api/trim_url.json?url=http://www.google.co.uk

... ফেরত:

{"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"}

... এবং URL এ URL গুলির আমার তালিকায় প্রদর্শিত হচ্ছে না http://tr.im/?page=1

এবং যদি আমি চালাতে পারি:

$ curl -u yacitus:xxxx http://api.tr.im/api/trim_url.json?url=http://www.google.co.uk

... আবার, আমি পেয়েছি:

{"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"}

নোট কোডটি 201, এবং বার্তাটি "tr.im URL ইতিমধ্যে তৈরি [ইয়াসিটাস]"।

আমি অবশ্যই বেসিক এইচটিটিপি প্রমাণীকরণ সঠিকভাবে করব না (উভয় প্রয়াসে)। আপনি আমার সমস্যা স্পট করতে পারেন? সম্ভবত আমার সন্ধান করা উচিত এবং তারের উপরে কী পাঠানো হচ্ছে তা দেখতে হবে? আমি এর আগে কখনও করিনি। পাইথন এপিআইগুলি কি আমি ব্যবহার করতে পারি (সম্ভবত পিডিবিতে)? বা অন্য কোনও সরঞ্জাম আছে (ম্যাক ওএস এক্সের পক্ষে ভাল) আমি ব্যবহার করতে পারি?


4
"WWW-Authenticate"urllib2 (বা httplib2) আপনার শংসাপত্র প্রেরণের আগে অবশ্যই সাইটের অবশ্যই 401 কোডটি পাঠানো উচিত এবং কোডটি অবশ্যই । আমার উত্তর নীচে দেখুন
মার্ক মিকোফস্কি

দ্রষ্টব্য: এই পরিষেবাটি অকার্যকর বলে মনে হচ্ছে।
লরেল

উত্তর:


247

এটি সত্যিই ভালভাবে কাজ করছে বলে মনে হচ্ছে (অন্য থ্রেড থেকে নেওয়া)

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)

7
বেস 64.encodestring এবং প্রতিস্থাপনের পরিবর্তে base64.standard_b64encode
পাওয়ে পোলুইচজ

4
request.add_header('Authorization', b'Basic ' + base64.b64encode(username + b':' + password))
jfs

4
এই উত্তরের উপর ভিত্তি করে আমি urlib2_prior_auth একটি প্যাকেজ তৈরি করেছি যার stdlib এর বাইরে কোনও নির্ভরতা নেই এবং আমি প্রাসঙ্গিক পরিবর্তনটি stdlib এ ঠেলে দেওয়ার চেষ্টা করি
mcepl

4
অথবা এমনকি ছোট / আমদানি এড়ানো: অনুরোধ.এডডি_হেডার ('অনুমোদন', বি'ব্যাসিক '+ (ব্যবহারকারীর নাম + বি': '+ পাসওয়ার্ড)। এনকোড (' বেস64 '))
মাকাপুফ

20

সত্যিই সস্তা সমাধান:

urllib.urlopen('http://user:xxxx@api.tr.im/api')

(যা আপনি সিদ্ধান্ত নিতে পারেন তা URL এর সুরক্ষার মতো বিভিন্ন কারণে উপযুক্ত নয়)

গিথুব এপিআই উদাহরণ :

>>> import urllib, json
>>> result = urllib.urlopen('https://personal-access-token:x-oauth-basic@api.github.com/repos/:owner/:repo')
>>> r = json.load(result.fp)
>>> result.close()

ক্যোরিয় স্ট্রিং প্যারামিটারগুলি ব্যবহার করে এর কোনও সুবিধা আছে?
ড্যারিল স্পিজিটর

4
ড্যারিল: যদি এটি কাজ করে তবে আমি বলব যে এটি হ'ল একটি সুবিধা এবং সম্ভবত বেশিরভাগ পোস্ট ক্লায়েন্টরা কীভাবে সেগুলি পরিচালনা করে সে সম্পর্কে আরও যত্নশীল careful
আলী আফশার

আমি সম্ভবত এটির সাথে যাব (যাতে আপনি আমার উত্সাহটি পেতে পারেন), তবে আমি এখনও আমার কোডটিতে কী কী সমস্যা আছে তা বের করতে চাই (যাতে এটি আমার গৃহীত উত্তর হবে না)।
ড্যারিল স্পিজিটর

36
এটি একটি ত্রুটি ফেরায় ... অবৈধ ইউআরএল: সংখ্যাসূচক পোর্ট: 'xxxx@api.tr.im/api'
নিক বল্টন

4
@ নলবোন নিশ্চিত করুন যে আপনি urllib2.urlopen (url) ব্যবহার করছেন না
ক্যান্টগেটানিক

13

কটাক্ষপাত এই তাই পোস্টে উত্তর এবং এই তাকান মৌলিক প্রমাণীকরণ টিউটোরিয়াল থেকে urllib2 ম্যানুয়াল অনুপস্থিত

কাজ করার জন্য urllib2 মৌলিক প্রমাণীকরণের জন্য, HTTP প্রতিক্রিয়াতে অবশ্যই HTTP কোড 401 অননুমোদিত এবং"WWW-Authenticate" মান সহ একটি কী থাকা উচিত "Basic", অন্যথায় পাইথন আপনার লগইন তথ্য প্রেরণ করবে না, এবং আপনাকে অনুরোধগুলি ব্যবহার করতে হবে , বা urllib.urlopen(url)আপনার লগইন সহ url, বা @ ফ্লোপোকের উত্তরের মতো একটি শিরোনাম যুক্ত করুন ।

urlopenচেষ্টা করে দেখতে চেষ্টা করে নিজের ত্রুটিটি দেখতে পারেন :

try:
    urllib2.urlopen(urllib2.Request(url))
except urllib2.HTTPError, e:
    print e.headers
    print e.headers.has_key('WWW-Authenticate')

এটি আমাকে সহায়তা করেছিল কারণ শিরোনামগুলি মুদ্রণের ফলে আমি বুঝতে পারি যে আমি প্রমাণীকরণের ক্ষেত্রটি টাইপ করেছি। +1
ফ্রিস্পেস

7

প্রস্তাবিত উপায় হ'ল requestsমডিউলটি ব্যবহার করা :

#!/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

পাইথন 2/3 সামঞ্জস্যপূর্ণ- urllib2ভিত্তিক বৈকল্পিকটি এখানে একটি একক উত্স :

#!/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()

পাইথন ৩.৫+ প্রবর্তন করেHTTPPasswordMgrWithPriorAuth() যা এতে অনুমতি দেয়:

.. অপ্রয়োজনীয় 401 প্রতিক্রিয়া হ্যান্ডলিং অপসারণ করতে, বা অনুমোদনের শিরোনাম না প্রেরণ করা হলে 401 এর পরিবর্তে 404 জবাব ফেরত সার্ভারের সাথে যোগাযোগ করার জন্য নিঃশর্তভাবে প্রথম অনুরোধে শংসাপত্রগুলি প্রেরণ ..

#!/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()

এই ক্ষেত্রে প্রয়োজনে এটির HTTPBasicAuthHandler()সাথে প্রতিস্থাপন করা সহজ ProxyBasicAuthHandler()


4

আমি সুপারিশ করব যে বর্তমান সমাধানটি আমার প্যাকেজ urllib2_prior_auth ব্যবহার করা যা এটি সুন্দরভাবে সমাধান করে (আমি স্ট্যান্ডার্ড লিবের অন্তর্ভুক্তিতে কাজ করি ।


4
এটি পাইথন 3.5 তে অন্তর্ভুক্ত করা হয়েছেurrlib.request.HTTPBasicPriorAuthHandler
এমসপেল

3

পাইথন urllib2 বেসিক অ্যাথ সমস্যা হিসাবে একই সমাধান ।

দেখতে https://stackoverflow.com/a/24048852/1733117 ; পরিচিত url- এর সাথে মেলে এমন প্রতিটি অনুরোধে শিরোনাম urllib2.HTTPBasicAuthHandlerযুক্ত করতে আপনি সাবক্লাস করতে পারেন Authorization

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

stripঅনর্থক কল কি পরে নেই b64encode?
মিহাই টডর

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.