如何在Python中进行DNS查找,包括引用/ etc/hosts?

Tob*_*ite 87 python dns

dnspython会非常好地进行我的DNS查找,但它完全忽略了内容/etc/hosts.

是否有一个python库调用,它会做正确的事情?即先检查etc/hosts,否则只回退到DNS查找?

Joc*_*zel 104

我真的不知道,如果你想要做的DNS查找自己或者如果你只是想要一台主机的IP地址.如果你想要后者,

import socket
print(socket.gethostbyname('localhost')) # result from hosts file
print(socket.gethostbyname('google.com')) # your os sends out a dns query
Run Code Online (Sandbox Code Playgroud)

  • 确实.Bortzmeyer的代码支持IPv4和IPv6. (8认同)
  • 据记录,_Python_ 中的 `socket.gethostbyname` 并未被弃用(从 3.10 和 3.11-dev 开始)。您引用的是 Linux 二进制文件的手册页,而不是 Python 库。 (5认同)

bor*_*yer 87

Python中的普通名称解析工作正常.为什么你需要DNSpython.只要使用插座getaddrinfo下面配置为您的操作系统的规则(Debian的,它遵循/etc/nsswitch.conf:

>>> print socket.getaddrinfo('google.com', 80)
[(10, 1, 6, '', ('2a00:1450:8006::63', 80, 0, 0)), (10, 2, 17, '', ('2a00:1450:8006::63', 80, 0, 0)), (10, 3, 0, '', ('2a00:1450:8006::63', 80, 0, 0)), (10, 1, 6, '', ('2a00:1450:8006::68', 80, 0, 0)), (10, 2, 17, '', ('2a00:1450:8006::68', 80, 0, 0)), (10, 3, 0, '', ('2a00:1450:8006::68', 80, 0, 0)), (10, 1, 6, '', ('2a00:1450:8006::93', 80, 0, 0)), (10, 2, 17, '', ('2a00:1450:8006::93', 80, 0, 0)), (10, 3, 0, '', ('2a00:1450:8006::93', 80, 0, 0)), (2, 1, 6, '', ('209.85.229.104', 80)), (2, 2, 17, '', ('209.85.229.104', 80)), (2, 3, 0, '', ('209.85.229.104', 80)), (2, 1, 6, '', ('209.85.229.99', 80)), (2, 2, 17, '', ('209.85.229.99', 80)), (2, 3, 0, '', ('209.85.229.99', 80)), (2, 1, 6, '', ('209.85.229.147', 80)), (2, 2, 17, '', ('209.85.229.147', 80)), (2, 3, 0, '', ('209.85.229.147', 80))]
Run Code Online (Sandbox Code Playgroud)

  • 很高兴添加转换步骤.`addrs = [str(i [4] [0])for for socket.getaddrinfo(name,80)]`给出了ips的列表. (4认同)

Tho*_*ner 9

听起来您不想自己解析 DNS。dnspython是一个独立的 DNS 客户端,它会忽略您的操作系统,因为它绕过了操作系统的实用程序。

我们可以查看一个名为 的 shell 实用程序getent来了解(类似 Debian 11)操作系统如何为程序解析 DNS。这可能是所有使用套接字实现的 *nix 类系统的标准。

请参阅man getent“hosts”部分,其中提到了 的使用getaddrinfo,我们可以将其视为man getaddrinfo

要在 Python 中使用它,我们必须从数据结构中提取一些信息:

import socket

def get_ipv4_by_hostname(hostname):
    # see `man getent` `/ hosts `
    # see `man getaddrinfo`

    return list(
        i        # raw socket structure
            [4]  # internet protocol info
            [0]  # address
        for i in 
        socket.getaddrinfo(
            hostname,
            0  # port, required
        )
        if i[0] is socket.AddressFamily.AF_INET  # ipv4

        # ignore duplicate addresses with other socket types
        and i[1] is socket.SocketKind.SOCK_RAW  
    )

print(get_ipv4_by_hostname('localhost'))
print(get_ipv4_by_hostname('google.com'))
Run Code Online (Sandbox Code Playgroud)


小智 5

list( map( lambda x: x[4][0], socket.getaddrinfo( \
     'www.example.com.',22,type=socket.SOCK_STREAM)))
Run Code Online (Sandbox Code Playgroud)

为您提供 www.example.com 的地址列表。(ipv4 和 ipv6)