Как перейти к URL-адресам с u в них?


Я наткнулся на URL - адреса, в которых есть символы Unicode, такие как следующие (обратите внимание, что это не будет соответствовать допустимой странице-это просто пример).

http://my_site_name.com/u0442uab86u0454uab8eR-u0454u043d-u043c/23795908

Как я могу декодировать / кодировать такой URL с помощью Python, чтобы я мог успешно выполнить HTTP GET для получения данных с этой веб-страницы?

2 5

2 ответа:

Технически это недопустимые URL-адреса, но они являются допустимыми IRIs (Интернационализированные идентификаторы ресурсов ), как определено вRFC 3987 .

Способ кодирования ИРИ в 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-которая ни requests 2.x ни Python 3.6 stdlib обрабатывать совершенно правильно).


Если вам приходится иметь дело с IRIs вручную, есть хороший шанс, что вам также придется иметь дело с IDNs Интернационализированными доменными именами вместо доменных имен 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)

Вот подход, который автоматизирует обнаружение и %-кодирование не-ASCII как в пути, так и в доменных разделах IRIs:

from urllib.request import quote  

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