URL encode

本文探讨了URL中的特殊字符为何需要进行URL编码,解释了URL编码的目的及规则,并通过PHP与Java的示例阐述了如何实现这一过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

个人技术博客:http://demi-panda.com

 

发现现在几乎所有的网站都对url中的汉字和特殊的字符,进行了urlencode操作,也就是:

http://hi.baidu.com/%BE%B2%D0%C4%C0%CF%C8%CB/creat/blog/

这个样子,中间%形式的,肯定就是我的登录用户名称了吧。

为什么对这些字符进行了u的编码形式,是为了字符编码(gbk、utf8)还是为了不出现特殊的字符在url中?都知道要转,但是转了的真正好处呢。查看了网上的很多资料,也没有找到更加准确的说法。

url转义其实也只是为了符合url的规范而已。因为在标准的url规范中中文和很多的字符是不允许出现在url中的。

看一下php的urlencode的说明了。

urlencode — 编码 URL 字符串

string   urlencode   (   string   $str   )

返回字符串,此字符串中除了  -_.   之外的所有非字母数字字符都将被替换成百分号(% )后跟两位十六进制数,空格则编码为加号(+ )。此编码与 WWW 表单 POST 数据的编码方式是一样的,同时与  application/x-www-form-urlencoded   的媒体类型编码方式一样。由于历史原因,此编码在将空格编码为加号(+)方面与 RFC1738 编码(参见  rawurlencode() )不同。此函数便于将字符串编码并将其用于 URL 的请求部分,同时它还便于将变量传递给下一页。

标准的英文说明是:

"...Only alphanumerics [0-9a-zA-Z], the special characters "$-_.+!*'(),"   [not including the quotes - ed] , and reserved characters used for their reserved purposes may be used unencoded within a URL."

那哪些字符是需要转化的呢?

1. ASCII 的控制字符

这些字符都是不可打印的,自然需要进行转化。

2. 一些非ASCII字符

这些字符自然是非法的字符范围。转化也是理所当然的了。

3. 一些保留字符

很明显最常见的就是“&”了,这个如果出现在url中了,那你认为是url中的一个字符呢,还是特殊的参数分割用的呢?

4. 就是一些不安全的字符了。

例如:空格。为了防止引起歧义,需要被转化为“+”。

明白了这些,也就知道了为什么需要转化了,而转化的规则也是很简单的。

按照每个字符对应的字符编码,不是符合我们范围的,统统的转化为%的形式也就是了。自然也是16进制的形式。

和字符编码无关

通过urlencode的转化规则和目的,我们也很容易的看出,urleocode是基于字符编码的。同样的一个汉字,不同的编码类型,肯定对应不同的urleocode的串。gbk编码的有gbk的encode结果。

apache等服务器,接受到字符串后,可以进行decode,但是还是无法解决编码的问题。编码问题,还是需要靠约定或者字符编码的判断解决。

因此,urleocode只是为了url中一些非ascii字符,可以正确无误的被传输,至于使用哪种编码,就不是eocode所关心和解决的问题了。

编码问题,不是urlencode所要解决的。

再结合 Java API 写一个例子,帮助进一步理解:

 

import java.net.*;


public class TestURI

{
  
public static void main(String[] args) throws Exception
 
 {
   
 String path = args[0];
  
  String query = args[1];

    
URI uri = new URI(
      "http",
      null,
      "smartstorage.yoyoyws.com",
      80,
      path,
      query,
      null);

    
    System.out.println("uri.toString(): " + uri.toString());
    System.out.println("uri.toASCIIString(): " + uri.toASCIIString());
 
 }

}



运行: 
java TestURI "/a/b/文件 1.txt" "versionId=ver_1"

结果:
uri.toString(): http://smartstorage.yoyoyws.com:80/a/b/文件%201.txt?versionId=ver_1
uri.toASCIIString(): http://smartstorage.yoyoyws.com:80/a/b/%E6%96%87%E4%BB%B6%201.txt?versionId=ver_1

 

servlet 实现了 doGet:
 public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
  {
    System.out.println("getRequestURI: " + request.getRequestURI());
    System.out.println("getParam: " + request.getParameter("param"));
  }

发送请求:
http://localhost:8080/你好?param=你好

tomcat 打印(tomcat 配置 URIEncoding="UTF-8"):
getRequestURI: /%E4%BD%A0%E5%A5%BD
getParam: 你好

结论:
tomcat 对 URL 中的 paramater 部分自动做 url decode,而不会对 URL 中的 path 部分做 url decode,需要应用开发人员来自己做 decode。

 

我们用 Java 作为 client 发送 HTTP 请求时,应该按照上面例子中的写法(调用 toASCIIString() )构造请求的 URL

参考资料:

另外 JDK 中也有一段详细的介绍:

http://download.oracle.com/javase/6/docs/api/java/net/URI.html#encode

http://www.blooberry.com/indexdot/html/topics/urlencoding.htm

http://cn.php.net/manual/zh/function.urlencode.php

 

