1. 程式人生 > >獲取URL中的一級域名

獲取URL中的一級域名

關於一級域名的含義請自行查詢,這裡不再詳述

下面直接上程式碼

#! /usr/bin/env python 

# -*- coding: UTF-8 -*-
'''
Created on 2015-10-15


@author: WFJ
'''


import re
import urlparse
import traceback

#這是國家級域名字尾字串,如果有新增加,請按照“字尾-說明"的格式新增
country_domain_names = """ad-Andorra安道爾
ae-United Arab Emirates阿聯酋
af-Afghanistan阿富汗
ag-Antigua and Barbuda安地卡及巴布達
ai-Anguilla安圭拉
al-Albania阿爾巴尼亞
am-Armenia亞美尼亞
an-Netherlands Antilles荷蘭屬地
ao-Angola安哥拉
aq-Antarctica南極洲
ar-Argentina阿根廷
as-American Samoa東薩摩亞
at-Austria奧地利
au-Australia澳大利亞
aw-Aruba阿魯巴
az-Azerbaijan亞塞拜然
ba-Bosnia Herzegovina波黑
bb-Barbados巴貝多
bd-Bangladesh孟加拉
be-Belgium比利時
bf-Burkina Faso布吉納法索
bg-Bulgaria保加利亞
bh-Bahrain巴林
bi-Burundi蒲隆地
bj-Benin貝南
bm-Bermuda百慕大
bn-Brunei Darussalam汶萊
bo-Bolivia玻利維亞
br-Brazil巴西
bs-Bahamas巴哈馬
bt-Bhutan不丹
bv-Bouvet Island布韋島
bw-Botswana伯茲瓦納
by-Belarus白俄羅斯
bz-Belize貝里斯
ca-Canada加拿大
cc-Cocos Islands科科斯群島
cf-Central African Republic中非
cg-Congo剛果
ch-Switzerland瑞士
ci-Ivory Coast象牙海岸
ck-Cook Islands庫克群島
cl-Chile智利
cm-Cameroon喀麥隆
cn-China中國
co-Colombia哥倫比亞
cq-Equatorial Guinea赤道幾內亞
cr-Costa Rica哥斯大黎加
cu-Cuba古巴
cv-Cape Verde維德角
cx-Christmas Island聖誕島(英屬)
cy-Cyprus塞普勒斯
cz-Czech Republic捷克
de-Germany德國
dj-Djibouti吉布提
dk-Denmark丹麥
dm-Dominica多明尼加聯邦
do-Dominican Republic多明尼加
dz-Algeria阿爾及利亞
ec-Ecuador厄瓜多
ee-Estonia愛沙尼亞
eg-Egypt埃及
eh-Western Sahara西薩摩亞
es-Spain西班牙
et-Ethiopia衣索比亞
ev-El Salvador薩爾瓦多
fi-Finland芬蘭
fj-Fiji斐濟
fk-Falkland Islands福克蘭群島
fm-Micronesia密克羅尼西亞
fo-Faroe Islands法羅群島
fr-France法國
ga-Gabon加彭
gb-Great Britain (UK)大不列顛聯合王國
gd-Grenada格瑞那達
ge-Georgia喬治亞
gf-French Guiana法屬蓋亞那
gh-Ghana迦納
gi-Gibraltar直布羅陀
gl-Greenland格陵蘭群島
gm-Gambia甘比亞
gn-Guinea幾內亞
gp-Guadeloupe瓜德羅普島(法屬)
gr-Greece希臘
gt-Guatemala瓜地馬拉
gu-Guam關島
gw-Guinea-Bissau幾內亞比索
gy-Guyana蓋亞那
hk-Hong Kong香港
hm-Heard 赫德與麥克唐納群島
hn-Honduras宏都拉斯
hr-Croatia克羅埃西亞
ht-Haiti海地
hu-Hungary匈牙利
id-Indonesia印度尼西亞
ie-Ireland愛爾蘭
il-Israel以色列
in-India印度
io-British Indian Ocean Territory英屬印度洋領地
iq-Iraq伊拉克
ir-Iran伊朗
is-Iceland冰島
it-Italy義大利
jm-Jamaica牙買加
jo-Jordan約旦
jp-Japan日本
ke-Kenya肯亞
kg-Kyrgyz Stan吉爾吉斯斯坦
kh-Cambodia柬埔塞
ki-Kiribati吉里巴斯
km-Comoros葛摩
kn-St. Kitts 聖克里斯多福及尼維斯
kp-Korea-North朝鮮
kr-Korea-South韓國
kw-Kuwait科威特
ky-Cayman Islands開曼群島(英屬)
kz-Kazakhstan哈薩克
la-Lao People's Republic寮國
lb-Lebanon黎巴嫩
lc-St. Lucia聖露西亞島
li-Liechtenstein列支敦斯登
lk-Sri Lanka斯里蘭卡
lr-Liberia賴比瑞亞
ls-Lesotho賴索托
lt-Lithuania立陶宛
lu-Luxembourg盧森堡
lv-Latvia拉脫維亞
ly-Libya利比亞
ma-Morocco摩洛哥
mc-Monaco摩納哥
md-Moldova摩爾多瓦
mg-Madagascar馬達加斯加
mh-Marshall Islands馬紹爾群島
ml-Mali馬裡
mm-Myanmar緬甸
mn-Mongolia蒙古
mo-Macao澳門
mp-Northern Mariana Islands北馬裡亞納群島
mq-Martinique馬提尼克島(法屬)
mr-Mauritania茅利塔尼亞
ms-Montserrat蒙塞拉特島
mt-Malta馬爾他
mv-Maldives馬爾地夫
mw-Malawi馬拉維
mx-Mexico墨西哥
my-Malaysia馬來西亞
mz-Mozambique莫三比克
na-Namibia納米比亞
nc-New Caledonia新喀里多尼亞
ne-Niger尼日
nf-Norfolk Island諾福克島
ng-Nigeria奈及利亞
ni-Nicaragua尼加拉瓜
nl-Netherlands荷蘭
no-Norway挪威
np-Nepal尼泊爾
nr-Nauru諾魯
nt-Neutral Zone中立區
nu-Niue紐埃
nz-New Zealand紐西蘭
om-Oman阿曼
pa-Panama巴拿馬
pe-Peru祕魯
pf-French Polynesia法屬玻利尼西亞
pg-Papua New Guinea巴布亞紐幾內亞
ph-Philippines菲律賓
pk-Pakistan巴基斯坦
pl-Poland波蘭
pm-St. Pierre 聖皮埃爾和密克隆群島
pn-Pitcairn Island皮特克恩島
pr-Puerto Rico波多黎各
pt-Portugal葡萄牙
pw-Palau帛琉
py-Paraguay巴拉圭
qa-Qatar卡達
re-Reunion Island留尼汪島(法屬)
ro-Romania羅馬尼亞
ru-Russian Federation俄羅斯
rw-Rwanda盧安達
sa-Saudi Arabia沙烏地阿拉伯
sb-Solomon Islands索羅門群島
sc-Seychelles塞席爾
sd-Sudan蘇旦
se-Sweden瑞典
sg-Singapore新加坡
sh-St. Helena海倫娜
si-Slovenia斯洛維尼亞
sj-Svalbard 斯瓦爾巴特和揚馬延島
sk-Slovakia斯洛伐克
sl-Sierra Leone獅子山
sm-San Marino聖馬利諾
sn-Senegal塞內加爾
so-Somalia索馬利亞
sr-Suriname蘇利南
st-Sao Tome 聖多美和普林西比
su-USSR蘇聯
sy-Syrian Arab Republic敘利亞
sz-Swaziland史瓦濟蘭
tc-Turks 特克斯和凱科斯群島
td-Chad查德
tf-French Southern Territories法屬南半球領地
tg-Togo多哥
th-Thailand泰國
tj-Tajikistan塔吉克
tk-Tokelau托克勞群島
tm-Turkmenistan土庫曼
tn-Tunisia突尼西亞
to-Tonga湯加
tp-East Timor東帝汶
tr-Turkey土耳其
tt-Trinidad 千里達及托巴哥
tv-Tuvalu圖瓦魯
tw-Taiwan臺灣
tz-Tanzania坦尚尼亞
ua-Ukrainian SSR 烏克蘭
ug-Uganda烏干達
uk-United Kingdom英國
us-United States美國
uy-Uruguay烏拉圭
va-Vatican City State梵地岡
vc-St.Vincent 聖文森及格瑞那丁
ve-Venezuela委內瑞拉
vg-Virgin Islands維京群島
vn-Vietnam越南
vu-Vanuatu萬那杜
wf-Wallis 瓦利斯和富圖鈉群島
ws-Samoa西薩摩亞
ye-Yemen葉門
yu-Yugoslavia南斯拉夫
za-South Africa南非
zm-Zambia尚比亞
zr-Zaire扎伊爾
zw-Zimbabwe辛巴威"""

