2009-07-01 32 views
39

cách bạn trích xuất tên miền từ URL, loại trừ bất kỳ tên miền phụ nào?Cách trích xuất tên miền cấp cao nhất (TLD) từ URL

nỗ lực đơn giản ban đầu của tôi là:

'.'.join(urlparse.urlparse(url).netloc.split('.')[-2:]) 

này làm việc cho http://www.foo.com, nhưng không http://www.foo.com.au. Có cách nào để làm điều này đúng cách mà không sử dụng kiến ​​thức đặc biệt về các TLD hợp lệ (Tên miền cấp cao nhất) hoặc mã quốc gia (vì chúng thay đổi).

nhờ

+2

Một câu hỏi có liên quan trước đây trên Stack Overflow: http://stackoverflow.com/questions/569137/how-to-get-domain-name-from-url –

+1

1: Các "đơn giản nỗ lực" trong việc này câu hỏi hoạt động tốt cho tôi, ngay cả khi nó trớ trêu thay đã không làm việc cho tác giả. – ArtOfWarfare

+0

Câu hỏi tương tự: http://stackoverflow.com/questions/14406300/python-urlparse-extract-domain-name-without-subdomain – user2314737

Trả lời

40

Không, không có "nội tại" cách nào để biết đó (ví dụ) zap.co.it là một tên miền phụ (vì công ty đăng ký Ý KHÔNG bán tên miền như co.it) trong khi zap.co.ukkhông phải là (vì nước Anh của công ty đăng ký KHÔNG bán các tên miền như co.uk, nhưng chỉ giống như zap.co.uk).

Bạn chỉ cần sử dụng bảng phụ (hoặc nguồn trực tuyến) để cho bạn biết hành vi nào của TLD đặc biệt như Vương quốc Anh và Úc - không có cách nào để từ bỏ việc nhìn chằm chằm vào chuỗi mà không có kiến ​​thức ngữ nghĩa bổ sung. tất nhiên nó có thể thay đổi, nhưng nếu bạn có thể tìm được nguồn trực tuyến tốt thì nguồn cũng sẽ thay đổi cho phù hợp, một hy vọng! -).

2

Có rất nhiều, nhiều TLD. Dưới đây là danh sách:

http://data.iana.org/TLD/tlds-alpha-by-domain.txt

Dưới đây là danh sách khác

http://en.wikipedia.org/wiki/List_of_Internet_top-level_domains

Dưới đây là một danh sách

http://www.iana.org/domains/root/db/

+0

Điều đó không hữu ích, bởi vì nó không cho bạn biết cái nào có "mức bổ sung ", giống như co.uk. –

+0

Lennart: Nó giúp, U có thể quấn chúng thành tùy chọn, trong một regex. –

40

Sử dụng this file of effective tldssomeone else tìm thấy trên trang web của Mozilla:

from __future__ import with_statement 
from urlparse import urlparse 

# load tlds, ignore comments and empty lines: 
with open("effective_tld_names.dat.txt") as tld_file: 
    tlds = [line.strip() for line in tld_file if line[0] not in "/\n"] 

def get_domain(url, tlds): 
    url_elements = urlparse(url)[1].split('.') 
    # url_elements = ["abcde","co","uk"] 

    for i in range(-len(url_elements), 0): 
     last_i_elements = url_elements[i:] 
     # i=-3: ["abcde","co","uk"] 
     # i=-2: ["co","uk"] 
     # i=-1: ["uk"] etc 

     candidate = ".".join(last_i_elements) # abcde.co.uk, co.uk, uk 
     wildcard_candidate = ".".join(["*"] + last_i_elements[1:]) # *.co.uk, *.uk, * 
     exception_candidate = "!" + candidate 

     # match tlds: 
     if (exception_candidate in tlds): 
      return ".".join(url_elements[i:]) 
     if (candidate in tlds or wildcard_candidate in tlds): 
      return ".".join(url_elements[i-1:]) 
      # returns "abcde.co.uk" 

    raise ValueError("Domain not in global list of TLDs") 

print get_domain("http://abcde.co.uk", tlds) 

kết quả trong:

abcde.co.uk 

Tôi đánh giá cao nó nếu ai đó cho tôi biết mà bit của trên có thể được viết lại theo một cách pythonic hơn. Ví dụ, phải có một cách tốt hơn để lặp qua danh sách last_i_elements, nhưng tôi không thể nghĩ ra. Tôi cũng không biết nếu ValueError là điều tốt nhất để nâng cao. Bình luận?

