从 python 中执行的命令 'host' 获取 IP

Obtaining IP from command 'host' executed inside python

我有这个功能可以显示域的第一个 ip:

def get_ip_address(url):
    command="host "+url
    process=os.popen(command)
    results=str(process.read()) 
    marker=results.find('has address')+12   
    print results[marker:].splitlines()[0]
    return results[marker:].splitlines()[0]

但这只显示了第一个 ip。我只想显示 ip。标记是没有 "has address" 如下所示(假设我输入 "reddit.com":

['151.101.65.140', 'reddit.com has address 151.101.129.140', 'reddit.com has address 151.101.193.140', 'reddit.com has address 151.101.1.140', 'reddit.com mail is handled by 1 aspmx.l.google.com.', 'reddit.com mail is handled by 10 aspmx2.googlemail.com.', 'reddit.com mail is handled by 10 aspmx3.googlemail.com.', 'reddit.com mail is handled by 5 alt1.aspmx.l.google.com.', 'reddit.com mail is handled by 5 alt2.aspmx.l.google.com.']

我只想显示 ips,而不是 reddit.com has address也不会显示 ip 的末尾,mail is handled等等。

我试过

def get_ip_address(url):
    command="host "+url
    process=os.popen(command)
    results=str(process.read()) 
    marker=results.find('has address')+12
    i=0
    arrayIps=[]
    while "has address" in results[marker:].splitlines()[i]:

        print results[marker:].splitlines()[i]
        arrayIps.append(results[marker:].splitlines()[i])
        print("array")
        print arrayIps[i]
        i=i+1
    return arrayIps

但是它不起作用!甚至没有返回任何有用的东西!

我期待的是一个数组(在本例中):

'151.101.65.140', '151.101.129.140', '151.101.193.140', '151.101.1.140'

尝试使用 .split() 在空格处拆分字符串 IP,然后取出其中的最后一项 [-1],然后在 [-1] 处拆分最后一项(应该是 IP 地址) =14=]。使用 ''.join(iterable) 连接 returned 的字符串,其中可迭代的是 .split('.') 的值。使用 .isnumeric() 检查连接的字符串是否为数值,如果为真,则打印并 return 最后一项。

def get_ip_address(url):
    command="host "+url
    process=os.popen(command)
    results=str(process.read())
    marker=results.find('has address')+12
    ip_list=[]
    for ip in results[marker:].splitlines()[0]:
        if ''.join(ip.split()[-1].split('.')).isnumeric():
            ip_list.append(ip.split()[-1])
    print ip_list
    return ip_list

坏消息是我似乎无法将 results=str(process.read()) 设置为任何内容。它目前只是 returns 一个空字符串,但希望你会有更多的运气 :D

(编辑:如您的评论所述,socket.getaddrinfo() 表现出色。在 Python 2.7 上不确定,但在 3.7.1 中有效)

(Edit2:这是您在 3.7.1 中的代码。在 2.7 中应该类似)

import socket
ip_list = []
for info in socket.getaddrinfo('reddit.com', 80):
    ip_list.append(info[-1][0])

看到它显示了您需要的多个主机。您的输出可以使用 map 函数

生成
In [132]: socket.getaddrinfo("reddit.com", 80, proto=socket.IPPROTO_TCP)
Out[132]: 
[(<AddressFamily.AF_INET: 2>,
  <SocketKind.SOCK_STREAM: 1>,
  6,
  '',
  ('151.101.65.140', 80)),
 (<AddressFamily.AF_INET: 2>,
  <SocketKind.SOCK_STREAM: 1>,
  6,
  '',
  ('151.101.1.140', 80)),
 (<AddressFamily.AF_INET: 2>,
  <SocketKind.SOCK_STREAM: 1>,
  6,
  '',
  ('151.101.129.140', 80)),
 (<AddressFamily.AF_INET: 2>,
  <SocketKind.SOCK_STREAM: 1>,
  6,
  '',
  ('151.101.193.140', 80))]


In [134]: list(map(lambda x:x[4][0],socket.getaddrinfo("reddit.com", 80, proto=socket.IPPROTO_TCP)))
Out[134]: ['151.101.129.140', '151.101.193.140', '151.101.65.140', '151.101.1.140']

您应该尝试使用 dig 命令而不是 host 并应用适当的正则表达式:

from subprocess import run, PIPE

def get_answer(url):
    response = run(["dig", "+noall", "+answer", "+short","{url}".format(url=url)], stdout=PIPE, universal_newlines=True)
    return response.stdout

备注:

编辑

如评论中所述,您可以使用 dig 中的 +short 选项删除正则表达式部分。