【问题标题】:Python: How to only URL Encode a specific URL Parameter?Python:如何仅对特定的 URL 参数进行 URL 编码?
【发布时间】:2021-11-17 01:16:24
【问题描述】:

我有一些包含大量 URL 参数的大 URL。

对于我的具体情况,当“q=”之后的内容以斜杠(“/”)开头时,我需要对一个特定URL参数(q)的内容进行URL编码

示例网址:

https://www.exmple.com/test?test1=abc&test2=abc&test3=abc&q=/"TEST"/"TEST"

如何仅对“q”参数内的 URL 的最后一部分进行 URL 编码?

这个例子的输出应该是:

https://www.exmple.com/test?test1=abc&test2=abc&test3=abc&q=%2F%22TEST%22%2F%22TEST%22%20

我已经用 urllib.parse 尝试了一些不同的东西,但它没有按照我想要的方式工作。

感谢您的帮助!

【问题讨论】:

  • 请将您诚实尝试解决此问题的代码编辑为minimal reproducible example,包括一些输入示例以及您想要生成的输出。

标签: python urllib urlencode urllib3


【解决方案1】:

&q=/部分分割字符串,只编码最后一个字符串

from urllib import parse

url = 'https://www.exmple.com/test?test1=abc&test2=abc&test3=abc&q=/"TEST"/"TEST"'
encoded = parse.quote_plus(url.split("&q=/")[1])
encoded_url = f"{url.split('&q=/')[0]}&q=/{encoded}"
print(encoded_url)

输出

https://www.exmple.com/test?test1=abc&test2=abc&test3=abc&q=%2F%22TEST%22%2F%22TEST%22

请注意,这与请求的输出之间存在差异,但最后有一个 url 编码空间 (%20)


编辑

注释显示了对编码的不同需求,因此代码需要稍作更改。下面的代码只对&q=之后的部分进行编码。基本上,首先拆分url和参数,然后遍历参数以找到q=参数,并对那部分进行编码。做一些 f-string 并加入魔法,你会得到一个带有 q 参数编码的 url。请注意,如果需要编码的部分中存在&,这可能会出现问题。

url = 'https://www.exmple.com/test?test1=abc&test2=abc&test3=abc&q=/"TEST"/"TEST"&utm_source=test1&cpc=123&gclid=abc123'
# the first parameter is always delimited by a ?
baseurl, parameters = url.split("?")
newparameters = []
for parameter in parameters.split("&"):
    # check if the parameter is the part that needs to be encoded
    if parameter.startswith("q="):
        # encode the parameter
        newparameters.append(f"q={parse.quote_plus(parameter[2:])}")
    else:
        # otherwise add the parameter unencoded
        newparameters.append(parameter)
# string magic to create the encoded url
encoded_url = f"{baseurl}?{'&'.join(newparameters)}"
print(encoded_url)

输出

https://www.exmple.com/test?test1=abc&test2=abc&test3=abc&q=%2F%22TEST%22%2F%22TEST%22&utm_source=test1&cpc=123&gclid=abc123

编辑 2

试图解决要编码的字符串中有& 字符的边缘情况,因为这会弄乱string.split("&")
我尝试使用 urllib.parse.parse_qs() 但这与 & 字符有相同的问题。 Docs供参考。

这个问题是一个很好的例子,说明边缘情况如何混淆简单的逻辑并使其过于复杂。

RFC3986 也没有对查询字符串的名称指定任何限制,否则本可以用来进一步缩小可能的错误范围。

更新代码

from urllib import parse


url = 'https://www.exmple.com/test?test1=abc&test2=abc&test3=abc&q=/"TEST"/&"TE&eeST"&utm_source=test1&cpc=123&gclid=abc123'
# the first parameter is always delimited by a ?
baseurl, parameters = url.split("?")

# addition to handle & in the querystring.
# it reduces errors, but it can still mess up if there's a = in the part to be encoded.
split_parameters = []
for index, parameter in enumerate(parameters.split("&")):
    if "=" not in parameter:
        # add this part to the previous entry in split_parameters
        split_parameters[-1] += f"&{parameter}"
    else:
        split_parameters.append(parameter)


newparameters = []
for parameter in split_parameters:
    # check if the parameter is the part that needs to be encoded
    if parameter.startswith("q="):
        # encode the parameter
        newparameters.append(f"q={parse.quote_plus(parameter[2:])}")
    else:
        # otherwise add the parameter unencoded
        newparameters.append(parameter)
# string magic to create the encoded url
encoded_url = f"{baseurl}?{'&'.join(newparameters)}"
print(encoded_url)

输出

https://www.exmple.com/test?test1=abc&test2=abc&test3=abc&q=%2F%22TEST%22%2F%26%22TE%26eeST%22&utm_source=test1&cpc=123&gclid=abc123

【讨论】:

  • 感谢您的大力帮助。我的代码还有一个问题。有时,在 q 参数之后还有更多参数。使用您的代码,其他参数也会得到我不想要的 URL 编码。如何确保只有 q 参数的内容被编码,无论它位于 URL 中的哪个位置?我想我必须解析 URL,而不仅仅是在某个时候拆分它,但我无法弄清楚如何准确地做到这一点。示例网址:exmple.com/test?test1=abc&test2=abc&test3=abc&q=/…
  • 查看我的编辑。这需要更多的逻辑,如果要编码的部分中存在& 字符,则会出现问题
  • @EdoAkse 我几乎添加了一个与你相同的答案(除了我称它们为“args”而你称它们为“参数”)。干得好!
  • @RufusVS 我从你那里偷了baseurl, parameters = url.split("?") 的部分。我一直忘记你可以在 python 中做那种奇怪的魔法。 @SERPY,当要编码的部分包含 & 字符时,我编辑了代码以减少问题的数量。
【解决方案2】:

@EdoAkse 有一个很好的答案,应该得到答案。

但我内心的纯粹主义者会做同样的事情略有不同,因为

(1) 我不喜欢对同一数据执行两次相同的功能(为了提高效率),并且

(2) 我喜欢使用 join 函数来反转拆分的逻辑对称性。

我的代码看起来更像这样:

from urllib import parse

url = 'https://www.exmple.com/test?test1=abc&test2=abc&test3=abc&q=/"TEST"/"TEST"'
splitter = "&q=/"   
unencoded,encoded = url.split(splitter)
encoded_url = splitter.join(unencoded,parse.quote_plus(encoded))
print(encoded_url)  

编辑:我忍不住根据评论发布我编辑的答案。您可以看到独立开发的虚拟相同代码。我想这一定是正确的方法。

from urllib import parse
url = 'https://www.exmple.com/test?test1=abc&test2=abc&test3=abc&q=/"TEST"/"TEST"'
base_url,arglist = url.split("?",1)
args = arglist.split("&")
new_args = []
for arg in args:
    if arg.lower().startswith("q="):
        new_args.append(arg[:2]+parse.quote_plus(arg[2:]))
    else:
        new_args.append(arg)
encoded_url = "?".join([base_url,"&".join(new_args)])
print(encoded_url) 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-11
    • 1970-01-01
    • 2018-09-09
    相关资源
    最近更新 更多