รับโพรโทคอ + ชื่อโฮสต์จาก 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: ya, bad ของฉัน ... ไม่ได้สังเกตเห็นการขาดหายไป/
เจอราร์ด

8
urlparse.urlparse()ส่งกลับ namedtuple เหมือนผล; คุณสามารถใช้{uri.scheme}://{uri.netloc}/'.format(uri=parsed_uri)สำหรับการอ่าน
jfs

12
ฉันไม่คิดว่านี่เป็นวิธีแก้ปัญหาที่ดีเพราะnetlocไม่ใช่โดเมน: ลองurlparse.urlparse('http://user:pass@example.com:8080')หามันให้เป็นส่วน ๆ'user:pass@'และ':8080'
starrify

22
โมดูล urlparse ถูกเปลี่ยนชื่อเป็น urllib.parse ในหลาม 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 เป็น namedtuple ดังนั้นจึงเป็นเรื่องง่ายในการเข้าถึงส่วนที่คุณต้องการ

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

2
นี่คือคำตอบที่ถูกต้องสำหรับคำถามตามที่เขียนไว้วิธีรับชื่อ DOMAIN โซลูชันที่เลือกจะให้ชื่อโฮสต์ซึ่งฉันเชื่อว่าเป็นสิ่งที่ผู้แต่งต้องการตั้งแต่แรก
สโคน

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
ไซมอน Steinberger

1
@SimonSteinberger :-) How'bout สิ่งนี้: 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
สำหรับงูหลาม 3 from urllib.parse import urlparseการนำเข้า
เจฟเวน

8

หากคุณคิดว่า URL ของคุณถูกต้องการดำเนินการนี้จะทำงานตลอดเวลา

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

สุดท้ายsplitเป็นความผิดที่มีเครื่องหมายทับไปข้างหน้ามากขึ้นในการแยก
CONvid19

2
มันจะไม่เป็นปัญหาถ้าไม่มีเครื่องหมายทับมากขึ้นแล้วรายการจะกลับมาพร้อมกับองค์ประกอบหนึ่ง จึงจะทำงานได้ไม่ว่าจะมีการเฉือนหรือไม่
ZeroErr0r

1
ฉันแก้ไขคำตอบของคุณเพื่อให้สามารถลบคะแนนโหวตลงได้ คำอธิบายที่ดี Tks
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

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


IMHO ทางออกที่ดีที่สุดเพราะง่ายและพิจารณาทุกกรณีที่หายาก ขอบคุณ!
ไซมอน Steinberger

2
ไม่ง่ายหรือไม่ดีขึ้น
Corey Goldberg

นี้ไม่ได้เป็นวิธีการแก้ปัญหาสำหรับคำถามที่ว่าเพราะคุณไม่ได้ให้โปรโตคอล (https: // หรือ http: //)
อเล็กซี่ Marinichenko

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.