Python: получение разделов пути URL

#python #url

#python #url

Вопрос:

Как мне получить определенные разделы пути из URL-адреса? Например, мне нужна функция, которая работает с этим:

 http://www.mydomain.com/hithere?image=2934
 

и возвращает «hithere»

или работает с этим:

 http://www.mydomain.com/hithere/something/else
 

и возвращает то же самое («hithere»)

Я знаю, что это, вероятно, будет использовать urllib или urllib2, но я не могу понять из документов, как получить только часть пути.

Комментарии:

1. Синтаксис URL-адреса выглядит примерно так: scheme://domain:port/path?query_string#fragment_id , так что ‘hithere’ — это целое path в первом случае и 1 раздел it во втором. Просто проанализируйте его url, тогда ‘hithere’ будет path.split(‘/’)[1]

2. не так ли path.split('/')[0] ? (первый элемент списка)

3. Нет, потому что путь начинается с ‘/’, поэтому [0] является пустой строкой. Т.е. ideone.com/hJRxk

Ответ №1:

Извлеките компонент пути из URL-адреса с помощью urlparse:

 >>> import urlparse
>>> path = urlparse.urlparse('http://www.example.com/hithere/something/else').path
>>> path
'/hithere/something/else'
 

Разделите путь на компоненты с помощью os.path.split:

 >>> import os.path
>>> os.path.split(path)
('/hithere/something', 'else')
 

Функции dirname и basename предоставляют вам две части разделения; возможно, используйте dirname в цикле while:

 >>> while os.path.dirname(path) != '/':
...     path = os.path.dirname(path)
... 
>>> path
'/hithere'
 

Комментарии:

1. У urllib нет какой-либо функции, которая может это сделать, не выполняя кучу синтаксического анализа / разделения / цикла строк? Я думал, что будет ярлык…

2. Не используйте os.path.split для URL-адресов, поскольку это зависит от платформы. Этот код завершится ошибкой в Windows, потому что он ожидает в качестве разделителя!

3. @Viorel Это неверно. Я только что протестировал. Было бы неправильно использовать os.path.join , поскольку он будет использовать неправильный разделитель, но split метод все равно может быть разделен / . Фактически, вы можете ввести все свои пути к каталогам для Windows, используя / в качестве разделителя каталогов в Python. Использование / в качестве разделителя каталогов работает во многих местах в Windows, а не только в Python.

4. os.path.split может сработать, но я думаю, что было бы плохой практикой использовать его здесь, поскольку он явно предназначен для путей к ОС, а не для URL-адресов.

5. использование os.path не удастся для URL-адресов, содержащих в Windows. Используйте posixpath вместо этого — см. Мой ответ.

Ответ №2:

Решение на Python 3.4 :

 from urllib.parse import unquote, urlparse
from pathlib import PurePosixPath

url = 'http://www.example.com/hithere/something/else'

PurePosixPath(
    unquote(
        urlparse(
            url
        ).path
    )
).parts[1]

# returns 'hithere' (the same for the URL with parameters)

# parts holds ('/', 'hithere', 'something', 'else')
#               0    1          2            3

 

Ответ №3:

Лучший вариант — использовать posixpath модуль при работе с компонентом пути URL-адресов. Этот модуль имеет тот же интерфейс, os.path что и POSIX-пути, и последовательно работает с ними при использовании на платформах на базе POSIX и Windows NT.


Пример кода:

 #!/usr/bin/env python3

import urllib.parse
import sys
import posixpath
import ntpath
import json

def path_parse( path_string, *, normalize = True, module = posixpath ):
    result = []
    if normalize:
        tmp = module.normpath( path_string )
    else:
        tmp = path_string
    while tmp != "/":
        ( tmp, item ) = module.split( tmp )
        result.insert( 0, item )
    return result

def dump_array( array ):
    string = "[ "
    for index, item in enumerate( array ):
        if index > 0:
            string  = ", "
        string  = ""{}"".format( item )
    string  = " ]"
    return string

def test_url( url, *, normalize = True, module = posixpath ):
    url_parsed = urllib.parse.urlparse( url )
    path_parsed = path_parse( urllib.parse.unquote( url_parsed.path ),
        normalize=normalize, module=module )
    sys.stdout.write( "{}n  --[n={},m={}]-->n    {}n".format( 
        url, normalize, module.__name__, dump_array( path_parsed ) ) )

test_url( "http://eg.com/hithere/something/else" )
test_url( "http://eg.com/hithere/something/else/" )
test_url( "http://eg.com/hithere/something/else/", normalize = False )
test_url( "http://eg.com/hithere/../else" )
test_url( "http://eg.com/hithere/../else", normalize = False )
test_url( "http://eg.com/hithere/../../else" )
test_url( "http://eg.com/hithere/../../else", normalize = False )
test_url( "http://eg.com/hithere/something/./else" )
test_url( "http://eg.com/hithere/something/./else", normalize = False )
test_url( "http://eg.com/hithere/something/./else/./" )
test_url( "http://eg.com/hithere/something/./else/./", normalize = False )

test_url( "http://eg.com/see/if/this/works", normalize = False )
test_url( "http://eg.com/see/if/this/works", normalize = False,
    module = ntpath )
 

Вывод кода:

 http://eg.com/hithere/something/else
  --[n=True,m=posixpath]-->
    [ "hithere", "something", "else" ]
http://eg.com/hithere/something/else/
  --[n=True,m=posixpath]-->
    [ "hithere", "something", "else" ]
