欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

利用Python+阿里云實現(xiàn)DDNS動態(tài)域名解析的方法

 更新時間:2019年04月01日 15:45:22   作者:mgsky1  
這篇文章主要介紹了利用Python+阿里云實現(xiàn)DDNS動態(tài)域名解析的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

引子

我想大家應該都很熟悉DNS了,這回在DNS前面加了一個D又變成了什么呢?這個D就是Dynamic(動態(tài)),也就是說,按照傳統(tǒng),一個域名所對應的IP地址應該是定死的,而使用了DDNS后,域名所對應的IP是可以動態(tài)變化的。那這個有什么用呢?
比如,在家里的路由器上連著一個raspberry pi(樹莓派),上面跑著幾個網(wǎng)站,我應該如和在外網(wǎng)環(huán)境下訪問網(wǎng)站、登陸樹莓派的SSH呢?

還有,家里的NAS(全稱Network Attach Storage 網(wǎng)絡附屬存儲,可以理解為私有的百度網(wǎng)盤)上存儲著大量的視頻、照片,如何在外網(wǎng)環(huán)境下和朋友分享呢?

這時,就要靠DDNS了!它會動態(tài)偵運營商分配給你的IP變化,并映射到域名上,這時就可以用域名來訪問家庭環(huán)境中的內(nèi)容了~

哈!有了域名,走遍天下都不怕有木有

實現(xiàn)效果(因為我已經(jīng)更新過了,所以它提示IP地址已存在,阿里云是不允許同一個IP重復更新的)

 

本地:

 

使用DDNS后,在外網(wǎng)環(huán)境下:

 

注:

這篇帖子適用于家庭寬帶的IP是公網(wǎng)IP的小伙伴,但是注意,這種公網(wǎng)IP是臨時的,會不定時進更改。判斷方法很簡單:先去百度搜索IP,查到自己的IP地址;接著本地開一個網(wǎng)站,比如在Windows下直接啟動IIS,Linux下安裝一個Apache或者Nginx啟動,使用它們的默認頁面;然后在路由器上設置好轉(zhuǎn)發(fā)規(guī)則,公網(wǎng)IP的網(wǎng)絡訪問端口最好不要用80,80端口可能被運營商封了;最后利用前面查到的公網(wǎng)IP+端口號訪問一下,看看能不能顯示內(nèi)網(wǎng)上的頁面,如果可以,恭喜你!

本文涉及到的技術點會比較多,比如爬蟲啊,設計模式啊,函數(shù)修飾符啊等等,可以算是一個綜合運用了吧~

實現(xiàn)思路

前面引文已經(jīng)說的很清楚了,就是探測家庭寬帶公網(wǎng)IP的變化,然后利用我們的程序?qū)⑦@個IP更新到它所綁定的二級域名上~
綜上,我的思路是這樣的:
1、利用Python去網(wǎng)上爬取自己真實的IP地址
2、利用阿里云所提供的接口更新IP

前期準備

