Отримайте протокол + ім'я хоста з URL-адреси


162

У моєму додатку Django мені потрібно отримати ім'я хоста від реферала request.META.get('HTTP_REFERER')разом із його протоколом, щоб з таких URL-адрес, як:

Я повинен отримати:

Я переглянув інші пов'язані питання та дізнався про urlparse, але з цього моменту не вдавався

>>> urlparse(request.META.get('HTTP_REFERER')).hostname
'docs.google.com'

Відповіді:


297

Ви повинні мати можливість це робити urlparse(docs: python2 , python3 ):

from urllib.parse import urlparse
# from urlparse import urlparse  # Python 2
parsed_uri = urlparse('http://stackoverflow.com/questions/1234567/blah-blah-blah-blah' )
result = '{uri.scheme}://{uri.netloc}/'.format(uri=parsed_uri)
print(result)

# gives
'http://stackoverflow.com/'

ця відповідь додає а /до третього прикладу http://www.domain.com, але я думаю, що це може бути недоліком питання, а не відповіддю.
SingleNegationElimination

@TokenMacGuy: так, мій поганий ... не помітив зниклих /
Джерард

8
urlparse.urlparse()повертає результат, схожий на назва; ви можете використовувати {uri.scheme}://{uri.netloc}/'.format(uri=parsed_uri)для читабельності.
jfs

12
Я не думаю, що це хороше рішення, як netlocі не домен: спробуйте urlparse.urlparse('http://user:pass@example.com:8080')і знайдіть, що дає такі деталі, як 'user:pass@'і':8080'
зірвіть

22
Модуль urlparse перейменований на urllib.parse в Python 3. Отже,from urllib.parse import urlparse
SparkAndShine

86

https://github.com/john-kurkowski/tldextract

Це більш багатослівна версія urlparse. Він виявляє домени та субдомени для вас.

З їх документації:

>>> import tldextract
>>> tldextract.extract('http://forums.news.cnn.com/')
ExtractResult(subdomain='forums.news', domain='cnn', suffix='com')
>>> tldextract.extract('http://forums.bbc.co.uk/') # United Kingdom
ExtractResult(subdomain='forums', domain='bbc', suffix='co.uk')
>>> tldextract.extract('http://www.worldbank.org.kg/') # Kyrgyzstan
ExtractResult(subdomain='www', domain='worldbank', suffix='org.kg')

ExtractResult є nametuple, тому отримати доступ до потрібних деталей просто.

>>> ext = tldextract.extract('http://forums.bbc.co.uk')
>>> ext.domain
'bbc'
>>> '.'.join(ext[:2]) # rejoin subdomain and domain
'forums.bbc'

2
Це правильна відповідь на запитання, як написано, як отримати ім’я ДОМАН. Обране рішення забезпечує HOSTNAME, який, на мою думку, в першу чергу хотів автор.
Сконе

49

Python3 за допомогою urlsplit :

from urllib.parse import urlsplit
url = "http://stackoverflow.com/questions/9626535/get-domain-name-from-url"
base_url = "{0.scheme}://{0.netloc}/".format(urlsplit(url))
print(base_url)
# http://stackoverflow.com/

23

Чисті рядкові операції :):

>>> url = "http://stackoverflow.com/questions/9626535/get-domain-name-from-url"
>>> url.split("//")[-1].split("/")[0].split('?')[0]
'stackoverflow.com'
>>> url = "stackoverflow.com/questions/9626535/get-domain-name-from-url"
>>> url.split("//")[-1].split("/")[0].split('?')[0]
'stackoverflow.com'
>>> url = "http://foo.bar?haha/whatever"
>>> url.split("//")[-1].split("/")[0].split('?')[0]
'foo.bar'

Це все, шановні.


2
Хороший і простий варіант, але в деяких випадках не вдається, наприклад, foo.bar?haha
Simon Steinberger

1
@SimonSteinberger :-) Як про це: url.split("//")[-1].split("/")[0].split('?')[0]:-))
SebMa

22
>>> import urlparse
>>> url = 'http://stackoverflow.com/questions/1234567/blah-blah-blah-blah'
>>> urlparse.urljoin(url, '/')
'http://stackoverflow.com/'

2
Для Python 3 імпорт є from urllib.parse import urlparse.
Джефф Боуен

8

якщо ви вважаєте, що ваша URL-адреса дійсна, це буде працювати весь час

domain = "http://google.com".split("://")[1].split("/")[0] 

Останнє splitневірно, більше немає прямих косої риски, щоб розділити їх.
CONvid19

2
це не буде проблемою, якщо більше не буде нахилів, то список повернеться з одним елементом. тож він спрацює, чи є коса коса риса чи ні
ZeroErr0r

