Python模块用于进行nslookup查询。

40

是否有一个Python模块可以执行与nslookup相同的功能? 我计划使用nslookup来挖掘有关要抓取的URL的域的一些信息。我知道我可以使用os.sys调用nslookup,但我只是想知道是否已经有了这个Python模块。 提前致谢!

9个回答

53

我正在使用以下代码:

import socket

ip_list = []
ais = socket.getaddrinfo("www.yahoo.com",0,0,0,0)
for result in ais:
  ip_list.append(result[-1][0])
ip_list = list(set(ip_list))

或者使用推导式:

ip_list = list({addr[-1][0] for addr in socket.getaddrinfo(name, 0, 0, 0, 0)})

Socket 对于 nslookup 似乎不太有效,特别是当所有主机名有多个域时。 - Nathan McKaskle
1
这对我来说很有效,可以获取Kubernetes有状态集中IP列表。 - Mitchell Tracy

19

你需要使用DNSPython

import dns.resolver

answers = dns.resolver.query('dnspython.org', 'MX')
for rdata in answers:
    print 'Host', rdata.exchange, 'has preference', rdata.preference

这只返回IP,而不是fqdn。 - Nathan McKaskle
dnspython是一个用于处理DNS的实用工具,因此不使用/etc/hosts。对于简单的正向DNS查找,最好使用socket.gethostbyname()(在dnspython的github上找到)。 - Rafal

15

问题在于socket.gethostbyname()只返回一个IP地址,而nslookup则会返回尽可能多的IP地址。

我使用的是:

import subprocess

process = subprocess.Popen(["nslookup", "www.google.com"], stdout=subprocess.PIPE)
output = process.communicate()[0].split('\n')

ip_arr = []
for data in output:
    if 'Address' in data:
        ip_arr.append(data.replace('Address: ',''))
ip_arr.pop(0)

print ip_arr

它将打印:

['54.230.228.101', '54.230.228.6', '54.230.228.37', '54.230.228.80', '54.230.228.41', '54.230.228.114', '54.230.228.54', '54.230.228.23']

9

7

我需要在AWS Route 53中使用CNames来追踪A记录。即将 messaging.myCompany.com 转换为 moreSpecificMessaging.myCompanyInternal.com

我也使用Socket,但是有另一种比较隐蔽的方法。

import socket

addr1 = socket.gethostbyname_ex('google.com')

print(addr1)

https://docs.python.org/3/library/socket.html#socket.gethostbyname_ex


我们也可以调用 socket.gethostbyname('google.com')。https://docs.python.org/2/library/socket.html#socket.gethostbyname - HarlemSquirrel
gethostbyname() 不支持IPv6名称解析,应该使用getaddrinfo()来支持IPv4/v6双栈。 - Christoph Lösch

7
请注意,socket.getfqdn()函数可以返回主机名的完全限定名称。详见:http://docs.python.org/2/library/socket.html?highlight=socket.getaddrinfo#socket.getfqdn 例如:
python -c  'import socket; print(socket.gethostname()); print(socket.getfqdn());'
myserver
myserver.mydomain.local

但结果取决于/etc/hosts配置。如果你有:
$ cat /etc/hosts
127.0.0.1       myserver  localhost.localdomain  localhost
socket.getfqdn() 的结果将为:
python -c  'import socket; print(socket.getfqdn());'
localhost.localdomain

哎呀!为了解决这个问题,我知道的唯一方法是按如下更改/etc/hosts文件:

$ cat /etc/hosts
127.0.0.1       myserver  myserver.mydomain.local  localhost.localdomain  localhost

希望这有所帮助!

虽然这很正确和彻底,但它只查找本地系统的主机名/完全限定域名。OP问如何查找用于站点抓取的外部DNS名称。尽管如此,还是要给你一个+1的评价。 - VooDooNOFX
当我获取FQDN时,也许只有一半的服务器具有完整的FQDN,其余的只是主机名。为什么?Nslookup在这些没有FQDN的服务器上显示了FQDN。 - Nathan McKaskle
@NathanMcKaskle,请查看您的/etc/hosts文件:您可能会自己找到答案。 - Laurent LAPORTE
@LaurentLAPORTE 我们有多个DNS域和不同域中的数千台服务器,我正在尝试从主机名获取FQDN,但所有返回的都只是“主机名”。我的主机看起来像127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4,我不知道发生了什么。 - Nathan McKaskle

2

之前的答案是正确的,但这里我会使用socket,它“提供了对BSD套接字接口的访问。它在所有现代Unix系统、Windows、MacOS和可能的其他平台上都可用。”

import socket

distinct_ips = []
# 0,0,0,0  is for (family, type, proto, canonname, sockaddr)
#change some_site.com to whatever your are looking up of course
socket_info = socket.getaddrinfo("some_site.com",0,0,0,0)
for result in socket_info:
    ns_ip = result[4][0]
    if distinct_ips.count(ns_ip)==0:
        distinct_ips.append(ns_ip)
        print(ns_ip)

2

我正在使用以下代码:

import socket
addr1 = socket.gethostbyname('google.com')
addr2 = socket.gethostbyname('yahoo.com')
print(addr1, addr2)

1
gethostbyname()不支持IPv6名称解析,应使用getaddrinfo()来支持IPv4/v6双栈。 - Christoph Lösch

1
$ sudo apt install python-dns
$ python
>>> import DNS
>>> d = DNS.DnsRequest(server="1.1.1.1", timeout=1)                                       
>>> r = d.req(name="stackoverflow.com", qtype="A")
>>> [i['data'] for i in r.answers]
['151.101.129.69', '151.101.193.69', '151.101.1.69', '151.101.65.69']

进一步的细节,例如ttl也可以被访问,此外这种方法的优点是可以让你指定要使用哪个名称服务器,而不仅仅使用系统默认值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接