【问题标题】:Does aiohttp process/encode form data differently than requests does?aiohttp 处理/编码表单数据是否与请求不同?
【发布时间】:2021-01-16 00:39:48
【问题描述】:

概述

我编写了一个脚本,该脚本可以进入页面,抓取表单输入,然后发回同一页面(就像用户会做的那样;需要这样做才能获取隐藏的输入/令牌/等。) .

我的脚本目前使用requests.Session,我正在尝试迁移到异步并改用aiohttp.ClientSession

这个登录功能的requests版本有效,但是aiohttp版本发送却返回一个无效的登录响应。

aiohttp 对我传递给s.post(...) 的数据字典有什么特殊作用吗?我看到 aiohttp 是 slightly opinionated when it comes to cookies 而 requests 不是。这是否也扩展到表单数据编码?

相关代码片段

请求版本

import requests
from bs4 import BeautifulSoup

URL = '...'

def login(s: requests.Session, username: str, password: str) -> requests.Response:
    response = s.get(URL)
    soup = BeautifulSoup(response.text, 'html.parser')
    inputs = soup.select('form input')
    data = {
        el['name']: el['value']
        for el in inputs
        if el.get('name') and el.get('value')
    }
    data.update({
        'Username': username,
        'Password': password
    })
    return s.post(URL, data=data)

if __name__ == '__main__':
    with requests.session() as s:
        response = login(s, <username>, <password>)

aiohttp 版本

import asyncio

import aiohttp
from bs4 import BeautifulSoup

URL = '...'

async def login(s: aiohttp.ClientSession, username: str, password: str) -> aiohttp.ClientResponse:
    async with s.get(URL) as response:
        soup = BeautifulSoup(await response.text(), 'html.parser')

    inputs = soup.select('form input')
    data = {
        el['name']: el['value']
        for el in inputs
        if el.get('name') and el.get('value')
    }
    data.update({
        'Username': username,
        'Password': password,
    })

    return await s.post(URL, data=data)

async def main():
    jar = aiohttp.CookieJar(quote_cookie=False)
    async with aiohttp.ClientSession(cookie_jar=jar) as s:
        response = await login(s, <username>, <password>)

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

我尝试过的事情

data 变量在两种情况下都被发送之前我已经打印出来并且它们是相同的(除了页面生成的随机标记等),我尝试更改内容类型标题,我已经启动了一个快速的 Flask 服务器,我已经向它发送了这两个请求,request.data 看起来相同。

版本

在 Ubuntu 20 上运行

Python:3.8.5

点冻结输出

aiodns==2.0.0
aiohttp==3.7.3
async-timeout==3.0.1
attrs==20.3.0
beautifulsoup4==4.9.3
brotlipy==0.7.0
cchardet==2.1.7
certifi==2020.12.5
cffi==1.14.4
chardet==3.0.4
click==7.1.2
Flask==1.1.2
idna==2.10
itsdangerous==1.1.0
Jinja2==2.11.2
MarkupSafe==1.1.1
multidict==5.1.0
numpy==1.19.5
pandas==1.2.0
pycares==3.1.1
pycparser==2.20
python-dateutil==2.8.1
python-dotenv==0.15.0
pytz==2020.5
requests==2.25.1
six==1.15.0
soupsieve==2.1
typing-extensions==3.7.4.3
ua-parser==0.10.0
urllib3==1.26.2
Werkzeug==1.0.1
yarl==1.6.3

主要问题

aiohttp 处理/编码表单数据是否与请求不同?如果不是,aiohttp 请求失败的原因是什么?

【问题讨论】:

    标签: python beautifulsoup python-requests python-asyncio aiohttp


    【解决方案1】:

    尝试设置 allow_redirects=False 并手动设置。

    async def login(s: aiohttp.ClientSession, username: str, password: str) -> aiohttp.ClientResponse:
        async with s.get(URL) as response:
            soup = BeautifulSoup(await response.text(), 'html.parser')
    
        inputs = soup.select('form input')
        data = {
            el['name']: el['value']
            for el in inputs
            if el.get('name') and el.get('value')
        }
        data.update({
            'Username': username,
            'Password': password,
        })
    
        resp = await s.post(URL, data=data, allow_redirects=False)
        return await s.get(resp.headers.get('Location'))
    

    【讨论】:

      猜你喜欢
      • 2018-12-07
      • 2019-10-07
      • 1970-01-01
      • 1970-01-01
      • 2022-07-08
      • 2015-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多