1、开发环境

  1. Python 3.7.9
  2. Windows 10

2、开发准备

  1. pip3 install aliyun-python-sdk-core
  2. 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();

 

posted on 2023-05-07 03:44  我,猪八戒  阅读(234)  评论(0编辑  收藏  举报