1、一個域名(國內(nèi)需要備案,港澳臺和國外聽說是不要的,我也沒嘗試過)
2、將域名的解析設置到阿里云的云解析上
3、為我們的DDNS創(chuàng)建一個二級域名(例如 ddns.expamle.com)
4、安裝阿里云Python SDK(具體教程可以去阿里云上找
5、建議先去閱讀一下Python SDK的使用示例
6、約定:所有的API請求都返回JSON格式,所以要使用Python的JSON模塊進行解析

環(huán)境版本

1、Python 3.6
2、網(wǎng)頁解析利用BeautifulSoup 4
3、阿里的云解析API和Python SDK直接使用官方最新版本即可

實現(xiàn)步驟

項目結(jié)構(gòu)

 

注:

AcsClientSingleton.py => 阿里云AcsClient單實例類

CommonRequestSingleton.py => 阿里云CommonRequest的單實例類,獲取阿里云Common Request請求類

DDNS.py => 主程序

IpGetter.py =>獲取家庭寬帶實際的公網(wǎng)IP

Utils.py => 工具類

爬IP

首當其沖的就是要獲得我們實際的IP地址,推薦ip138.com

你看到的頁面是這樣的:

 

畫紅框的部分是一個iframe

 

其中的URL是一直會變化的,所以第一步是要獲取這個URL,我這里用到的解析框架是BeautifulSoup,感覺用Scrapy有點大材小用了

#獲得IP檢測的網(wǎng)頁URL
def getIpPage():
 url = "http://www.ip138.com/"
 response = urllib.request.urlopen(url)
 html = response.read().decode("gb2312")
 soup = BeautifulSoup(html, "lxml")
 _iframe = soup.body.iframe
 return _iframe["src"]

獲取到檢測IP地址的URL后,我們可以觀察一下網(wǎng)頁結(jié)構(gòu)

 

發(fā)現(xiàn),我們只需要獲取到center標簽的內(nèi)容,然后用正則提取出IP即可

#獲取IP地址
def getRealIp(url):
 response = urllib.request.urlopen(url)
 html = response.read().decode("gb2312")
 pattern = r"(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)"
 matchs = re.search(pattern,html)
 ip_addr = ""
 for i in range(1,5):
  ip_addr += matchs.group(i) + "."
 return ip_addr[:-1]

然后我們爬的工作就完成了,可以將這個獲取IP的過程進行封裝,放進工具類里

查文檔

阿里云云解析API文檔

我們需要用到的是UpdateDomainRecord這個Action。

可以觀察一下它的請求參數(shù)

 

在阿里的請求中,有一個公共參數(shù)(上面沒有提及),里面有一個簽名,這個簽名雖然官方提供了簽名生成的算法,不過如果自己實現(xiàn)很容易出錯,所以我們使用它的Python SDK。在簽名中,有一個至關重要的是AccessKey,AccessKey的生成可以在管理控制臺的AccessKeys模塊獲取

 

生成之后一定要保管好這個密鑰哦?。。。?!

由于云解析官方并沒有提供對應的SDK模塊,只提供了API,不過我們可以利用SDK中的CommonRequest對象來進行API操作。不知道各位有木有發(fā)現(xiàn)在更新域名解析記錄的請求參數(shù)中有一個RecordId,這個RecordId要利用DescribeDomainRecords這個Action來獲取。

如果每次請求都要使用CommonRequest對象,這樣難免會造成一定的內(nèi)存浪費,所以使用面向?qū)ο笤O計模式中的單例模式進行優(yōu)化。

class CommonRequestSing:
 #私有類變量
 __request = None

 #該修飾符將實例方法變成類方法
 #,因為類方法無法操作私有的類變量,所以使用實例方法進行操作,再進行轉(zhuǎn)換為類方法
 @classmethod
 def getInstance(self):
  if self.__request is None:
   self.__request = CommonRequest()
  return self.__request

同時,在構(gòu)造請求式,也會用到AcsClient對象,也可使用單例模式優(yōu)化

class AcsClientSing:
 __client = None
 @classmethod
 def getInstance(self):
  if self.__client is None:
   self.__client = AcsClient('Your_AccessKeyId', 'Your_AccessKeySecret', 'cn-hangzhou')
  return self.__client

這里用到了函數(shù)修飾符@classmethod,主要功能是將實例方法轉(zhuǎn)換為類方法。

這兩個單實例都可封裝進工具類中,直接調(diào)用工具類獲取實例就可以了,代碼會更美觀一些。

獲取RecordID

利用DescribeDomainRecords 這個Action來獲得。

#獲取二級域名的RecordId
 def getRecordId(domain):
  client = Utils.getAcsClient()
  request = Utils.getCommonRequest()
  request.set_domain('alidns.aliyuncs.com')
  request.set_version('2015-01-09')
  request.set_action_name('DescribeDomainRecords')
  request.add_query_param('DomainName', 'Your_DomainName eg.example.com')
  response = client.do_action_with_exception(request)
  jsonObj = json.loads(response.decode("UTF-8"))
  records = jsonObj["DomainRecords"]["Record"]
  for each in records:
   if each["RR"] == domain:
    return each["RecordId"]

更新解析記錄IP,DDNS邏輯核心

def DDNS():
 client = Utils.getAcsClient()
 recordId = Utils.getRecordId('ddns')
 ip = Utils.getRealIP()
 request = Utils.getCommonRequest()
 request.set_domain('alidns.aliyuncs.com')
 request.set_version('2015-01-09')
 request.set_action_name('UpdateDomainRecord')
 request.add_query_param('RecordId', recordId)
 request.add_query_param('RR', 'ddns')
 request.add_query_param('Type', 'A')
 request.add_query_param('Value', ip)
 response = client.do_action_with_exception(request)
 return response

if __name__ == "__main__":
 try:
  result = DDNS()
  print("成功!")
 except (ServerException,ClientException) as reason:
  print("失敗!原因為")
  print(reason.get_error_msg())

至此結(jié)束~然后設置好路由器端口映射,這時候你就可以使用ddns.example.com:XXX來進行訪問設置在家庭網(wǎng)絡中的資源了~
然后可以將這個Python代碼設置為定時任務,比如每天執(zhí)行一次,或者根據(jù)運營商的IP變化策略調(diào)整~

源碼(最新):https://github.com/mgsky1/DDNS

源碼(結(jié)構(gòu)與文章一樣的):點擊這里

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

最新評論