+10

Nếu bạn cần gọi getDomain() thường trong thực tế, chẳng hạn như trích xuất các tên miền từ một tệp nhật ký lớn, tôi khuyên bạn nên tạo một tập hợp tlds, ví dụ: tlds = set ([line.strip() cho dòng trong tldFile nếu dòng [0] không có trong "/ \ n"]). Điều này cung cấp cho bạn tra cứu thời gian liên tục cho từng kiểm tra đó cho dù một số mục có trong các tld hay không. Tôi thấy tốc độ khoảng 1500 lần cho các lần tra cứu (thiết lập so với danh sách) và cho toàn bộ hoạt động của tôi giải nén miền từ một tệp nhật ký dòng ~ 20 triệu, khoảng 60 lần tăng tốc (6 phút xuống từ 6 giờ). –

+1

Điều này thật tuyệt vời! Chỉ một câu hỏi nữa: đó là tệp 'effective_tld_names.dat' cũng được cập nhật cho các tên miền mới như' .amsterdam', '.vodka' và' .wtf'? – kramer65

+0

Danh sách hậu tố công khai của Mozilla được bảo trì thường xuyên, có, và bây giờ có nhiều thư viện Python bao gồm nó. Xem http://publicsuffix.org/ và các câu trả lời khác trên trang này. – tripleee

38

Dưới đây là một mô-đun python vĩ đại ai đó đã viết để giải quyết vấn đề này sau khi nhìn thấy câu hỏi này: https://github.com/john-kurkowski/tldextract

Module nhìn lên TLD trong Public Suffix List, mantained bởi tình nguyện viên Mozilla

Trích:

Mặt khác, tldextract biết tất cả các gTLD [Tên miền cấp cao chung chung là gì] và ccTLD [Tên miền cấp cao nhất của mã quốc gia] trông giống như bằng cách tra cứu số hiện đang sống theo số Public Suffix List. Vì vậy, với một URL, nó biết tên miền phụ của nó từ tên miền của nó, và miền của nó từ mã quốc gia của nó.

+1

Điều này làm việc cho tôi nơi 'tld' không thành công (nó đánh dấu một URL hợp lệ là không hợp lệ). – szeitlin

0

Đây là cách tôi xử lý nó:

if not url.startswith('http'): 
    url = 'http://'+url 
website = urlparse.urlparse(url)[1] 
domain = ('.').join(website.split('.')[-2:]) 
match = re.search(r'((www\.)?([A-Z0-9.-]+\.[A-Z]{2,4}))', domain, re.I) 
if not match: 
    sys.exit(2) 
elif not match.group(0): 
    sys.exit(2) 
+2

Có miền được gọi là .travel. Nó sẽ không hoạt động với mã trên. – Sri

19

Sử dụng python tld

https://pypi.python.org/pypi/tld

$ pips cài đặt tld

from tld import get_tld 
print get_tld("http://www.google.co.uk") 

Google.co.uk

hoặc không có giao thức:

from tld import get_tld 

get_tld("www.google.co.uk", fix_protocol=True) 

google.co.uk

+2

Điều này sẽ trở nên không đáng tin cậy hơn với các gTLD mới. –

+0

Xin chào, cảm ơn vì đã chỉ ra điều này. Tôi đoán, khi nói đến điểm mà các gTLD mới thực sự đang được sử dụng, một sửa chữa thích hợp có thể đi vào gói '' tld''. –

+0

Cảm ơn bạn @ArturBarseghyan! Nó rất dễ sử dụng với Python. Nhưng bây giờ tôi đang sử dụng nó cho sản phẩm cấp doanh nghiệp, có nên tiếp tục sử dụng nó ngay cả khi gTLD không được hỗ trợ? Nếu có, khi nào bạn cho rằng gTLDs sẽ được hỗ trợ? Cảm ơn bạn một lần nữa. –

0

Cho đến get_tld được cập nhật cho tất cả những người mới, tôi kéo tld từ lỗi. Chắc chắn đó là mã xấu nhưng nó hoạt động.

def get_tld(): 
    try: 
    return get_tld(self.content_url) 
    except Exception, e: 
    re_domain = re.compile("Domain ([^ ]+) didn't match any existing TLD name!"); 
    matchObj = re_domain.findall(str(e)) 
    if matchObj: 
     for m in matchObj: 
     return m 
    raise e 
Các vấn đề liên quan