पायथन में दिए गए URL में params जोड़ें


125

मान लीजिए मुझे एक URL दिया गया।
इसमें पहले से ही GET मानदंड हो सकते हैं (जैसे http://example.com/search?q=question) या यह नहीं हो सकता (जैसे http://example.com/)।

और अब मुझे इसकी तरह कुछ पैरामीटर जोड़ने की जरूरत है {'lang':'en','tag':'python'}। पहले मामले में मैं जा रहा हूँ http://example.com/search?q=question&lang=en&tag=pythonऔर दूसरे में - http://example.com/search?lang=en&tag=python

क्या ऐसा करने का कोई मानक तरीका है?

जवाबों:


180

वहाँ urllibऔर urlparseमॉड्यूल के साथ quirks के एक जोड़े हैं । यहाँ एक काम कर उदाहरण है:

try:
    import urlparse
    from urllib import urlencode
except: # For Python 3
    import urllib.parse as urlparse
    from urllib.parse import urlencode

url = "http://stackoverflow.com/search?q=question"
params = {'lang':'en','tag':'python'}

url_parts = list(urlparse.urlparse(url))
query = dict(urlparse.parse_qsl(url_parts[4]))
query.update(params)

url_parts[4] = urlencode(query)

print(urlparse.urlunparse(url_parts))

ParseResult, का परिणाम urlparse(), केवल-पढ़ने के लिए है और हमें listइसके डेटा को संशोधित करने का प्रयास करने से पहले इसे परिवर्तित करने की आवश्यकता है ।


13
आप शायद urlparse.parse_qsइसके बजाय उपयोग करना चाहते हैं parse_qsl। उत्तरार्द्ध एक सूची देता है जबकि आप एक तानाशाही चाहते हैं। Docs.python.org/library/urlparse.html#urlparse.parse_qs देखें ।
फ्लोरियन ब्रूनर

11
@florian: अजगर 2.7 में कम से कम आप तो कॉल करने की आवश्यकता urlencodeके रूप में urllib.urlencode(query, doseq=True)। अन्यथा, मूल url में मौजूद पैरामीटर सही ढंग से संरक्षित नहीं किए गए हैं (क्योंकि वे @ parse_qs @ से tuples के रूप में वापस आ गए हैं
rluba

5
मैंने इसे पायथन 3 में भी काम करने के लिए फिर से लिखा है। यहाँ कोड
द्वितीया_

12
के परिणाम urlparse()और urlsplit()वास्तव में namedtupleउदाहरण हैं। इस प्रकार आप उन्हें एक चर में सीधे असाइन कर सकते हैं और url_parts = url_parts._replace(query = …)इसे अपडेट करने के लिए उपयोग कर सकते हैं ।
फुएरमुरमेल

2
सावधानी - यह कार्यान्वयन कुछ क्वेरी सेवाओं का उपयोग करने वाले दोहराए गए क्वेरी मापदंडों को हटा देता है। थोड़े संशोधन के साथ इसे ठीक किया जा सकता है। क्वेरी = urlparse.parse_qsl (url_parts [4]) क्वेरी + = params.items () लेकिन यदि आप क्वेरी का उपयोग कर बाहर निकलने की जगह बदलना चाहते हैं, तो थोड़ा अधिक लगता है।
ombre42

51

क्यों

मैं इस पृष्ठ पर सभी समाधानों से संतुष्ट नहीं हूं ( आओ, हमारी पसंदीदा कॉपी-पेस्ट चीज़ कहां है? ) इसलिए मैंने यहां जवाबों के आधार पर अपना स्वयं का लिखा। यह पूर्ण और अधिक पायथोनिक होने की कोशिश करता है। मैंने अधिक उपभोक्ता-पक्ष ( जेएस ) के अनुकूल होने के लिए तर्कों में तानाशाही और बूल मूल्यों के लिए एक हैंडलर जोड़ा है , लेकिन वे अभी तक वैकल्पिक हैं, आप उन्हें छोड़ सकते हैं।

यह काम किस प्रकार करता है

टेस्ट 1: नए तर्क जोड़ना, एरे और बूल मान को संभालना:

url = 'http://stackoverflow.com/test'
new_params = {'answers': False, 'data': ['some','values']}

add_url_params(url, new_params) == \
    'http://stackoverflow.com/test?data=some&data=values&answers=false'

टेस्ट 2: मौजूदा आर्ग को फिर से बनाना, DICT मानों को संभालना:

url = 'http://stackoverflow.com/test/?question=false'
new_params = {'question': {'__X__':'__Y__'}}

add_url_params(url, new_params) == \
    'http://stackoverflow.com/test/?question=%7B%22__X__%22%3A+%22__Y__%22%7D'

बोलना आसान है। मुझे कोड दिखाओ।

कोड ही। मैंने इसका विवरण देने की कोशिश की है:

from json import dumps

try:
    from urllib import urlencode, unquote
    from urlparse import urlparse, parse_qsl, ParseResult
except ImportError:
    # Python 3 fallback
    from urllib.parse import (
        urlencode, unquote, urlparse, parse_qsl, ParseResult
    )


def add_url_params(url, params):
    """ Add GET params to provided URL being aware of existing.

    :param url: string of target URL
    :param params: dict containing requested params to be added
    :return: string with updated URL

    >> url = 'http://stackoverflow.com/test?answers=true'
    >> new_params = {'answers': False, 'data': ['some','values']}
    >> add_url_params(url, new_params)
    'http://stackoverflow.com/test?data=some&data=values&answers=false'
    """
    # Unquoting URL first so we don't loose existing args
    url = unquote(url)
    # Extracting url info
    parsed_url = urlparse(url)
    # Extracting URL arguments from parsed URL
    get_args = parsed_url.query
    # Converting URL arguments to dict
    parsed_get_args = dict(parse_qsl(get_args))
    # Merging URL arguments dict with new params
    parsed_get_args.update(params)

    # Bool and Dict values should be converted to json-friendly values
    # you may throw this part away if you don't like it :)
    parsed_get_args.update(
        {k: dumps(v) for k, v in parsed_get_args.items()
         if isinstance(v, (bool, dict))}
    )

    # Converting URL argument to proper query string
    encoded_get_args = urlencode(parsed_get_args, doseq=True)
    # Creating new parsed result object based on provided with new
    # URL arguments. Same thing happens inside of urlparse.
    new_url = ParseResult(
        parsed_url.scheme, parsed_url.netloc, parsed_url.path,
        parsed_url.params, encoded_get_args, parsed_url.fragment
    ).geturl()

    return new_url

कृपया ध्यान रखें कि कुछ समस्याएँ हो सकती हैं, यदि आपको एक मिल जाए तो कृपया मुझे बताएं और हम इस बात को बेहतर बनाएंगे


शायद पायलटन 3 समर्थन को शामिल करने के लिए urllib.parse को छोड़कर एक कोशिश जोड़ें? स्निपेट के लिए धन्यवाद, बहुत उपयोगी!
मैट जुव

शायद आयात भी जोड़ सकते हैं?
क्रिस्टोफ रूसो

यूनेकोड्स ने इनडेल्स को उकसाया जैसे http://stackoverflow.com/with%2Fencoded?data=some&data=values&answe%2rs=false। इसके अलावा, तीन शेवरॉन >>>का उपयोग करें, जो आपके सिद्धांतों को बढ़ाने में मदद करने के लिए
pelson

क्यों नहीं बदल parsed_get_args = dict(parse_qsl(get_args))करने के लिएparsed_get_args = parse_qs(get_args)
मैट एम

41

आप URL एन्कोडिंग का उपयोग करना चाहते हैं यदि स्ट्रिंग्स में मनमाना डेटा हो सकता है (उदाहरण के लिए, वर्ण जैसे कि एम्परसेंड, स्लैश, आदि को इनकोड करना होगा)।

Urllib.urlencode देखें:

>>> import urllib
>>> urllib.urlencode({'lang':'en','tag':'python'})
'lang=en&tag=python'

अजगर 3 में:

from urllib import parse
parse.urlencode({'lang':'en','tag':'python'})

5
अजगर 3 में, इसे urllib.parse.urlencode
shad0w_wa1k3r

23

आप फ़र्ल मॉड्यूल https://github.com/gruns/furl का भी उपयोग कर सकते हैं

>>> from furl import furl
>>> print furl('http://example.com/search?q=question').add({'lang':'en','tag':'python'}).url
http://example.com/search?q=question&lang=en&tag=python

21

लड़ाई परीक्षण पुस्तकालय के लिए इसे आउटसोर्स ।

यह मैं इसे कैसे करूंगा:

from requests.models import PreparedRequest
url = 'http://example.com/search?q=question'
params = {'lang':'en','tag':'python'}
req = PreparedRequest()
req.prepare_url(url, params)
print(req.url)

17

यदि आप अनुरोधों का उपयोग कर रहे हैं :

import requests
...
params = {'tag': 'python'}
requests.get(url, params=params)

1
@chefhose सवाल है ... किसके सापेक्ष? आप एक वेब पेज में नहीं हैं, इसके सापेक्ष होने का कोई संदर्भ नहीं है।
क्रिस्टोफ रूसो

11

हाँ: urllib का उपयोग करें ।

प्रलेखन में उदाहरणों से :

>>> import urllib
>>> params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
>>> f = urllib.urlopen("http://www.musi-cal.com/cgi-bin/query?%s" % params)
>>> print f.geturl() # Prints the final URL with parameters.
>>> print f.read() # Prints the contents

1
क्या आप कुछ संक्षिप्त उदाहरण दे सकते हैं?
z4y4ts

1
f.read () आपको HTML पेज दिखाएगा। कॉलिंग url देखने के लिए f.geturl ()
ccheneson

5
-1 URL (जो वास्तव में मूल स्ट्रिंग हेरफेर है) को पार्स करने के लिए HTTP अनुरोध का उपयोग करने के लिए। साथ ही वास्तविक समस्या पर विचार नहीं किया जाता है, क्योंकि आपको यह जानना होगा कि URL क्वेरी स्ट्रिंग को सही तरीके से जोड़ने में सक्षम होने के लिए कैसा दिखता है।
प्रहार

या तो लेखक ने प्रश्न को संपादित किया या तो यह उत्तर उससे संबंधित नहीं है।
सिंपलीस्ज़

11

इस उत्तर के आधार पर , साधारण मामलों के लिए एक-लाइनर (पायथन 3 कोड):

from urllib.parse import urlparse, urlencode


url = "https://stackoverflow.com/search?q=question"
params = {'lang':'en','tag':'python'}

url += ('&' if urlparse(url).query else '?') + urlencode(params)

या:

url += ('&', '?')[urlparse(url).query == ''] + urlencode(params)

4
मुझे पता है कि आपने "सरल मामलों" का उल्लेख किया है, लेकिन स्पष्ट करने के लिए: यदि ?एंकर ( #?stuff) में है तो यह ठीक से काम नहीं करेगा ।
यन दोनदल

7

मुझे यह दो शीर्ष उत्तरों की तुलना में अधिक सुरुचिपूर्ण लगता है:

from urllib.parse import urlencode, urlparse, parse_qs

def merge_url_query_params(url: str, additional_params: dict) -> str:
    url_components = urlparse(url)
    original_params = parse_qs(url_components.query)
    # Before Python 3.5 you could update original_params with 
    # additional_params, but here all the variables are immutable.
    merged_params = {**original_params, **additional_params}
    updated_query = urlencode(merged_params, doseq=True)
    # _replace() is how you can create a new NamedTuple with a changed field
    return url_components._replace(query=updated_query).geturl()

assert merge_url_query_params(
    'http://example.com/search?q=question',
    {'lang':'en','tag':'python'},
) == 'http://example.com/search?q=question&lang=en&tag=python'

सबसे महत्वपूर्ण चीजें जो मुझे शीर्ष उत्तरों में नापसंद हैं (वे फिर भी अच्छे हैं):

  • Łukasz: queryURL घटकों में सूचकांक को याद रखने के लिए
  • नीलमणि: अद्यतन बनाने का बहुत ही क्रियात्मक तरीका ParseResult

मेरी प्रतिक्रिया के बारे में क्या बुरा है, यह अनपैकिंग dictका उपयोग करके जादुई रूप से मर्ज लग रहा है, लेकिन मैं पसंद करता हूं कि उत्परिवर्तन के खिलाफ मेरे पूर्वाग्रह के कारण पहले से ही मौजूद शब्दकोश को अपडेट करना।


6

मुझे likedukasz संस्करण पसंद है, लेकिन चूंकि urllib और urllparse फ़ंक्शन इस मामले में उपयोग करने के लिए कुछ अजीब हैं, इसलिए मुझे लगता है कि इस तरह से कुछ करना अधिक सरल है:

params = urllib.urlencode(params)

if urlparse.urlparse(url)[4]:
    print url + '&' + params
else:
    print url + '?' + params

4
[4] के बजाय .query के बारे में कैसे?
डेब्बी मेंडेज़

4

संयुक्त शब्दकोश पर urlparseमौजूदा URL को अलग करने के लिए विभिन्न कार्यों का उपयोग करें urllib.urlencode(), फिर urlparse.urlunparse()सभी को एक साथ फिर से वापस लाने के लिए।

या बस के परिणाम को लेने urllib.urlencode()और इसे उचित रूप से URL पर ले जाएं।


3

अभी तक एक और जवाब:

def addGetParameters(url, newParams):
    (scheme, netloc, path, params, query, fragment) = urlparse.urlparse(url)
    queryList = urlparse.parse_qsl(query, keep_blank_values=True)
    for key in newParams:
        queryList.append((key, newParams[key]))
    return urlparse.urlunparse((scheme, netloc, path, params, urllib.urlencode(queryList), fragment))

2

यहां बताया गया है कि मैंने इसे कैसे लागू किया।

import urllib

params = urllib.urlencode({'lang':'en','tag':'python'})
url = ''
if request.GET:
   url = request.url + '&' + params
else:
   url = request.url + '?' + params    

एक जादू की तरह काम किया। हालाँकि, मुझे इसे लागू करने के लिए अधिक क्लीनर तरीका पसंद आया होगा।

ऊपर लागू करने का एक और तरीका इसे एक विधि में रखा गया है।

import urllib

def add_url_param(request, **params):
   new_url = ''
   _params = dict(**params)
   _params = urllib.urlencode(_params)

   if _params:
      if request.GET:
         new_url = request.url + '&' + _params
      else:
         new_url = request.url + '?' + _params
   else:
      new_url = request.url

   return new_ur

1

अजगर 2.5 में

import cgi
import urllib
import urlparse

def add_url_param(url, **params):
    n=3
    parts = list(urlparse.urlsplit(url))
    d = dict(cgi.parse_qsl(parts[n])) # use cgi.parse_qs for list values
    d.update(params)
    parts[n]=urllib.urlencode(d)
    return urlparse.urlunsplit(parts)

url = "http://stackoverflow.com/search?q=question"
add_url_param(url, lang='en') == "http://stackoverflow.com/search?q=question&lang=en"
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.