近期做过一个判断域名所对应的网站是否可以正常提供服务的功能。开始的思路就是按照域名文件,逐个进行获取ip地址并且访问获取返回值。但是在执行过程中发现,获取域名ip地址耗时比较长,导致整个程序执行时间都被拉长了。为了缩短程序执行时间就想着能不能用协程试试。因为Python的多线程实际上是假的多线程,所以就没有选择多线程作为解决思路。
我选的是使用asyncio标准库。
首先把dns查询获取ip这个耗时最长的功能,写成一个async函数。这样就可以用await来修饰,将查询挂起。
#-*- coding:UTF-8 -*-
import dns.resolver
import os,time
import httplib2
import asyncio
now = lambda : time.time()#定义一个获取当前时间的匿名函数
start=now()#获取程序开始执行的时间
#appdomain = 'xn--164b'
async def dns_query(domain):#定义dns查询函数,该函数的dns查询过程会消耗比较多的时间
iplist = []
domain_ips=dns.resolver.query(domain,'A')
for i in domain_ips.response.answer:
for j in i.items:
if j.rdtype==28:
iplist.append(j.address)
return iplist
第二,定义一个async函数来完成dns查询后的其他操作,我用的是httplib2来获取web头和content。下边的callback函数时开始测试绑定回调用的,测试完功能没啥问题就注释掉了。
async def get_iplist(domain = ''):
try:
A = await dns_query(domain)#将消耗比较多的操作放到await后,执行时挂起。#await 后边必须跟一个awaitable对象,须是协程
for ip in A:
checkurl=ip+":80"
getcontent=""
httplib2.socket.setdefaulttimeout(5)
conn=httplib2.Http()
try:
resp,getcontent=conn.request("http://"+checkurl)
finally:
if resp['status']=='200':
print("{} is ok!".format(ip))
return ip
except Exception as e:
print("dns resolver error %s" % str(e))
return
#def callback(future):#绑定回调函数
# for ip in future.result():
# checkurl=ip+":80"
# getcontent=""
# httplib2.socket.setdefaulttimeout(5)
# conn=httplib2.Http()
# try:
# resp,getcontent=conn.request("http://"+checkurl)
# finally:
# if resp['status']=='200':
# print("{} is ok!".format(ip))
第三、现在的domain_list.txt文件不算太大,但是域名的增长速度比较快这个文件的内容在后期会比较大,所以用了with open的方式打开文件,逐行读取文件产生一个生成器,自动调用next读取下一行数据。这种方式可以避免domain_list文件太大之后一次性读取造成内存不足。(原谅我用的小服务器只有8G的可怜内存~~~)。
第四、创建一个事件循环,并且把循环产生的task添加到事件循环中。
tasks=[]
with open('domain_list.txt','r') as file:
for domain_line in file:
coroutine=get_iplist(domain_line.strip())
task=asyncio.ensure_future(coroutine)
# task.add_done_callback(callback)
tasks.append(task)
#couortine1=get_iplist('xn--zf')
loop=asyncio.get_event_loop()
#task1=asyncio.ensure_future(couortine1)
#task1.add_done_callback(callback)
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
print("Time Cost is:",now() - start)
完成,后续其实还将探测结果写到文件中通过smtplib标准库发送到了我们的报警邮箱里。不过那个功能比较好写,就不在这贴了。
本文介绍了一种利用Python的asyncio库实现的高效域名检测方案。通过对DNS查询和HTTP请求等耗时操作采用协程处理,大幅提高了检测效率。文章详细展示了如何编写异步函数并结合事件循环来并发处理大量域名的检测任务。
2149

被折叠的 条评论
为什么被折叠?



