【问题标题】:AIOHTTP replacing %3A with :AIOHTTP 将 %3A 替换为:
【发布时间】:2021-06-13 08:22:12
【问题描述】:

解决此问题:

import yarl
async with cs.get(yarl.URL(f"https://ipqualityscore.com/api/json/url/{self.token}/{url}",encoded=True)) as r:

您好,我遇到了这个问题,AIOHTTP 将%3A 等字符转换为原始:。我需要在 API req 中使用 %3A 版本,如果没有,它会引发 404

我的代码:

for link in results:
    url = urllib.parse.quote(link, safe = '')
    await ctx.send(url)
    ## ^^ 1st ^^

    async with aiohttp.ClientSession() as cs:

        await ctx.send(f"https://ipqualityscore.com/api/json/url/{self.token}/{url}")
        ## ^^ 2nd ^^

        async with cs.get(f"https://ipqualityscore.com/api/json/url/{self.token}/{url}") as r:
            text = await r.json()
            await ctx.send(text)

它应该使用的 URL:

https://ipqualityscore.com/api/json/url/PRIVATE_TOKEN/https%3A%2F%2Fstreancommunuty.ru%2Ftradoffer%2Fnew%2F%3Fpartner%3D1284276379%26token%3DiMDdLkoe

出现错误(并使用了 url):

aiohttp.client_exceptions.ContentTypeError: 0, message='Attempt to decode JSON with unexpected mimetype: text/html; charset=utf-8', url=URL('https://ipqualityscore.com/api/json/url/PRIVATE_TOKEN/https:%2F%2Fstreancommunuty.ru%2Ftradoffer%2Fnew%2F%3Fpartner=1284276379&token=iMDdLkoe')

错误更多解释/突出显示为图像

【问题讨论】:

  • aalways 将代码、数据和完整的错误消息作为文本(不是屏幕截图,不是链接)放在有问题的地方(不是评论)。
  • 首先你可以检查你从urllib.parse.quote()得到的print( url )。如果您使用: 获得它,那么您可以手动将其替换为%3A - url = url.replace(':', "%3A")
  • 最终你可能会尝试引用"%3A"或手动转换为%253A
  • 第三次使用URL时cs是什么?似乎错误来自其get 方法,由于某种原因,该方法部分取消引用了您提供的引用 URL。
  • @Blckknght cs 来自async with aiohttp.ClientSession() as cs:

标签: python aiohttp


【解决方案1】:

首先,你确定这是你想做的吗?我问是因为虽然: 是 URL 中的保留字符,但它不用作 URL 的 path 组件中的分隔符,因此无论它是否是百分比编码的,它都应该意味着与 Web 服务器完全相同。您确定 : 是否是百分比编码是导致您问题的唯一原因吗?也就是说,这个特定的 Web 服务器可能没有正确遵循 RFC,在这种情况下,您可能需要解决它。

如果它你想做的,我想你需要prevent aiohttp from normalizing the URL。从这个问题的答案来看,听起来你可以这样做:

import yarl

...

ipqs_url = yarl.URL(
    f"https://ipqualityscore.com/api/json/url/{self.token}/{url}",
    encoded=True)
await ctx.send(ipqs_url)

同样,您可以将 yarl.URL 对象传递给 cs.get。

【讨论】:

  • 问题是url 必须在cs.get(...) 中使用,而不是ctx.send(...) - 和cs.get(...) 使所有问题。
  • 是的,我 100% 确定。这个 API 检查 URL,所以我需要传递这样编码的 URL,如果没有,它会引发 404 另外,谢谢!成功了:async with cs.get(yarl.URL(f"https://ipqualityscore.com/api/json/url/{self.token}/{url}",encoded=True)) as r:
  • @furas 会话应该同样能够获取 Yarl URL 对象。
  • 现在我明白了:我在没有 encoded=True 的情况下对其进行了测试,但它不起作用。
