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'

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

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:pass@example.com: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'

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/

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.


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

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] 

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é ...


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


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


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)

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

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'

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


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, '/')

-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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.