#這是國際級域名字尾字串,如果有新增加,請按照“字尾-說明"的格式新增
international_domain_names = """.com-商業機構,任何人都可以註冊
.edu-教育機構
.gov-政府部門
.int-國際組織
.mil-美國軍事部門
.net-網路組織,例如因特網服務商和維修商,現在任何人都可以註冊
.org-非盈利組織,任何人都可以註冊
.biz-商業
.info-網路資訊服務組織
.pro-用於會計、律師和醫生
.name-用於個人
.museum-用於博物館
.coop-用於商業合作團體
.aero-用於航空工業
.xxx-用於成人、色情網站
.idv-用於個人"""




class SLD(object):
    """
            該方法的準確與否取決於頂級域名字尾庫的完善性,目前只添加了國際級域名字尾和國家級域名字尾
    """
    def __init__(self):
        #url格式校驗的正則表示式
        self.url_regex = r"^(http://|https://){0,1}[A-Za-z0-9][A-Za-z0-9\-\.]+[A-Za-z0-9]\.[A-Za-z]{2,}[\43-\176]*$"
        #頂級域名字尾字典
        self.top_domain_suffix = self.get_top_domain_suffix()


    def get_top_domain_suffix(self):
        "獲取頂級域名字尾"
        "將國家域名字尾、國際域名字尾以及兩者的結合生成一個字典,{'.com.cn':None, '.cn':None}這種格式,這種格式可以提高查詢速度"
        k_1 = map(lambda s:".%s"%s.split("-")[0], country_domain_names.split("\n"))
        k_2 = map(lambda s:s.split("-")[0], international_domain_names.split("\n"))
        mem_dict = {}.fromkeys(["%s%s"%(k2,k1) for k2 in k_2 for k1 in k_1])
        mem_dict.update({}.fromkeys(k_1))
        mem_dict.update({}.fromkeys(k_2))
        return mem_dict




    def get_host(self, url):
        "獲取url的host"
        host = ""
        if re.match(self.url_regex, url):
            if url.startswith("http"):
                host_port = urlparse.urlparse(url)[1]
                host = host_port.split(":")[0]
            elif "/" in url:
                host = url[:url.find("/")].split(":")[0]
            else:
                host = url
        else:
            print "[%s] not a url" %url
        return host
           
    def get_l_s_r(self, c, h):
        "返回字串h中字元c的位置l,c右邊的部分s,左邊的部分r"
        l = h.rindex(c)
        s = h[l:]
        r = h[:l]
        return l,s,r

    #傳入引數url,返回一級域名,返回空表示url不規範    

    def get_second_level_domain(self, url):

        try:
            second_level_domain = ""
            host = self.get_host(url)
            dot_num = host.count(".")
            #根據host中的點"."去判斷host中頂級域名的結構
            if dot_num >= 2:
                dot_1,suffix_1,remainder_1 = self.get_l_s_r(".", host)
                dot_2,suffix_2,remainder_2 = self.get_l_s_r(".", remainder_1)
                #對國家與國際結合的域名字尾進行判斷
                if self.top_domain_suffix.has_key(suffix_2):
                    dot_3 = remainder_2.rindex(".")
                    second_level_domain = host[dot_3+1:]
                #對國家或國際域名字尾進行判斷
                elif self.top_domain_suffix.has_key(suffix_1):
                    second_level_domain = host[dot_2+1:]
                else:
                    print "['%s'] get top domain error!" %host
               
            else:
                dot_1,suffix_1,remainder_1 = self.get_l_s_r(".", host)
                #只能是國家或國際域名字尾,進行判斷
                if self.top_domain_suffix.has_key(suffix_1):
                    second_level_domain = host
                else:
                    print "['%s'] get top domain error!" %host
            return second_level_domain
        
        except:
            traceback.print_exc()
   

#這下面是測試程式碼
if __name__ == '__main__':
    a = SLD()
    for u in ["https://www.sina.com.cn:80/news/1/index.html", "https://www.jd.com.cn:80", "https://www.sina.com/","www.baidu.com.cn/news/1/index.html", "news.aodun.com.cn/1/a.html", "aodun.com", "d.adf.jf.cn", "adf.adfkj","a.news.aodun.com.cn:80/1/a.html"]:
        print a.get_second_level_domain(u)