【解决方案2】:

编辑:

基于@Weeble 答案的最小工作代码。

它使用yarlencoded=True 来停止将%3A 重新引用到:

import urllib.parse
import aiohttp
import asyncio
import yarl

import os
token = os.getenv('IPQUALITYSCORE_TOKEN')

link = 'https://streancommunuty.ru/tradoffer/new/?partner=1284276379&token=iMDdLkoe'

async def main(link):
    url = urllib.parse.quote(link, safe='')
    print('--- url ---')
    print(url)
    
    async with aiohttp.ClientSession() as cs:
        
        yarl_url = yarl.URL(f"https://ipqualityscore.com/api/json/url/{token}/{url}", encoded=True)
                            
        async with cs.get(yarl_url) as r:
            #print('--- text ---')
            #text = await r.text() 
            #print(text)
            print('--- data ---')
            data = await r.json()
            print(data)
            print('--- url ---')
            print(r.url)
            
loop = asyncio.get_event_loop()
loop.run_until_complete(main(link))

编辑:

我发现Request url of client session gets malformed #3424 表明它使用了模块 yarl`,该模块会自动请求一些字符。它正在帮助创建正确的 URL,但在您的情况下,它只会造成问题。它可能需要更改源代码才能停止。

以下是不能解决所有问题的旧版本。


旧:(它不能解决主要问题)

如果我引用 link 两次,代码不会引发错误

url = urllib.parse.quote(link, safe='')  # first time
url = urllib.parse.quote(url)            # second time

但我没有TOKEN,所以我从服务器收到消息Invalid or unauthorized key,我无法检查这是否解决了所有问题。


用于测试的最少工作代码。

import urllib.parse
import aiohttp
import asyncio

token = 'PRIVATE_TOKEN'
link = 'https://streancommunuty.ru/tradoffer/new/?partner=1284276379&token=iMDdLkoe'

async def main(link):
    url = urllib.parse.quote(link, safe='')
    url = urllib.parse.quote(url)
    print('--- url ---')
    print(url)
    
    async with aiohttp.ClientSession() as cs:
    
        async with cs.get(f"https://ipqualityscore.com/api/json/url/{token}/{url}") as r:
            #print('--- text ---')
            #text = await r.text()
            #print(text)
            data = await r.json()
            print('--- data ---')
            print(data)
            
loop = asyncio.get_event_loop()
loop.run_until_complete(main(link))

结果:

--- url ---
https%253A%252F%252Fstreancommunuty.ru%252Ftradoffer%252Fnew%252F%253Fpartner%253D1284276379%2526token%253DiMDdLkoe
--- data ---
{'success': False, 'message': 'Invalid or unauthorized key. Please check the API key and try again.', 'request_id': '4DqddqGpINmFBAI'}

【讨论】:

  • 我不认为双重转义是正确的做法。它会使任何: 字符消失,但 将双重转义其他所有内容。所有%XY 转义都将变成%25XY,因为第一次转义中的% 在第二次转义时会自行转义。
  • @Blckknght 是的,它可能不起作用,但我没有 TOKEN 来测试它。此时我在此门户上创建帐户以查看它是否将其作为正确的数据。也许它需要挖掘aiohttp的源代码来解决这个问题。
  • 抱歉,这个双重功能不起作用 :( 它引发了 HTTP 错误 503
  • @LeoCx1000 是的,我创建了帐户来测试它,它似乎需要直接在源代码中更改某些内容才能跳过它。基于Request url of client session gets malformed #3424 它使用模块yarl 自动将%3A 转换为: 以创建正确的URL,但在您的情况下它只会产生问题。他们不想更改它 - 您必须更正源代码并发送给作者,然后他们可以在下一个版本中更改它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-12-12
  • 1970-01-01
  • 2018-06-04
  • 2015-01-14
  • 2020-12-30
  • 2011-04-29
  • 2014-03-06
相关资源
最近更新 更多