在使用python开发的时候,发现requests能请求到数据,而aiohttp需要指定dns才能获取数据。
这个问题是因为 aiohttp 默认使用 AsyncResolver(基于 aiodns),它需要系统 DNS 配置支持。而 requests 使用的是系统默认的 DNS 解析方式(通常是阻塞式的 socket 解析)。
以下是几种解决方案:
方案1:使用 ThreadedResolver(推荐)
最简单的方案是让 aiohttp 使用和 requests 类似的线程 DNS 解析器:
import aiohttp
import asyncio
async def fetch_data():
# 使用 ThreadedResolver 替代默认的 AsyncResolver
connector = aiohttp.TCPConnector(
resolver=aiohttp.resolver.ThreadedResolver()
)
async with aiohttp.ClientSession(connector=connector) as session:
async with session.get('http://example.com') as response:
return await response.text()
# 使用
asyncio.run(fetch_data())
方案2:自定义 DNS 服务器
如果需要指定特定的 DNS 服务器:
import aiohttp
import asyncio
from aiohttp.resolver import AsyncResolver
async def fetch_data():
# 指定 DNS 服务器,例如使用 Google DNS
resolver = AsyncResolver(nameservers=["8.8.8.8", "8.8.4.4"])
connector = aiohttp.TCPConnector(resolver=resolver)
async with aiohttp.ClientSession(connector=connector) as session:
async with session.get('http://example.com') as response:
return await response.text()
asyncio.run(fetch_data())
方案3:安装并配置 aiodns
确保正确安装了 aiodns 和 pycares:
pip install aiodns pycares
然后在代码中可能还需要配置:
import aiohttp
import asyncio
async def fetch_data():
# 可以设置超时时间
timeout = aiohttp.ClientTimeout(total=10)
async with aiohttp.ClientSession(timeout=timeout) as session:
async with session.get('http://example.com') as response:
return await response.text()
asyncio.run(fetch_data())
方案4:全局设置(所有请求生效)
如果想让整个应用都使用 ThreadedResolver:
import aiohttp
import asyncio
class CustomClientSession(aiohttp.ClientSession):
def __init__(self, *args, **kwargs):
connector = aiohttp.TCPConnector(
resolver=aiohttp.resolver.ThreadedResolver()
)
super().__init__(connector=connector, *args, **kwargs)
# 使用自定义 Session
async def fetch_data():
async with CustomClientSession() as session:
async with session.get('http://example.com') as response:
return await response.text()
asyncio.run(fetch_data())
推荐解决方案
对于大多数情况,方案1(ThreadedResolver) 是最简单且兼容性最好的解决方案,因为它使用与 requests 相同的方式解析 DNS,只是在线程池中执行以避免阻塞。如果性能要求较高且 DNS 解析频繁,可以考虑方案2,指定可靠的公共 DNS 服务器。

