requests.get 和 aiohttp GET 和 Httpx 模块之间的不同结果

Dan*_*nik 5 python python-requests python-asyncio aiohttp httpx

我正在尝试访问具有机器人防护功能的网站。

使用以下脚本使用请求我可以访问该网站。

request = requests.get(url,headers={**HEADERS,'Cookie': cookies})
Run Code Online (Sandbox Code Playgroud)

我得到了所需的 HTML。但是当我使用 aiohttp 时

async def get_data(session: aiohttp.ClientSession,url,cookies):
    async with session.get(url,timeout = 5,headers={**HEADERS,'Cookie': cookies}) as response:
        text = await response.text()
        print(text)
Run Code Online (Sandbox Code Playgroud)

我收到机器人预防页面作为响应。

这是我用于所有请求的标头。

HEADERS = {
    'User-Agent': 'PostmanRuntime/7.29.0',
    'Host': 'www.dnb.com',
    'Connection': 'keep-alive',
    'Accept': '/',
    'Accept-Encoding': 'gzip, deflate, br'
} 
Run Code Online (Sandbox Code Playgroud)

我比较了 requests.get 和 aiohttp 的请求标头,它们是相同的。

结果不同有什么原因吗?如果是这样为什么?

编辑:我检查了 httpx 模块,问题也出现在httpx.Client()那里httpx.AsyncClient()

response = httpx.request('GET',url,headers={**HEADERS,'Cookie':cookies})
Run Code Online (Sandbox Code Playgroud)

效果不太好。(不是异步的)

Max*_*ing 1

我尝试使用wireshark捕获数据包来比较请求和aiohttp。

服务器:

    import http
    server = http.server.HTTPServer(("localhost", 8080), 
    http.server.SimpleHTTPRequestHandler)
    server.serve_forever()
Run Code Online (Sandbox Code Playgroud)

有要求:

    import requests
    url = 'http://localhost:8080'
    HEADERS = {'Content-Type': 'application/json'}
    cookies = ''
    request = requests.get(url,headers={**HEADERS,'Cookie': cookies})
Run Code Online (Sandbox Code Playgroud)

请求数据包:

    GET / HTTP/1.1
    Host: localhost:8080
    User-Agent: python-requests/2.27.1
    Accept-Encoding: gzip, deflate, br
    Accept: */*
    Connection: keep-alive
    Content-Type: application/json
    Cookie: 
Run Code Online (Sandbox Code Playgroud)

使用 aiohttp:

    import aiohttp
    import asyncio
    
    url = 'http://localhost:8080'
    HEADERS = {'Content-Type': 'application/json'}
    cookies = ''
    async def get_data(session: aiohttp.ClientSession,url,cookies):
        async with session.get(url,timeout = 5,headers={**HEADERS,'Cookie': cookies}) as response:
            text = await response.text()
            print(text)
    
    async def main():
        async with aiohttp.ClientSession() as session:
            await get_data(session,url,cookies)
    
    asyncio.run(main())
Run Code Online (Sandbox Code Playgroud)

aiohttp数据包:

    GET / HTTP/1.1
    Host: localhost:8080
    Content-Type: application/json
    Cookie: 
    Accept: */*
    Accept-Encoding: gzip, deflate
    User-Agent: Python/3.10 aiohttp/3.8.1
Run Code Online (Sandbox Code Playgroud)

如果该站点似乎接受来自请求的数据包,那么您可以尝试通过设置标头使 aiohttp 数据包相同:

    HEADERS = { 'User-Agent': 'python-requests/2.27.1','Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Type': 'application/json','Cookie': ''}
Run Code Online (Sandbox Code Playgroud)

如果您还没有这样做,我建议您使用wireshark 捕获请求,以确保aiohttp 不会弄乱您的标头。

您还可以尝试其他用户代理字符串,或尝试不同顺序的标头。该顺序并不重要,但有些网站无论如何都会检查它以进行机器人保护(例如在这个问题中)。