Nhận giao thức + tên máy chủ từ URL


160

Trong ứng dụng Django của tôi, tôi cần lấy tên máy chủ từ người giới thiệu request.META.get('HTTP_REFERER')cùng với giao thức của nó để từ các URL như:

Tôi sẽ nhận được:

Tôi đã xem qua các câu hỏi liên quan khác và tìm thấy về urlparse, nhưng điều đó đã không thực hiện được mánh khóe kể từ đó

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

Câu trả lời:


296

Bạn sẽ có thể làm điều đó với 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/'

câu trả lời này thêm một /ví dụ thứ ba http://www.domain.com, nhưng tôi nghĩ rằng đây có thể là một thiếu sót của câu hỏi, không phải là câu trả lời.
Độc thân Khuyến khích

@TokenMacGuy: ya, xấu của tôi ... đã không nhận thấy sự mất tích /
Gerard

8
urlparse.urlparse()trả về một kết quả giống như tên; bạn có thể sử dụng {uri.scheme}://{uri.netloc}/'.format(uri=parsed_uri)để dễ đọc.
jfs

12
Tôi không nghĩ rằng đây là một giải pháp tốt, vì netlockhông phải là miền: hãy thử urlparse.urlparse('http://user:pass@example.com:8080')và tìm nó mang lại những phần như 'user:pass@'':8080'
starrify

22
Mô-đun urlparse được đổi tên thành urllib.parse trong Python 3. Vì vậy,from urllib.parse import urlparse
SparkAndShine 21/07/2015

86

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

Đây là một phiên bản dài hơn của urlparse. Nó phát hiện tên miền và tên miền phụ cho bạn.

Từ tài liệu của họ:

>>> 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 là một tên được đặt tên, vì vậy thật đơn giản để truy cập vào các phần bạn muốn.

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

2
Đây là câu trả lời chính xác cho câu hỏi như đã viết, làm thế nào để có được tên DOMAIN. Giải pháp được chọn cung cấp HOSTNAME, mà tôi tin là điều mà tác giả muốn ở nơi đầu tiên.
Scone

49

Python3 sử dụng url :

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

Hoạt động chuỗi thuần :):

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

Đó là tất cả mọi người.


2
Tùy chọn tốt và đơn giản, nhưng thất bại trong một số trường hợp, ví dụ: foo.bar?haha
Simon Steinberger

1
@SimonSteinberger :-) Làm thế nào để biết điều này 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
Đối với Python 3, quá trình nhập là from urllib.parse import urlparse.
Jeff Bowen

7

nếu bạn nghĩ url của bạn hợp lệ thì nó sẽ hoạt động mọi lúc

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

Điều cuối cùng splitlà sai, không có thêm dấu gạch chéo về phía trước để phân chia.
CONvid19

2
Sẽ không có vấn đề gì, nếu không còn dấu gạch chéo nữa, danh sách sẽ trở lại với một phần tử. do đó, nó sẽ hoạt động cho dù có dấu gạch chéo hay không
ZeroErr0r

1
Tôi đã chỉnh sửa câu trả lời của bạn để có thể loại bỏ phiếu bầu xuống. Giải thích tốt đẹp. Tks.
CONvid19

5

Có bất cứ điều gì sai với các hoạt động chuỗi thuần túy:

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

Nếu bạn muốn có một dấu gạch chéo được nối thêm, hãy mở rộng tập lệnh này một chút như vậy:

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

Điều đó có thể được tối ưu hóa một chút ...


7
Điều đó không sai nhưng chúng tôi đã có một công cụ đã thực hiện công việc, chúng ta đừng phát minh lại bánh xe;)
Gerard

5

Đây là một phiên bản cải tiến một chút:

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

Đầu ra

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

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


IMHO giải pháp tốt nhất, bởi vì đơn giản và nó xem xét tất cả các trường hợp hiếm gặp. Cảm ơn!
Simon Steinberger

2
không đơn giản cũng không cải thiện
Corey Goldberg

Đây không phải là một giải pháp cho câu hỏi vì bạn không cung cấp giao thức (https: // hoặc http: //)
Alexei Marinichenko

2

Điều này hơi khó hiểu, nhưng sử dụng urlparsetheo cả hai hướng:

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

("",) * 4bit lẻ đó là do urlparse mong đợi một chuỗi chính xác len(urlparse.ParseResult._fields) = 6


2

Tôi biết đó là một câu hỏi cũ, nhưng tôi cũng gặp nó ngày hôm nay. Giải quyết điều này với một lớp lót:

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

2

Hàm thư viện chuẩn urllib.parse.urlsplit () là tất cả những gì bạn cần. Đây là một ví dụ cho 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

Nó có thể được giải quyết bằng 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

để có được tên miền / tên máy chủ và Xuất xứ *

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

* Originđược sử dụng trong XMLHttpRequestcác tiêu đề


0

Bạn chỉ có thể sử dụng urljoin với gốc tương đối '/' làm đối số thứ hai:

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

Nếu nó chứa ít hơn 3 dấu gạch chéo thì bạn đã có và nếu không thì chúng ta có thể tìm thấy sự xuất hiện giữa nó:

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.