• 【工具类】阿里域名关联ip(python版)


    获取代码如下

    # coding=utf-8
    
    import argparse
    import json
    import urllib
    import logging
    
    # 加载 ali 核心 SDK
    from aliyunsdkcore.client import AcsClient
    from aliyunsdkalidns.request.v20150109 import (
        DescribeSubDomainRecordsRequest,
        AddDomainRecordRequest,
        UpdateDomainRecordRequest,
        DeleteDomainRecordRequest,
    )
    
    logger = logging.getLogger(__name__)
    handler = logging.StreamHandler()
    handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s[%(filename)s:%(lineno)d] %(message)s"))
    logger.addHandler(handler)
    logger.setLevel(logging.INFO)
    
    
    # get_public_ip 获取外网IP
    # 备选url: http://www.3322.org/dyndns/getip 是最纯净的格式
    # 备选url1: http://pv.sohu.com/cityjson?ie=utf-8   json格式, 对获取值作进一步处理才能使用
    # 备选url2: curl -L tool.lu/ip curl方式获取, 对获取值作进一步处理才能使用
    def get_public_ip():
        url = "http://www.3322.org/dyndns/getip"  # 可考虑将此URL作为配置项,以便于未来更改
        try:
            with urllib.request.urlopen(url) as response:
                html = response.read()
                # 使用strip()代替replace("\n", ""),以删除所有前导和尾随空白
                ip = str(html, encoding="utf-8").strip()
                return ip
        except urllib.error.URLError as e:
            logger.info(f"Error fetching IP: {e.reason}")
            return None
    
    
    # 查询记录
    # {
    #   "TotalCount":  1,
    #   "PageSize":  20,
    #   "RequestId":  "DAD4AEC3-3F09-569E-88FF-0732E93CBDDE",
    #   "DomainRecords":  {
    #      "Record":  [
    #        {
    #           "Status":  "ENABLE",
    #           "Line":  "default",
    #           "RR":  "c",
    #           "Locked":  false,
    #           "Type":  "A",
    #           "DomainName":  "baidu.cn",
    #           "Value":  "127.0.0.1",
    #           "RecordId":  "880481632183704576",
    #           "TTL":  600,
    #           "Weight":  1
    #        }
    #      ]
    #   },
    #   "PageNumber":  1
    # }
    def get_domain_info(client, sub_domain, domain_name):
        request = DescribeSubDomainRecordsRequest.DescribeSubDomainRecordsRequest()
        request.set_accept_format("json")
    
        # 记录类型,A表示IP 地址记录,具体参考 https://ephen.me/2016/dns-rr/
        request.set_Type("A")
        request.set_SubDomain(sub_domain+"."+domain_name)
    
        try:
            response = client.do_action_with_exception(request)
            response_str = response.decode("utf-8")
    
            records = json.loads(response_str)
            return records
        except Exception as e:
            logger.error(f"An error occurred: {e}")
            return None
    
    
    def _send_req(request, client, value, rr, domainname):
        """
        发送DNS记录请求
    
        Args:
            request (DNSRequest): DNS请求对象
            client (DnsClient): DNS客户端对象
            value (str): 新的IP地址
            rr (str): 子域名名称
            domainname (str): 主域名
    
        Returns:
            dict: 包含TotalCount字段的字典,表示获取到的记录条数,0表示没有记录,其他数字表示有多少条相同记录,正常有记录的值应该为1,如果值大于1则应该检查是不是重复添加了相同的记录。
        """
    
        request.set_accept_format("json")
    
        # request.set_Priority('1')  # MX 记录时的必选参数
        request.set_TTL(
            "600"
        )  # 可选值的范围取决于你的阿里云账户等级,免费版为 600 - 86400 单位为秒
        request.set_Value(value)  # 新增的 ip 地址
        # 记录类型,IP 地址记录,具体参考 https://ephen.me/2016/dns-rr/
        request.set_Type("A")
        request.set_RR(rr)  # 子域名名称
        request.set_DomainName(domainname)  # 主域名
    
        # 获取记录信息,返回信息中包含 TotalCount 字段,表示获取到的记录条数 0 表示没有记录
        # 其他数字为多少表示有多少条相同记录,正常有记录的值应该为1,如果值大于1则应该检查是不是重复添加了相同的记录
        response = client.do_action_with_exception(request)
        response = str(response, encoding="utf-8")
        relsult = json.loads(response)
        return relsult
    
    
    def add_domain_record(client, value, rr, domain_name):
        request = AddDomainRecordRequest.AddDomainRecordRequest()
        return _send_req(request, client, value, rr, domain_name)
    
    
    def update_domain_record(client, value, rr, record_id):
        request = UpdateDomainRecordRequest.UpdateDomainRecordRequest()
        return _send_req(request, client, value, rr, record_id)
    
    
    def del_domain_record(client, sub_domain, domain_name):
        try:
            info = get_domain_info(client, sub_domain, domain_name)
            if info["TotalCount"] == 0:
                logger.info(f"{sub_domain}.{domain_name} not exist")
                return 0
            elif info["TotalCount"] == 1:
                record_id = info["DomainRecords"]["Record"][0]["RecordId"]
    
                request = DeleteDomainRecordRequest.DeleteDomainRecordRequest()
                request.set_accept_format("json")
                request.set_RecordId(record_id)
    
                result = client.do_action_with_exception(request)
                logger.info(f"del {sub_domain}.{domain_name} result {result}")
                return 0
            else:
                logger.warning("multiple resource records, please check at https://dns.console.aliyun.com")
                return -1
    
        except Exception as e:
            logger.error(f"error occurred {sub_domain}.{domain_name} result {e}")
            return -2
    
    
    def set_domain_record(client, value, sub_domain, domain_name):
        info = get_domain_info(client, sub_domain, domain_name)
    
        # 检查info是否为空以及其是否包含必要的键
        if not info or "TotalCount" not in info:
            logger.error("Failed to get domain info or invalid response format.")
            return
    
        if info["TotalCount"] == 0:
            result = add_domain_record(client, value, sub_domain, domain_name)
            logger.info(f"adding {value} for {sub_domain}.{domain_name} result {result}")
        elif info["TotalCount"] == 1:
            record_info = info.get("DomainRecords", {}).get("Record", [{}])[0]
            record_id = record_info.get("RecordId")
            old_ip = record_info.get("Value")
            if value == old_ip:
                logger.info(f"same val {value}, no need to update")
            else:
                result = update_domain_record(client, value, sub_domain, record_id)
                logger.info(f"update {value} for {sub_domain}.{domain_name} result {result}")
        else:
            logger.warning("multiple resource records, please check at https://dns.console.aliyun.com")
    
    
    # python alidns.py --key=xxx --secret=xxx --domain=baidu.cn
    if __name__ == "__main__":
        parser = argparse.ArgumentParser()
        parser.description='please enter correct para'
        # AccessKey 和 Secret  建议使用 RAM 子账户的 KEY 和 SECRET 增加安全性
        parser.add_argument("-k", "--key", help="accessKey", type=str, default="private accessKey")
        parser.add_argument("-s", "--secret", help="secret", type=str, default="private secret")
        parser.add_argument("-d", "--domain", help="domain name",  type=str, default="baidu.cn")
        args = parser.parse_args()
    
        public_ip = get_public_ip()
        logger.info(f"public_ip {public_ip}")
        
        # 地区节点 可选地区取决于你的阿里云帐号等级,普通用户只有四个,分别是杭州、上海、深圳、河北,具体参考官网API
        regionId = "cn-hangzhou"
        client = AcsClient(args.key, args.secret, regionId)  # 配置认证信息
    
        domain_name = args.domain       # 设置主域名
        sub_domains = ["a", "b", "c"]   # 子域名列表  列表参数可根据实际需求增加或减少值
    
        # 删除记录测试
        for sub_domain in sub_domains:
            del_domain_record(client, sub_domain, domain_name)
        
        # 获取记录测试
        for sub_domain in sub_domains:
            info = get_domain_info(client, sub_domain, domain_name)
            print(f"get-info: {json.dumps(info)}")
    
        for sub_domain in sub_domains:  # 循环子域名列表进行批量操作
            set_domain_record(client, public_ip, sub_domain, domain_name)
    
        # 获取记录测试
        for sub_domain in sub_domains:
            info = get_domain_info(client, sub_domain, domain_name)
            print(f"get-info: {json.dumps(info)}")
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213

    输入输出

    python alidns.py --key=xxx --secret=xxx --domain=baidu.cn
    
    2024-02-23 17:46:13,408 INFO[alidns.py:187] public_ip xxx.xxx.xxx.xxx
    2024-02-23 17:46:13,890 INFO[alidns.py:142] del a.baidu.cn result b'{"RequestId":"3FC56A68-678C-5039-A905-55151473925A","RecordId":"880481630604579840"}'
    2024-02-23 17:46:14,313 INFO[alidns.py:142] del b.baidu.cn result b'{"RequestId":"E2F92A34-130F-5108-A6B6-05139A3666C3","RecordId":"880481631418256384"}'
    2024-02-23 17:46:14,714 INFO[alidns.py:142] del c.baidu.cn result b'{"RequestId":"B6ACC80B-0F85-5603-8475-9B0583ED5B95","RecordId":"880481632183704576"}'
    get-info: {"TotalCount": 0, "PageSize": 20, "RequestId": "4A21718E-8DD1-5878-AD8E-3EA708C53716", "DomainRecords": {"Record": []}, "PageNumber": 1}
    get-info: {"TotalCount": 0, "PageSize": 20, "RequestId": "95405D16-2E81-54C5-B794-D73BEF51F35B", "DomainRecords": {"Record": []}, "PageNumber": 1}
    get-info: {"TotalCount": 0, "PageSize": 20, "RequestId": "09C39264-2CA7-5BFF-9250-9AE83242890C", "DomainRecords": {"Record": []}, "PageNumber": 1}
    2024-02-23 17:46:15,474 INFO[alidns.py:163] adding xxx.xxx.xxx.xxx for a.baidu.cn result {'RequestId': '11D855D8-1A9A-52C9-B0D4-0F0E5C161453', 'RecordId': '880482138503304192'}
    2024-02-23 17:46:15,831 INFO[alidns.py:163] adding xxx.xxx.xxx.xxx for b.baidu.cn result {'RequestId': '93A11426-5992-58A6-9D52-83ACC2310769', 'RecordId': '880482139254086656'}
    2024-02-23 17:46:16,188 INFO[alidns.py:163] adding xxx.xxx.xxx.xxx for c.baidu.cn result {'RequestId': 'DC94B74E-074E-5554-BCAC-BEEFD0AC8C30', 'RecordId': '880482140006968320'}
    get-info: {"TotalCount": 1, "PageSize": 20, "RequestId": "0D90F3A3-6CD9-5295-80E7-8AAE7D9D2C34", "DomainRecords": {"Record": [{"Status": "ENABLE", "Line": "default", "RR": "a", "Locked": false, "Type": "A", "DomainName": "baidu.cn", "Value": "xxx.xxx.xxx.xxx", "RecordId": "880482138503304192", "TTL": 600, "Weight": 1}]}, "PageNumber": 1}
    get-info: {"TotalCount": 1, "PageSize": 20, "RequestId": "0205D91F-123F-57B1-91F9-1C5D82B70911", "DomainRecords": {"Record": [{"Status": "ENABLE", "Line": "default", "RR": "b", "Locked": false, "Type": "A", "DomainName": "baidu.cn", "Value": "xxx.xxx.xxx.xxx", "RecordId": "880482139254086656", "TTL": 600, "Weight": 1}]}, "PageNumber": 1}
    get-info: {"TotalCount": 1, "PageSize": 20, "RequestId": "7653F278-088F-5CDE-9ACC-78958FCDF662", "DomainRecords": {"Record": [{"Status": "ENABLE", "Line": "default", "RR": "c", "Locked": false, "Type": "A", "DomainName": "baidu.cn", "Value": "xxx.xxx.xxx.xxx", "RecordId": "880482140006968320", "TTL": 600, "Weight": 1}]}, "PageNumber": 1}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  • 相关阅读:
    LeetCode精选200道--栈与队列篇
    搜题公众号搭建
    前端深入理解JavaScript面向对象编程与Class
    手边酒店V2独立版小程序 1.0.21 免授权+小程序前端
    错误:ModuleNotFoundError: No module named ‘httplib‘
    爬虫到底难在哪里?
    语文世界杂志语文世界杂志社语文世界编辑部2022年第9期目录
    MC-4/11/01/400 ELAU 软件允许用户完全访问相机设置
    Spring Bean自动装配的简介
    PTA 7-86 分支结构——大小写字母判断
  • 原文地址:https://blog.csdn.net/knowledgebao/article/details/136262267