#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 NTntpath
- На платформах, основанных на Unix / Posix
os.path
,posixpath
ntpath
не будет корректно обрабатывать обратную косую черту (posixpath
рекомендуется.- не забудьте использовать
urllib.parse.unquote
- рассмотрите возможность использования
posixpath.normpath
- Семантика нескольких разделителей путей (
/
) не определена RFC 3986. Тем не менее,posixpath
разрушает несколько смежных разделителей путей (т. Е. Обрабатывает///
,//
И/
то же самое) - Несмотря на то, что пути POSIX и URL имеют схожий синтаксис и семантику, они не идентичны.
Нормативные ссылки:
- Стандарт IEEE Std 1003.1, 2013 — Vol. 1: Базовые определения — Раздел 4.12: Разрешение имени пути
- Справочное руководство по библиотеке GNU C — Раздел 11.2: имена файлов
- IETF RFC 3986: Унифицированный идентификатор ресурса (URI): общий синтаксис — Раздел 3.3: Путь
- IETF RFC 3986: Унифицированный идентификатор ресурса (URI): общий синтаксис — Раздел 6: Нормализация и сравнение
- Википедия: нормализация 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»]