Obtener protocolo + nombre de host de URL


162

En mi aplicación Django, necesito obtener el nombre de host del referente request.META.get('HTTP_REFERER')junto con su protocolo para que de URL como:

Debería obtener:

Revisé otras preguntas relacionadas y encontré sobre urlparse, pero eso no funcionó ya que

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

Respuestas:


297

Debería poder hacerlo con 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/'

esta respuesta agrega un /al tercer ejemplo http://www.domain.com, pero creo que esto podría ser una deficiencia de la pregunta, no de la respuesta.
SingleNegationElimination

@TokenMacGuy: sí, mi mal ... no noté los desaparecidos /
Gerard

8
urlparse.urlparse()devuelve un resultado con nombre de tupla; podría usar {uri.scheme}://{uri.netloc}/'.format(uri=parsed_uri)para facilitar la lectura.
jfs

12
No creo que esta sea una buena solución, ya netlocque no es un dominio: intente urlparse.urlparse('http://user:pass@example.com:8080')y encuentre que le da partes como 'user:pass@'y':8080'
starrify

22
El módulo urlparse se renombra a urllib.parse en Python 3. Entonces,from urllib.parse import urlparse
SparkAndShine

86

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

Esta es una versión más detallada de urlparse. Detecta dominios y subdominios por ti.

De su documentación:

>>> 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 es una tupla nombrada, por lo que es fácil acceder a las partes que desea.

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

2
Esta es la respuesta correcta para la pregunta tal como está escrita, cómo obtener el nombre de DOMINIO. La solución elegida proporciona el HOSTNAME, que creo que es lo que el autor quería en primer lugar.
Scone

49

Python3 usando 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

Operaciones de cadena pura :):

>>> 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'

Eso es todo amigos.


2
Opción buena y simple, pero falla en algunos casos, por ejemplo foo.bar?haha
Simon Steinberger

1
@SimonSteinberger :-) ¿Qué tal esto ? 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
Para Python 3 la importación es from urllib.parse import urlparse.
Jeff Bowen

8

si crees que tu url es válida, esto funcionará todo el tiempo

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

Lo último splitestá mal, no hay más barras diagonales para dividir.
CONvid19

2
no será un problema, si no hay más barras, la lista volverá con un elemento. así que funcionará si hay una barra oblicua o no
ZeroErr0r

1
Edité su respuesta para poder eliminar el voto negativo. Buena explicación Tks
CONvid19

5

¿Hay algo malo con las operaciones de cadena pura:

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

Si prefiere que se agregue una barra inclinada final, extienda este script un poco así:

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

Eso probablemente se puede optimizar un poco ...


77
no está mal, pero tenemos una herramienta que ya hace el trabajo, no reinventemos la rueda;)
Gerard

5

Aquí hay una versión ligeramente mejorada:

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

Salida

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

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


En mi humilde opinión la mejor solución, porque es simple y considera todo tipo de casos raros. ¡Gracias!
Simon Steinberger

2
ni simple ni mejorado
Corey Goldberg

Esta no es una solución para la pregunta porque no proporciona un protocolo (https: // o http: //)
Alexei Marinichenko

2

Esto es un poco obtuso, pero se usa urlparseen ambas direcciones:

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

ese ("",) * 4bit extraño se debe a que urlparse espera una secuencia de exactamente len(urlparse.ParseResult._fields) = 6


2

Sé que es una vieja pregunta, pero también la encontré hoy. Resuelto esto con una frase:

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

2

La función de biblioteca estándar urllib.parse.urlsplit () es todo lo que necesita. Aquí hay un ejemplo para 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

Podría resolverse mediante 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

para obtener dominio / nombre de host y origen *

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

* Originse usa en XMLHttpRequestencabezados


0

Simplemente puede usar urljoin con la raíz relativa '/' como segundo argumento:

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

Si contiene menos de 3 barras, entonces lo tienes y si no, entonces podemos encontrar la aparición entre ellas:

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.