Obtenir le protocole + le nom d'hôte à partir de l'URL

162

Dans mon application Django, j'ai besoin d'obtenir le nom d'hôte du référent request.META.get('HTTP_REFERER')avec son protocole afin que des URL telles que:

Je devrais avoir:

J'ai examiné d'autres questions connexes et j'ai trouvé sur urlparse, mais cela n'a pas fonctionné depuis

>>> urlparse(request.META.get('HTTP_REFERER')).hostname
'docs.google.com'
Gérard
la source

Réponses:

297

Vous devriez pouvoir le faire avec 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
la source
cette réponse ajoute un /au troisième exemple http://www.domain.com, mais je pense que cela pourrait être une lacune de la question, pas de la réponse.
SingleNegationElimination
@TokenMacGuy: oui, mon mauvais ... je n'ai pas remarqué les disparus /
Gerard
8
urlparse.urlparse()retourne un résultat de type "nommé"; vous pouvez utiliser {uri.scheme}://{uri.netloc}/'.format(uri=parsed_uri)pour la lisibilité.
jfs
12
Je ne pense pas que ce soit une bonne solution, car ce netlocn'est pas le domaine: essayez de urlparse.urlparse('http://user:[email protected]:8080')trouver que cela donne des parties comme 'user:pass@'et':8080'
starrifiez
22
Le module urlparse est renommé urllib.parse en Python 3. Donc,from urllib.parse import urlparse
SparkAndShine
86

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

Il s'agit d'une version plus détaillée d'urlparse. Il détecte les domaines et sous-domaines pour vous.

De leur documentation:

>>> 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 est un namedtuple, il est donc simple d'accéder aux parties souhaitées.

>>> ext = tldextract.extract('http://forums.bbc.co.uk')
>>> ext.domain
'bbc'
>>> '.'.join(ext[:2]) # rejoin subdomain and domain
'forums.bbc'
dm03514
la source
2
C'est la bonne réponse à la question telle qu'elle est écrite, comment obtenir le nom de DOMAIN La solution choisie fournit le HOSTNAME, qui, je crois, est ce que l'auteur voulait en premier lieu.
Scone
49

Python3 utilisant 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
la source
23

Opérations de chaîne pure :):

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

C'est tout, les gars.

SebMa
la source
2
Bonne et simple option, mais échoue dans certains cas, par exemple foo.bar?haha
Simon Steinberger
1
@SimonSteinberger :-) How'bout this: 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
la source
2
Pour Python 3, l'importation est from urllib.parse import urlparse.
Jeff Bowen
8

si vous pensez que votre URL est valide, cela fonctionnera tout le temps

domain = "http://google.com".split("://")[1].split("/")[0] 
ZeroErr0r
la source
Le dernier splitest faux, il n'y a plus de barres obliques à diviser.
CONvid19
2
ce ne sera pas un problème, s'il n'y a plus de barres obliques, la liste retournera avec un élément. donc cela fonctionnera qu'il y ait une barre oblique ou non
ZeroErr0r
1
J'ai modifié votre réponse pour pouvoir supprimer le vote défavorable. Belle explication. Tks.
CONvid19
5

Y a-t-il quelque chose qui ne va pas avec les opérations sur chaînes pures:

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 vous préférez ajouter une barre oblique à la fin, étendez ce script un peu comme ceci:

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

Cela peut probablement être un peu optimisé ...

Simon Steinberger
la source
7
ce n'est pas faux mais nous avons un outil qui fait déjà le travail, ne réinventons pas la roue;)
Gerard
5

Voici une version légèrement améliorée:

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

Production

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

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

Faiz
la source
IMHO la meilleure solution, car simple et elle considère toutes sortes de cas rares. Merci!
Simon Steinberger
2
ni simple ni amélioré
Corey Goldberg
Ce n'est pas une solution à la question car vous ne fournissez pas de protocole (https: // ou http: //)
Alexei Marinichenko
2

C'est un peu obtus, mais utilise urlparsedans les deux sens:

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

ce ("",) * 4bit impair est dû au fait que urlparse attend une séquence d' exactement len(urlparse.ParseResult._fields) = 6

SingleNegationElimination
la source
2

Je sais que c'est une vieille question, mais moi aussi je l'ai rencontrée aujourd'hui. Résolu cela avec un one-liner:

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

La fonction de bibliothèque standard urllib.parse.urlsplit () est tout ce dont vous avez besoin. Voici un exemple pour 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
la source
1

Cela pourrait être résolu par 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
la source
0

pour obtenir le domaine / nom d'hôte et l'origine *

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

* Originest utilisé dans les en- XMLHttpRequesttêtes

cieunteung
la source
0

Vous pouvez simplement utiliser urljoin avec la racine relative '/' comme deuxième argument:

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
la source
-1

Si elle contient moins de 3 barres obliques, vous l'avez et sinon, nous pouvons trouver l'occurrence entre elles:

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
la source