python实现阿里云域名动态解析IP

当我们有长期域名但是发现云服务器价格配置低价格昂贵时
就想有没有方法实现使用自己的电脑做服务器,这时我们需要解决一个问题
域名解析需要一个公网IP地址,家用的公网IP与云服务器不同,是不定时更新的,购买固定IP价格个人也是承受不起的。那我们可不可是动态修改IP呢?
答案是:可以的。

一、实现动态修改IP需要以下条件:

1、拥有实名的域名 例如:baidu.com
2、在阿里云注册 AccessKeyID 和 AccessSecret (控制台点击头像就能看到)
3、安装支持包:
pip install aliyun-python-sdk-core
pip install aliyun-python-sdk-domain
pip install aliyun-python-sdk-alidns
pip install requests
pip install APScheduler
4、使用代码

二、代码实现讲解

1、查询当前外网IP地址
2、使用AccessKey 秘钥查询 域名和完整域名 如:www.baidu.com
3、对比解析域名IP和当前域名IP是否存在或者IP是否一致
4、完整域名不存在新建域名解析,存在IP地址一致不修改反之修改

三、上代码:代码设置每5分钟查询更新

# -*- coding:utf-8 -*-
# @Author : 小福不认命
import datetime
import json
import requests
from aliyunsdkcore.client import AcsClient
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.schedulers.background import BackgroundScheduler
from aliyunsdkalidns.request.v20150109.DescribeSubDomainRecordsRequest import DescribeSubDomainRecordsRequest
from aliyunsdkalidns.request.v20150109.DeleteSubDomainRecordsRequest import DeleteSubDomainRecordsRequest
from aliyunsdkalidns.request.v20150109.AddDomainRecordRequest import AddDomainRecordRequest
from aliyunsdkalidns.request.v20150109.UpdateDomainRecordRequest import UpdateDomainRecordRequest

ipv4_flag = 1  # 是否开启ipv4 ddns解析,1为开启,0为关闭
ipv6_flag = 1  # 是否开启ipv6 ddns解析,1为开启,0为关闭
accessKeyId = ""  # 将accessKeyId改成自己的accessKeyId
accessSecret = ""  # 将accessSecret改成自己的accessSecret
domain = "baidu.com"  # 你的主域名
name_ipv4 = "www"  # 要进行ipv4 ddns解析的主机记录,即前缀
name_ipv6 = "www"  # 要进行ipv6 ddns解析的主机记录,即前缀 [此处对应的是阿里云解析中的 主机记录 应填写 www 或 @ 等。填写www解析后的域名为www.xxx.com;填写@解析后为主域名xxx.com]
ip_v4_url = [{"url": 'https://test.ipw.cn/', 'res_t': "text", 'key': "\n"}]
ip_v6_url = [{"url": 'https://test.ipw.cn/', 'res_t': "text", 'key': "\n"}]
client = AcsClient(accessKeyId, accessSecret, 'cn-hangzhou')

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"}


def update(RecordId, RR, Type, Value):  # 修改域名解析记录
    try:
        request = UpdateDomainRecordRequest()
        request.set_accept_format('json')
        request.set_RecordId(RecordId)
        request.set_RR(RR)
        request.set_Type(Type)
        request.set_Value(Value)
        response = client.do_action_with_exception(request)
        print("这是更新请求结果", response)
        return Type
    except Exception as e:
        print("更新结果异常", e)
        return False


# 添加新的域名解析记录
def add(DomainName, RR, Type, Value):
    try:
        request = AddDomainRecordRequest()
        request.set_accept_format('json')
        request.set_DomainName(DomainName)
        request.set_RR(RR)
        request.set_Type(Type)
        request.set_Value(Value)
        response = client.do_action_with_exception(request)
        print("这是新增请求结果", response)
        return True
    except Exception as e:
        print("这是新增请求结果异常", e)
        return False


def get_ip_address(type_re: int = 1):
    if type_re == 1:
        url_list = ip_v4_url
    elif type_re == 2:
        url_list = ip_v6_url
    else:
        return False
    for index, item in enumerate(url_list):
        try:
            res = requests.get(item['url'], headers=headers)
            if res.status_code == 200:
                if item['res_t'] == "json":
                    return res.json()[item['key']]
                res.encoding = "utf-8"
                return res.text.split(item['key'])[0]
            if res.status_code != 200 and index != len(url_list) - 1:
                continue
            else:
                return False
        except Exception as e:
            print("请求获取IP异常", e)
            print("请求获取IP异常", type_re)
            continue
    return False


