Разбор URL в Python – нормализация двойного слэш в путях

Я работаю над приложением, которое должно анализировать URL-адреса (в основном URL-адреса HTTP) в HTML-страницах – я не контролирую входные данные, и некоторые из них, как и ожидалось, немного беспорядочны.

Одна из проблем, с которыми я часто сталкиваюсь, заключается в том, что urlparse очень строгий (и, возможно, даже багги?), Когда дело доходит до разбора и объединения URL-адресов, которые имеют двойные слэши в части пути, например:

testUrl = 'http://www.example.com//path?foo=bar' urlparse.urljoin(testUrl, urlparse.urlparse(testUrl).path) 

Вместо ожидаемого результата http://www.example.com//path (или даже лучше, с нормализованной единственной косой чертой), я заканчиваю http://path .

Кстати, причина, по которой я запускаю такой код, состоит в том, что это единственный способ, которым я нашел до сих пор, чтобы отделить часть запроса / фрагмента от URL-адресов. Может быть, есть лучший способ сделать это, но я не смог его найти.

Может ли кто-нибудь рекомендовать способ избежать этого, или я должен просто нормализовать путь самостоятельно, используя (относительно простое, я знаю) регулярное выражение?

5 Solutions collect form web for “Разбор URL в Python – нормализация двойного слэш в путях”

Если вы хотите получить URL-адрес без части запроса, я бы пропустил модуль urlparse и просто сделаю:

 testUrl.rsplit('?') 

URL-адрес будет иметь индекс 0 возвращенного списка и запрос в индексе 1.

Невозможно иметь два '?' в URL-адресе, поэтому он должен работать для всех URL-адресов.

Только путь ( //path ) недействителен, что смущает функцию и интерпретируется как имя хоста

http://tools.ietf.org/html/rfc3986.html#section-3.3

Если URI не содержит компонент полномочий, то путь не может начинаться с двух косой черты («//»).

Мне не особенно нравится одно из этих решений, но они работают:

 import re import urlparse testurl = 'http://www.example.com//path?foo=bar' parsed = list(urlparse.urlparse(testurl)) parsed[2] = re.sub("/{2,}", "/", parsed[2]) # replace two or more / with one cleaned = urlparse.urlunparse(parsed) print cleaned # http://www.example.com/path?foo=bar print urlparse.urljoin( testurl, urlparse.urlparse(cleaned).path) # http://www.example.com//path 

В зависимости от того, что вы делаете, вы можете выполнить соединение вручную:

 import re import urlparse testurl = 'http://www.example.com//path?foo=bar' parsed = list(urlparse.urlparse(testurl)) newurl = ["" for i in range(6)] # could urlparse another address instead # Copy first 3 values from # ['http', 'www.example.com', '//path', '', 'foo=bar', ''] for i in range(3): newurl[i] = parsed[i] # Rest are blank for i in range(4, 6): newurl[i] = '' print urlparse.urlunparse(newurl) # http://www.example.com//path 

В официальных документах urlparse указано, что:

Если URL-адрес является абсолютным URL-адресом (то есть, начиная с // или схемы: //), в результате будет указано имя хоста и / или схема URL-адреса. Например

 urljoin('http://www.cwi.nl/%7Eguido/Python.html', ... '//www.python.org/%7Eguido') 'http://www.python.org/%7Eguido' 

Если вы не хотите этого поведения, предварительно обработайте URL с помощью urlsplit () и urlunsplit (), удалив возможные схемы и компоненты netloc.

Таким образом, вы можете:

 urlparse.urljoin(testUrl, urlparse.urlparse(testUrl).path.replace('//','/')) 

Вывод = 'http://www.example.com/path'

Попробуй это:

 def http_normalize_slashes(url): url = str(url) segments = url.split('/') correct_segments = [] for segment in segments: if segment != '': correct_segments.append(segment) first_segment = str(correct_segments[0]) if first_segment.find('http') == -1: correct_segments = ['http:'] + correct_segments correct_segments[0] = correct_segments[0] + '/' normalized_url = '/'.join(correct_segments) return normalized_url 

Примеры URL:

 print(http_normalize_slashes('http://www.example.com//path?foo=bar')) print(http_normalize_slashes('http:/www.example.com//path?foo=bar')) print(http_normalize_slashes('www.example.com//x///c//v///path?foo=bar')) print(http_normalize_slashes('http://////www.example.com//x///c//v///path?foo=bar')) 

Вернется:

 http://www.example.com/path?foo=bar http://www.example.com/path?foo=bar http://www.example.com/x/c/v/path?foo=bar http://www.example.com/x/c/v/path?foo=bar 

Надеюсь, поможет.. 🙂

Разве это не может быть решением?

 urlparse.urlparse(testUrl).path.replace('//', '/') 
  • Есть предопределенный класс для URL-адреса в Python?
  • Объединение URL с urlunparse
  • urlparse.urlparse возвращает 3 '/' вместо 2 после схемы
  • Python urlparse - вырезать доменное имя без субдомена
  • разбор URL-адреса в python с изменением его части
  • Как построить относительный URL-адрес, учитывая два абсолютных URL-адреса в Python
  • python, "urlparse.urlparse (url) .hostname" return None value
  • Python `urlparse`: добавление ключевых слов GET к URL-адресу
  • Python - лучший язык программирования в мире.