1
Я відредагував вашу відповідь, щоб мати змогу зняти голосування. Приємне пояснення. Ткс.
CONvid19

5

Чи є щось не так з чистими рядковими операціями:

url = 'http://stackoverflow.com/questions/9626535/get-domain-name-from-url'
parts = url.split('//', 1)
print parts[0]+'//'+parts[1].split('/', 1)[0]
>>> http://stackoverflow.com

Якщо ви віддаєте перевагу додаванню косої косої риски, розгорніть цей сценарій приблизно так:

parts = url.split('//', 1)
base = parts[0]+'//'+parts[1].split('/', 1)[0]
print base + (len(url) > len(base) and url[len(base)]=='/'and'/' or '')

Можливо, це можна трохи оптимізувати ...


7
це не помиляється, але ми отримали інструмент, який вже працює, не давайте винаходити колесо;)
Джерард

5

Ось трохи покращена версія:

urls = [
    "http://stackoverflow.com:8080/some/folder?test=/questions/9626535/get-domain-name-from-url",
    "Stackoverflow.com:8080/some/folder?test=/questions/9626535/get-domain-name-from-url",
    "http://stackoverflow.com/some/folder?test=/questions/9626535/get-domain-name-from-url",
    "https://StackOverflow.com:8080?test=/questions/9626535/get-domain-name-from-url",
    "stackoverflow.com?test=questions&v=get-domain-name-from-url"]
for url in urls:
    spltAr = url.split("://");
    i = (0,1)[len(spltAr)>1];
    dm = spltAr[i].split("?")[0].split('/')[0].split(':')[0].lower();
    print dm

Вихідні дані

stackoverflow.com
stackoverflow.com
stackoverflow.com
stackoverflow.com
stackoverflow.com

Fiddle: https://pyfiddle.io/fiddle/23e4976e-88d2-4757-993e-532aa41b7bf0/?i=true


ІМХО найкраще рішення, тому що просте і воно розглядає всілякі рідкісні випадки. Дякую!
Саймон Штейнбергер

2
ні простий, ні вдосконалений
Corey Goldberg

Це не вирішення питання, оскільки ви не надаєте протокол (https: // або http: //)
Олексій Мариниченко

2

Це трохи тупо, але використовує urlparseв обох напрямках:

import urlparse
def uri2schemehostname(uri):
    urlparse.urlunparse(urlparse.urlparse(uri)[:2] + ("",) * 4)

цей непарний ("",) * 4біт є тому, що urlparse очікує послідовності точно len(urlparse.ParseResult._fields) = 6


2

Я знаю, що це старе питання, але я теж сьогодні зіткнувся з ним. Вирішили це за допомогою одного вкладиша:

import re
result = re.sub(r'(.*://)?([^/?]+).*', '\g<1>\g<2>', url)

2

Стандартна функція бібліотеки urllib.parse.urlsplit () - все, що вам потрібно. Ось приклад для Python3:

>>> import urllib.parse
>>> o = urllib.parse.urlsplit('https://user:pass@www.example.com:8080/dir/page.html?q1=test&q2=a2#anchor1')
>>> o.scheme
'https'
>>> o.netloc
'user:pass@www.example.com:8080'
>>> o.hostname
'www.example.com'
>>> o.port
8080
>>> o.path
'/dir/page.html'
>>> o.query
'q1=test&q2=a2'
>>> o.fragment
'anchor1'
>>> o.username
'user'
>>> o.password
'pass'

1

Це може бути вирішено за допомогою re.search ()

import re
url = 'https://docs.google.com/spreadsheet/ccc?key=blah-blah-blah-blah#gid=1'
result = re.search(r'^http[s]*:\/\/[\w\.]*', url).group()
print(result)

#result
'https://docs.google.com'

0

щоб отримати домен / ім'я хоста та джерело *

url = '/programming/9626535/get-protocol-host-name-from-url'
hostname = url.split('/')[2] # stackoverflow.com
origin = '/'.join(url.split('/')[:3]) # https://stackoverflow.com

* Originвикористовується в XMLHttpRequestзаголовках


0

Ви можете просто використовувати urljoin з відносним коренем '/' як другий аргумент:

try:
    from urlparse import urljoin  # Python2
except ImportError:
    from urllib.parse import urljoin  # Python3


url = '/programming/9626535/get-protocol-host-name-from-url'

root_url = urljoin(url, '/')

-1

Якщо він містить менше 3 косої риси, таким чином, у вас це є, а якщо ні, то ми можемо знайти виникнення між ним:

import re

link = http://forum.unisoftdev.com/something

slash_count = len(re.findall("/", link))
print slash_count # output: 3

if slash_count > 2:
   regex = r'\:\/\/(.*?)\/'
   pattern  = re.compile(regex)
   path = re.findall(pattern, url)

   print path
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.