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

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/'
kgr
fuente
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:[email protected]: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'
dm03514
fuente
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/
Marc SJ
fuente
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.

SebMa
fuente
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/'
png
fuente
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] 
ZeroErr0r
fuente
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 ...

Simon Steinberger
fuente
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

Faiz
fuente
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

SingleNegationElimination
fuente
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)
Orix Au Yeung
fuente
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:[email protected]:8080/dir/page.html?q1=test&q2=a2#anchor1')
>>> o.scheme
'https'
>>> o.netloc
'user:[email protected]: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'
famzah
fuente
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'
kiwi
fuente
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

cieunteung
fuente
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, '/')
Mirko
fuente
-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
Juraj
fuente