urllib2.urlopen 不会自动在 url 的末尾加“/”

urllib2.urlopen does not add a "/" to the last of url with chinese automatically

示例:

url_1 = "http://yinwang.org/blog-cn/2013/04/21/ydiff-%E7%BB%93%E6%9E%84%E5%8C%96%E7%9A%84%E7%A8%8B%E5%BA%8F%E6%AF%94%E8%BE%83/"

url_2 = "http://yinwang.org/blog-cn/2013/04/21/ydiff-%E7%BB%93%E6%9E%84%E5%8C%96%E7%9A%84%E7%A8%8B%E5%BA%8F%E6%AF%94%E8%BE%83"

如您所见,如果我不在 URL 的最后添加 /,当我使用 urllib2.urlopen(url_2) 时,它会出现 returns 400 错误,因为有效的URL应该是url_1,如果URL不包含任何中文,urllib2.urlopenurllib.urlopen会自动添加一个/

问题是 urllib.urlopen 在所有这些情况下都能正常工作,但是 urllib2.urlopen 只有在 URL 没有中文的情况下才能正常工作。

所以我想知道这是 urllib2.urlopen 的一个小错误,还是有其他解释?

这里实际发生的是在实际错误之前由服务器启动的几个重定向:

  1. 要求:http://yinwang.org/blog-cn/2013/04/21/ydiff-%E7%BB%93%E6%9E%84%E5%8C%96%E7%9A%84%E7%A8%8B%E5%BA%8F%E6%AF%94%E8%BE%83
  2. 响应:重定向到 http://www.yinwang.org/blog-cn/2013/04/21/ydiff-%E7%BB%93%E6%9E%84%E5%8C%96%E7%9A%84%E7%A8%8B%E5%BA%8F%E6%AF%94%E8%BE%83
  3. 要求:http://www.yinwang.org/blog-cn/2013/04/21/ydiff-%E7%BB%93%E6%9E%84%E5%8C%96%E7%9A%84%E7%A8%8B%E5%BA%8F%E6%AF%94%E8%BE%83
  4. 响应:重定向到 http://www.yinwang.org/blog-cn/2013/04/21/ydiff-结构化的程序比较/(准确地说,实际上是 'http://www.yinwang.org/blog-cn/2013/04/21/ydiff-\xe7\xbb\x93\xe6\x9e\x84\xe5\x8c\x96\xe7\x9a\x84\xe7\xa8\x8b\xe5\xba\x8f\xe6\xaf\x94\xe8\xbe\x83/'

据我所知,上次重定向无效。地址应为纯 ASCII(应编码非 ascii 字符)。正确的编码地址是:http://www.yinwang.org/blog-cn/2013/04/21/ydiff-%E7%BB%93%E6%9E%84%E5%8C%96%E7%9A%84%E7%A8%8B%E5%BA%8F%E6%AF%94%E8%BE%83/

现在,urllib 似乎表现不错,在请求最终地址之前自己进行转换,而 urllib2 只是使用它接收到的地址。

你可以看到,如果你尝试手动打开最终地址:

urllib

>>> print urllib.urlopen('http://www.yinwang.org/blog-cn/2013/04/21/ydiff-\xe7\xbb\x93\xe6\x9e\x84\xe5\x8c\x96\xe7\x9a\x84\xe7\xa8\x8b\xe5\xba\x8f\xe6\xaf\x94\x
e8\xbe\x83/').geturl()
http://www.yinwang.org/blog-cn/2013/04/21/ydiff-%E7%BB%93%E6%9E%84%E5%8C%96%E7%9A%84%E7%A8%8B%E5%BA%8F%E6%AF%94%E8%BE%83/

urllib2

>>> try:
...     urllib2.urlopen('http://www.yinwang.org/blog-cn/2013/04/21/ydiff-\xe7\xbb\x93\xe6\x9e\x84\xe5\x8c\x96\xe7\x9a\x84\xe7\xa8\x8b\xe5\xba\x8f\xe6\xaf\x94\xe8\xbe\x83/')
... except Exception as e:
...     print e.geturl()
...
http://www.yinwang.org/blog-cn/2013/04/21/ydiff-š╗ôŠ×äňîľšÜäšĘőň║ĆŠ»öŔżâ/

解决方案

如果是你的服务器,你应该解决那里的问题。否则,我想应该可以编写一个 urllib2.HTTPRedirectHandler 来对 urllib2 中的重定向 URL 进行编码。