1、开发环境
- Python 3.7.9
- Windows 10
2、开发准备
- pip3 install aliyun-python-sdk-core
- pip3 install aliyun-python-sdk-alidns
3、具体实现
''' # 思想思路: # 1、从www.jsonip.com上获取外网IP地址; # 2、从保持的Record文件中或阿里云上获取记录的Record; # 3、判断1中的IP和2中的IP是否相同,不同则更新Record; # 4、不管是否更新了DDNS都从新记录Record到文件; ''' import os; import sys; import json; import datetime; import time; import urllib.request; from aliyunsdkcore.client import AcsClient from aliyunsdkcore.acs_exception.exceptions import ClientException from aliyunsdkcore.acs_exception.exceptions import ServerException from aliyunsdkalidns.request.v20150109 import DescribeDomainRecordsRequest from aliyunsdkalidns.request.v20150109 import UpdateDomainRecordRequest class DDNS: m_recordPath = 'AliRecord.log'; m_logPath = 'Trace.log'; '''------------------------------------------- # 保存外网IP地址; -------------------------------------------''' m_publicIP = ''; m_aliClient = None; m_doaminName = '你的域名'; m_accessKeyID = '阿里云上的accessKeyID'; m_accessKeySecret = '阿里云上的accessKeySecret'; m_aliRecord = ''; '''------------------------------------------- # 初始化类示例; # 内部获取外网IP地址; # 内部获取阿里云DDNS记录; -------------------------------------------''' def __init__(self): # 初始化日志和记录文件路径 self.m_logPath = sys.path[0] + '\\Trace.log'; self.m_recordPath = sys.path[0] + '\\AliRecord.log'; self.Trace(self.m_logPath); self.Trace(self.m_recordPath); # 删除日志文件和Record文件 self.DeleteFile(self.m_logPath); # 初始化阿里云的Client self.m_aliClient = AcsClient(self.m_accessKeyID, self.m_accessKeySecret); # 获取外网IP地址 self.m_publicIP = self.GetPublicIP(); '''------------------------------------------- # 获取本机的外网IP地址 -------------------------------------------''' def GetPublicIP(self): httpHead = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0)'}; requestx = urllib.request.Request('http://jsonip.com', headers=httpHead); retValue = urllib.request.urlopen(requestx); retValue = json.load(retValue)['ip']; self.Trace('当前外网IP地址 = ' + retValue); return retValue; '''------------------------------------------- # 获取记录的IP;先判断本地文件中保持的IP, # 如果不存在文件,则从阿里云上获取记录的IP; # 如果存在文件,则从文件中获取IP地址; -------------------------------------------''' def GetRecord(self): msg = ''; if os.path.isfile(self.m_recordPath): file = open(self.m_recordPath, 'r'); r = file.read(); file.close(); msg = '当前文件内容: '; else: request = DescribeDomainRecordsRequest.DescribeDomainRecordsRequest(); #request.set_action_name("DescribeDomainRecords"); #request.set_RRKeyWord(self.m_rrKeyword); #request.set_TypeKeyWord(self.m_keywordType); request.set_DomainName(self.m_doaminName); r = self.m_aliClient.do_action_with_exception(request).decode("UTF-8"); msg = '阿里云获取内容: '; self.Trace(msg + r); return r; '''------------------------------------------- # 将阿里云上获取的信息,记录到文件中 -------------------------------------------''' def WriteRecord(self): self.Trace('写入阿里云DDNS的记录 = ' + self.m_recordPath); self.DeleteFile(self.m_recordPath); self.WriteFile(self.m_recordPath, self.m_aliRecord); '''------------------------------------------- # 记录日志 -------------------------------------------''' def Trace(self, v): tm = datetime.datetime.now(); vv = datetime.datetime.strftime(tm, '%H:%M:%S'); self.WriteFile(self.m_logPath, '【' + vv + '】' + v + '\r\n'); print(v); '''------------------------------------------- # 写文件 -------------------------------------------''' def WriteFile(self, f, v): # 这里以追加的方式打开文件 file = open(f, 'a'); file.write(v); file.close(); '''------------------------------------------- # 删除文件 -------------------------------------------''' def DeleteFile(self, f): # 文件存在才删除 if os.path.isfile(f): os.remove(f); '''------------------------------------------- # 获取阿里云中解析的记录ID -------------------------------------------''' def GetRecordId(self): record = json.loads(self.m_aliRecord); saveID = record["DomainRecords"]["Record"][0]["RecordId"]; self.Trace("记录中的ID = " + saveID); return saveID; '''------------------------------------------- # 获取阿里云中解析的IP地址 -------------------------------------------''' def GetRecordIP(self): record = json.loads(self.m_aliRecord); saveIP = record["DomainRecords"]["Record"][0]["Value"]; self.Trace("记录中的IP = " + saveIP); return saveIP; '''------------------------------------------- # 获取阿里云中解析的RR值 -------------------------------------------''' def GetRecordRR(self): record = json.loads(self.m_aliRecord); saveRR = record["DomainRecords"]["Record"][0]["RR"]; self.Trace("记录中的RR = " + saveRR); return saveRR; '''------------------------------------------- # 获取阿里云中解析的Type值 -------------------------------------------''' def GetRecordType(self): record = json.loads(self.m_aliRecord); vvType = record["DomainRecords"]["Record"][0]["Type"]; self.Trace("记录中的Type = " + vvType); return vvType; '''------------------------------------------- # 向阿里云设置DDNS记录 -------------------------------------------''' def SetRecord(self): recordId = self.GetRecordId(); recordType = self.GetRecordType(); recordRR = self.GetRecordRR(); request = UpdateDomainRecordRequest.UpdateDomainRecordRequest(); request.set_action_name("UpdateDomainRecord"); request.set_RecordId(recordId); request.set_Type(recordType); request.set_RR(recordRR); request.set_Value(self.m_publicIP); self.Trace("执行更新, 上传IP = " + self.m_publicIP); try: self.m_aliClient.do_action_with_exception(request); except ServerException as e: self.Trace('更新阿里云DDNS异常, 删除本地Record文件 = ' + self.m_recordPath); self.DeleteFile(self.m_recordPath); return 0; return 1; '''------------------------------------------- # 执行DDNS; # 1、先判断IP是否相同; # 2、如果不相同,则更新IP; -------------------------------------------''' def RunDDNS(self): retVal = 1; # 获取阿里云DDNS记录 self.m_aliRecord = self.GetRecord(); # 判断当前IP地址与记录中的IP不同,则更新DDNS记录 if self.m_publicIP != self.GetRecordIP(): retVal = self.SetRecord(); else: self.Trace('不执行更新'); if retVal == 1: self.WriteRecord(); return retVal; '''----------------------------------------------- # 执行代码 -----------------------------------------------''' if __name__ == '__main__': aliyun = DDNS(); if ( aliyun.RunDDNS() == 0 ): aliyun.Trace('第二次执行'); aliyun.RunDDNS();