使用Aiohttp+Asyncio请求Tripadvisor站点超时该如何解决
解决方案
问题根因
超时问题核心是Tripadvisor的反爬策略识别到了aiohttp请求和常规浏览器/requests请求的特征差异:
- requests会自动补充
Accept、Accept-Encoding、Accept-Language等常规请求头,你给aiohttp仅传了User-Agent,缺失的头信息会被判定为异常流量,服务器会直接挂起连接不返回响应 - aiohttp默认未设置全局请求超时,被拦截后会一直等待直到触发系统级超时抛出错误
- Windows平台下旧版asyncio默认使用的SelectorEventLoop对部分HTTPS站点的TLS握手支持存在缺陷,也会增加超时概率
修改后的可运行代码
from aiohttp import ClientSession, ClientTimeout, TCPConnector import asyncio import sys home_url = 'https://www.tripadvisor.com' # 补充完整和浏览器一致的请求头,不要只传User-Agent headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8', 'Upgrade-Insecure-Requests': '1' } async def main(): # 配置1:设置10秒总超时,避免长时间阻塞 # 配置2:TCPConnector开启ssl正常校验,Windows平台可按需调整配置 async with ClientSession( headers=headers, timeout=ClientTimeout(total=10), connector=TCPConnector(ssl=True) ) as session: tourist_sites_url = home_url + '/Attractions-g294245-Activities-a_allAttractions.true-Philippines.html' async with session.get(tourist_sites_url) as response: print(f'{response.status=}\n') print(await response.text()) if __name__ == '__main__': # Windows平台手动指定事件循环为ProactorEventLoop,解决TLS握手问题 if sys.platform == 'win32': asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) asyncio.run(main())
额外优化建议
- 如果仍偶发超时,可以在请求逻辑外层加重试逻辑,捕获TimeoutError后重试2-3次
- 高并发请求时建议限制并发数,避免触发站点频率限制
- 不要复用同一个ClientSession长时间大量请求,必要时定期新建会话更换请求特征
内容的提问来源于stack exchange,提问作者clarkycode
相关产品推荐
相关产品推荐

