代码之家  ›  专栏  ›  技术社区  ›  aBlaze

如何导航到包含\u的URL?

  •  5
  • aBlaze  · 技术社区  · 6 年前

    我遇到过在URL中包含Unicode字符的URL,如以下所示(请注意,这不会映射到有效页面-这只是一个示例)。

    http://my_site_name.com/\u0442\uab86\u0454\uab8eR-\u0454\u043d-\u043c/23795908

    如何使用Python对这样的URL进行解码/编码,以便成功执行HTTP GET从该网页检索数据?

    2 回复  |  直到 6 年前
        1
  •  5
  •   Community Dai    3 年前

    从技术上讲,这些不是有效的URL,但它们是有效的IRIs( Internationalized Resource Identifiers ),定义见 RFC 3987

    将IRI编码为URI的方式是:

    • UTF-8对路径进行编码
    • %-对生成的UTF-8进行编码

    例如(摘自链接的维基百科文章),此IRI:

    https://en.wiktionary.org/wiki/Ῥόδος
    

    映射到此URI:

    https://en.wiktionary.org/wiki/%E1%BF%AC%CF%8C%CE%B4%CE%BF%CF%82
    

    我相信 requests 开箱即用地处理这些问题(虽然只是最近才出现,而且在3.0之前只有“部分支持”,我不知道这意味着什么)。我很确定 urllib2 在Python2.7中没有,并且 urllib.request 在Python 3.6中可能也没有。

    无论如何,如果您选择的HTTP库不处理IRIs,您可以手动执行:

    def iri_to_uri(iri):
        p = urllib.parse.urlparse(iri)
        path = urllib.parse.quote_from_bytes(p.path.encode('utf-8'))
        p = [:2] + (path,) + p[3:]
        return urllib.parse.urlunparse(p2)
    

    还有许多第三方库可以处理IRIs,它们大多是从Twisted和Amara等其他项目中分离出来的。也许值得搜索PyPI来寻找一个,而不是自己构建它。

    或者您可能需要更高级别的库,如 hyperlink 处理RFC 3987中所有复杂问题(以及 RFC 3986 ,URI规范的当前版本 请求 x或Python 3.6 stdlib句柄(非常正确)。


    如果您必须手动处理IRIs,那么很有可能您还必须处理IDN Internationalized Domain Names 也可以代替ASCII域名,尽管从技术上讲,它们是不相关的规范。所以你可能想做这样的事情:

    def iri_to_uri(iri):
        p = urllib.parse.urlparse(iri)
        netloc = p.netloc.encode('idna').decode('ascii')
        path = urllib.parse.quote_from_bytes(p.path.encode('utf-8'))
        p = [:1] + (netloc, path) + p[3:]
        return urllib.parse.urlunparse(p2)
    
        2
  •  1
  •   TavoloPerUno    6 年前

    以下是一种在IRIs的路径和域部分自动检测和编码非ASCII码的方法:

    from urllib.request import quote  
    
    def iri_to_uri(iri):
        return ("".join([x if ord(x) < 128 else quote(x) for x in iri]))