def run_ipv4():
    print("运行ipv4:{}".format(datetime.datetime.now()))
    # 获得请求
    request = DescribeSubDomainRecordsRequest()
    # 设置返回类型
    request.set_accept_format('json')
    # 加载需要查询的域名
    request.set_DomainName(domain)
    # 查询域名前缀和域名拼接 完整域名
    request.set_SubDomain(name_ipv4 + '.' + domain)
    # 查询记录类型   A  解析IP
    request.set_Type("A")
    # 获取域名解析记录列表
    response = client.do_action_with_exception(request)
    print("获得查询结果", response)
    # 将返回的JSON数据转化为Python能识别的
    domain_list = json.loads(response)
    # 查询 当前服务器 IP地址
    # 使用IP.SB的接口获取ipv4地址
    ipv4 = get_ip_address(1)
    if not ipv4:
        return False
    print("获取到IPv4地址:%s" % ipv4)
    # 如果 前缀没有解析域名 新增
    if domain_list['TotalCount'] == 0:
        reso = add(domain, name_ipv4, "A", ipv4)
        if reso:
            print("新建域名解析成功")
        else:
            print("新建域名解析失败")
    # 如果 前缀存在解析获得解析的IP地址
    elif domain_list['TotalCount'] == 1:
        # 获得 解析的IP地址 不同则更新
        if domain_list['DomainRecords']['Record'][0]['Value'].strip() != ipv4.strip():
            reso = update(domain_list['DomainRecords']['Record'][0]['RecordId'], name_ipv4, "A", ipv4)
            if reso:
                print("修改域名解析成功")
            else:
                print("修改域名解析失败")
        # 相同IP地址 不进行操作
        else:
            print("IPv4地址没变")
    # 如果 解析有多个 前缀相同时
    elif domain_list['TotalCount'] > 1:
        # 删除 子域名请求
        request = DeleteSubDomainRecordsRequest()
        request.set_accept_format('json')
        request.set_DomainName(domain)
        request.set_RR(name_ipv4)
        # 解析类型 A
        request.set_Type("A")
        # 提交请求
        response = client.do_action_with_exception(request)
        print("这是删除请求结果", response)
        # 设置新增地址
        add(domain, name_ipv4, "A", ipv4)
        print("修改域名解析成功")


def run_ipv6():
    request = DescribeSubDomainRecordsRequest()
    # 设置请求类型
    request.set_accept_format('json')
    # 查询的域名
    request.set_DomainName(domain)
    # 查询域名的前缀
    request.set_SubDomain(name_ipv6 + '.' + domain)
    # 设定使用 ipv6
    request.set_Type("AAAA")
    # 获取域名解析记录列表
    response = client.do_action_with_exception(request)
    print("获得查询结果", response)
    # 将返回的JSON数据转化为Python能识别的
    domain_list = json.loads(response)
    # 使用IP.SB的接口获取ipv6地址
    ipv6 = get_ip_address(1)
    if not ipv6:
        return False
    print("获取到IPv6地址:%s" % ipv6)
    if domain_list['TotalCount'] == 0:
        reso = add(domain, name_ipv6, "AAAA", ipv6)
        if reso:
            print("新增域名解析成功")
        else:
            print("新增域名解析失败")
    elif domain_list['TotalCount'] == 1:
        if domain_list['DomainRecords']['Record'][0]['Value'].strip() != ipv6.strip():
            reso = update(domain_list['DomainRecords']['Record'][0]['RecordId'], name_ipv6, "AAAA", ipv6)
            if reso:
                print("修改域名解析成功")
            else:
                print("修改域名解析失败")
        else:
            print("IPv6地址没变")
    elif domain_list['TotalCount'] > 1:
        request = DeleteSubDomainRecordsRequest()
        request.set_accept_format('json')
        request.set_DomainName(domain)
        request.set_RR(name_ipv6)
        request.set_Type("AAAA")
        response = client.do_action_with_exception(request)
        print("存在多个IPv6地址返回结果", response)
        add(domain, name_ipv6, "AAAA", ipv6)
        print("修改域名解析成功")


# 定时任务 间隔时间启动 启动 第一次不会运行
def task_ipv4():
    she = BlockingScheduler()
    she.add_job(func=run_ipv4, trigger="interval", minutes=5, id="update_ip", name="update_ip")
    she.start()


if __name__ == '__main__':
    if ipv4_flag == 1:
        task_ipv4()
    # if ipv6_flag == 1:
    #     run_ipv6()

效果展示:
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小福不认命

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值