一个查找可用IP并自动生成 hosts 的脚本
标签: python ;
某些时候下载东西会撞墙,大抵是因为该域名被ban了。在最简单的情况下,只要找到该域名还可以访问的IP,写进hosts
文件中就可以访问了。不过查找可用IP的过程比较繁琐, 比较适合让脚本来干。
下面的脚本就是干这个事的。基本用法:
# 不带任何参数运行,直接查找 raw.githubusercontent.com
python findip.py
# 或者把目标域名作为参数传递给它
python findip.py xxx.xxx.xxx
程序会尝试读取系统hosts
文件的内容,替换或者添加指定域名的条目,再把内容打印到标准输出。可以用管道生成新的 hosts
文件,再替换回去。
python findip.py > hosts
程序运行依赖系统中安装有可运行的nslookup
命令,Windows 默认是安装了的,Linux 就不一定了,需要自行安装。
#!/usr/bin/env python3
import subprocess
import re
import platform
from pathlib import Path
import sys
arch = platform.system().lower()
coding = 'gb2312' if arch == 'windows' else 'utf-8'
pattern = '\\s*(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})\\s*?'
if platform.system().lower() == 'linux': pattern = 'Address:' + pattern
# 通过 DNS 查询主机的 IP 地址
def nslookup(domain):
ns_out = subprocess.Popen(['nslookup', domain, '8.8.8.8'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE).stdout.readlines()
iplist = []
for line in ns_out:
m = re.match(pattern, line.decode(coding))
if m:
iplist.append(m.group(1))
return iplist
# 返回 ping 的时延(ms)
def ping(host):
param = '-n' if arch == 'windows' else '-c'
cmd = ['ping', param, '1', host]
response = subprocess.run(cmd, stdout=subprocess.PIPE)
if response.returncode == 0:
out = response.stdout.decode(coding).splitlines()
for line in out:
m = re.match('.*=(\\d+\\.?\\d*) *ms', line)
if m: return(float(m.group(1)))
return None
# 查找可用 IP,并返回时延最短的主机IP
def lookup_ip(domain):
ips = nslookup(domain)
if len(ips) > 0:
timeout = None
ip = None
for i in ips:
t = ping(i)
if t:
if not timeout or t < timeout:
ip = i
timeout = t
if ip:
return(ip, timeout)
print('No available IP address found')
return None
print('No valid IP address for', domain, 'found')
return None
def update_hosts(ip, domain):
hosts = Path('C:/Windows/System32/drivers/etc/hosts') if arch == 'windows' else Path('/etc/hosts')
found_host = False
with open(hosts, 'r') as f:
for line in f:
if line.find(domain) >= 0:
print(f'{ip}\t{domain}')
found_host = True
else:
print(line, end="")
if not found_host:
print(f'\n{ip}\t{domain}')
if __name__ == '__main__':
domain = 'raw.githubusercontent.com'
if len(sys.argv) > 1:
domain = sys.argv[1]
ip, timeout = lookup_ip(domain)
if ip:
#print(f'{ip}\t{domain}')
update_hosts(ip,domain)