<think>我们正在处理URL编码的问题。根据引用,我们需要使用urllib.parse中的urlencode或quote函数。注意,用户可能想对整个URL编码,但引用指出:只能对参数值进行编码,不能对整个URL或param=value一起编码。因此,我们需要区分情况。 用户问题:我想对URL进行编码 请问Python URL encode 根据引用[1]和[2],正确的做法是: 1. 如果要对查询字符串的参数进行编码,应该分别对每个参数的值进行编码,然后组合成param=encoded_value的形式。 2. 如果有一个字典表示多个参数,可以使用urllib.parse.urlencode()对整个字典编码,它会自动处理每个值的编码。 3. 如果要对单个字符串(比如参数值)进行编码,可以使用urllib.parse.quote()。 另外,引用[3]提到了解码时的错误处理,但用户目前只问编码。 因此,回答应该包括: - 使用quote对单个字符串(参数值)编码 - 使用urlencode对参数字典编码 注意:不能对整个URL编码(比如包含协议、主机、路径等),只能对查询参数部分进行编码。 步骤: 1. 引入urllib.parse 2. 对于单个字符串:quote(string, safe='', encoding='utf-8', errors='strict') 3. 对于字典:urlencode(query, doseq=False, safe='', encoding='utf-8', errors='strict') 注意:safe参数用于指定不需要编码的字符(默认是'/',但通常查询参数中可能需要编码斜杠,所以有时设置为空字符串)。默认情况下,字母数字和连字符、点、下划线、波浪线不编码。其他字符都会被百分号编码。 示例: 单个参数值:quote('a b') 会变成 'a%20b' 字典:urlencode({'key1': 'value 1', 'key2': 'value@2'}) 会变成 'key1=value%201&key2=value%402' 另外,引用[2]中有一个例子,注意在字典中同一个键多次出现,使用列表(并设置doseq=True)可以生成多个键值对。 但是,用户的问题没有具体说明是编码一个字符串还是编码一个字典。所以我们需要提供两种情况。 另外,注意用户可能想编码整个URL?但引用[1]特别强调不能对整个URL编码。所以我们需要提醒用户:只能对查询参数部分进行编码。 因此,回答结构: 1. 解释URL编码的作用(将特殊字符转换为%加十六进制形式,以便在URL中安全传输) 2. 说明只能对查询参数的值进行编码(或者整个查询字符串的字典编码),不能对整个URL编码(否则会破坏URL结构) 3. 提供两种方法: a. 使用quote编码单个字符串(用于参数值) b. 使用urlencode编码字典(用于多个参数) 4. 示例代码 注意:在Python3中,urllib.parse是标准库。 同时,根据引用[3],在解码时可以使用错误处理,但编码时quote函数默认是严格模式,会抛出异常,但通常字符串是str类型(Python3要求是str,如果是bytes需要先解码?)实际上,quote函数要求字符串是str(Unicode)类型,如果是bytes,需要先解码。 所以,如果用户有字节串,需要先解码为字符串,再编码。 但是,用户的问题没有提到字节串,所以我们假设输入是字符串。 最后,生成相关问题。 引用标识:我们使用了引用[1][2][3]中的信息,所以在回答中适当位置添加引用标识。 回答:</think>### Python URL 编码详解 在 Python 中对 URL 进行编码时,**只能对参数值进行编码**,不能对整个 URL 或完整的 `param=value` 字符串编码。正确做法是使用 `urllib.parse` 模块的 `quote()` 或 `urlencode()` 函数,具体取决于场景: #### 1. **对单个参数值编码(`quote()`)** ```python from urllib.parse import quote value = "特殊参数 & 值@test" encoded_value = quote(value, safe='') # safe='' 表示强制编码所有非安全字符 print(encoded_value) # 输出: %E7%89%B9%E6%AE%8A%E5%8F%82%E6%95%B0%20%26%20%E5%80%BC%40test ``` - **说明**: `quote()` 将字符串中的特殊字符(如空格、`&`、`@`)转换为 `%xx` 格式的转义序列。 `safe` 参数指定不编码的字符(默认不编码字母数字和 `_.-~`)。 #### 2. **对参数字典编码(`urlencode()`)** ```python from urllib.parse import urlencode params = { "name": "张三&Li", "page": "1/2" } encoded_query = urlencode(params, doseq=True) print(encoded_query) # 输出: name=%E5%BC%A0%E4%B8%89%26Li&page=1%2F2 ``` - **说明**: `urlencode()` 自动处理字典中所有值的编码,生成完整的查询字符串。 `doseq=True` 确保列表值(如 `tags=["a","b"]`)被正确展开为 `tags=a&tags=b`[^2]。 #### 关键注意事项: 1. **仅编码参数值** 错误做法:`quote("key=value")`(会破坏 URL 结构) 正确做法:`key=quote(value)`[^1]。 2. **字符集一致性** 编码/解码需使用相同字符集(通常为 UTF-8): ```python from urllib.parse import unquote decoded = unquote("%E5%BC%A0%E4%B8%89", encoding="utf-8") # 输出: "张三" ``` 3. **处理异常字符** 解码时可忽略非法字节: ```python s.decode("utf-8", "ignore") # 跳过无效字节 s.decode("utf-8", "replace") # 替换为占位符
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值