http://eg.com/hithere/something/else/
  --[n=False,m=posixpath]-->
    [ "hithere", "something", "else", "" ]
http://eg.com/hithere/../else
  --[n=True,m=posixpath]-->
    [ "else" ]
http://eg.com/hithere/../else
  --[n=False,m=posixpath]-->
    [ "hithere", "..", "else" ]
http://eg.com/hithere/../../else
  --[n=True,m=posixpath]-->
    [ "else" ]
http://eg.com/hithere/../../else
  --[n=False,m=posixpath]-->
    [ "hithere", "..", "..", "else" ]
http://eg.com/hithere/something/./else
  --[n=True,m=posixpath]-->
    [ "hithere", "something", "else" ]
http://eg.com/hithere/something/./else
  --[n=False,m=posixpath]-->
    [ "hithere", "something", ".", "else" ]
http://eg.com/hithere/something/./else/./
  --[n=True,m=posixpath]-->
    [ "hithere", "something", "else" ]
http://eg.com/hithere/something/./else/./
  --[n=False,m=posixpath]-->
    [ "hithere", "something", ".", "else", ".", "" ]
http://eg.com/see/if/this/works
  --[n=False,m=posixpath]-->
    [ "see", "if", "this", "works" ]
http://eg.com/see/if/this/works
  --[n=False,m=ntpath]-->
    [ "see", "if", "this", "works" ]
 

Примечания:

  • На платформах os.path под управлением Windows NT ntpath
  • На платформах, основанных на Unix / Posix os.path , posixpath
  • ntpath не будет корректно обрабатывать обратную косую черту ( ) (см. Последние два случая в code / output) — именно поэтому posixpath рекомендуется.
  • не забудьте использовать urllib.parse.unquote
  • рассмотрите возможность использования posixpath.normpath
  • Семантика нескольких разделителей путей ( / ) не определена RFC 3986. Тем не менее, posixpath разрушает несколько смежных разделителей путей (т. Е. Обрабатывает /// , // И / то же самое)
  • Несмотря на то, что пути POSIX и URL имеют схожий синтаксис и семантику, они не идентичны.

Нормативные ссылки:

Комментарии:

1. Решение Python 3.4 : url_path = PurePosixPath(urllib.parse.unquote(urllib.parse.urlparse(url‌​).path)) .

2. @Navin стоит опубликовать это в качестве ответа

3. Отличный ответ. Однако это не удается, если в одном из исправленных URL есть ошибка. Например: test_url( "http://eg.com/hithere//something/else" ) приведет к бесконечному циклу на while tmp != "/":

Ответ №4:

Примечание в Python3 импорт изменен, чтобы from urllib.parse import urlparse просмотреть документацию. Вот пример:

 >>> from urllib.parse import urlparse
>>> url = 's3://bucket.test/my/file/directory'
>>> p = urlparse(url)
>>> p
ParseResult(scheme='s3', netloc='bucket.test', path='/my/file/directory', params='', query='', fragment='')
>>> p.scheme
's3'
>>> p.netloc
'bucket.test'
>>> p.path
'/my/file/directory'
 

Ответ №5:

 import urlparse

output = urlparse.urlparse('http://www.example.com/temp/something/happen/index.html').path

output

'/temp/something/happen/index.html'

Split the path -- inbuilt rpartition func of string 

output.rpartition('/')[0]

'/temp/something/happen'
 

Ответ №6:

Вот пример использования urlparse и rpartition.

 # Python 2x:
from urlparse import urlparse
# Python 3x:
from urllib.parse import urlparse

def printPathTokens(full_url):
    print('printPathTokens() called: %s' % full_url)

    p_full = urlparse(full_url).path

    print(' . p_full url: %s' % p_full)

    # Split the path using rpartition method of string
    # rpartition "returns a tuple containing the part the before separator,
    # argument string and the part after the separator" 
    (rp_left, rp_match, rp_right) = p_full.rpartition('/')

    if rp_match == '': # returns the rpartition separator if found
        print(' . No slashes found in path')
    else:
        print(' . path to last resource: %s' % rp_left)
        if rp_right == '': # Ended with a slash
            print(' . last resource: (none)')
        else:
            print(' . last resource: %s' % (rp_right))


printPathTokens('http://www.example.com/temp/something/happen/index.html')
# Output:
# printPathTokens() called: http://www.example.com/temp/something/happen/index.html
# . p_full url: /temp/something/happen/index.html
# . path to last resource: /temp/something/happen
# . last resource: index.html

printPathTokens('http://www.example.com/temp/something/happen/')
# Output:
# printPathTokens() called: http://www.example.com/temp/something/happen/
# . p_full url: /temp/something/happen/
# . path to last resource: /temp/something/happen
# . last resource: (none)

printPathTokens('http://www.example.com/temp/something/happen')
# Output:
# printPathTokens() called: http://www.example.com/temp/something/happen
# . p_full url: /temp/something/happen
# . path to last resource: /temp/something
# . last resource: happen
 

Ответ №7:

Комбинация urlparse и os.path.split сделает свое дело. Следующий скрипт сохраняет все разделы URL-адреса в списке в обратном порядке.

 import os.path, urlparse

def generate_sections_of_url(url):
    path = urlparse.urlparse(url).path
    sections = []; temp = "";
    while path != '/':
        temp = os.path.split(path)
        path = temp[0]
        sections.append(temp[1])
    return sections
 

Это вернет: [«else», «something», «hithere»]