V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
Trim21
V2EX  ›  Python

Python 要如何处理直接从直接 bytes 进行百分号编码的 url query?

  •  
  •   Trim21 ·
    Trim21 · 2023-07-14 20:28:08 +08:00 · 1332 次点击
    这是一个创建于 505 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我现在有一些 url 的 query 是直接从 bytes 进行百分号编码之后拼接成的。

    但是 python 的 urllib.parse.parse_qs 的解析是基于 str 的,默认所有的 query 都是百分比编码的字符串,在解析的时候会先解析为 bytes ,然后 bytes.decode(encoding=encoding) 转成字符串。

    所以用 parse_qs 无法解析这些 query string 。

    标准库里同时提供了 unquote_to_bytes,但是并没有对应的 parse_qs_to_bytes 来解析整个 query string ,有什么简单地办法来处理这个 query ?

    如果要自己手动分割 query string 的话感觉相当于要重新实现 parse_qs

    from urllib.parse import parse_qs, quote, unquote_to_bytes, urlparse
    
    
    raw_bytes = bytes.fromhex('123456789abcdef123456789abcdef123456789a')
    
    url = f'https://example.com/?q={quote(raw_bytes)}'
    print(url)
    
    assert unquote_to_bytes(quote(raw_bytes)) == raw_bytes
    
    parsed_q = parse_qs(urlparse(url).query).get("q")[0].encode()
    print(parsed_q.hex())  # 12345678efbfbdefbfbdefbfbdefbfbd234567efbfbdefbfbdefbfbdefbfbd12345678efbfbd
    

    https://gist.github.com/trim21/b60d3999bea03bcac403380d4b157a02

    8 条回复    2023-07-15 01:40:51 +08:00
    NoOneNoBody
        1
    NoOneNoBody  
       2023-07-14 21:57:29 +08:00
    需要自己写个闭包,因为编码是不确定的
    wali77
        2
    wali77  
       2023-07-14 22:04:26 +08:00
    mrzhu
        3
    mrzhu  
       2023-07-14 22:20:09 +08:00
    没想到在这里碰到你 bgm
    Trim21
        4
    Trim21  
    OP
       2023-07-14 22:21:11 +08:00 via Android
    @NoOneNoBody 为什么要闭包…

    研究了一下,解决方法应该是 encoding=raw_unicode_escape 编码解析 querystring ,然后再用这个编码把字符串的 encode/decode 为 bytes ,就是正确的结果了。如果有其他的 UTF8 query 的话再手动用对应编码转换一下。
    mrzhu
        5
    mrzhu  
       2023-07-14 22:21:25 +08:00
    😂
    NoOneNoBody
        6
    NoOneNoBody  
       2023-07-14 22:39:08 +08:00
    @Trim21 #4
    单纯解决问题当然不需要

    写成 fun 就是为了复用,方便调用,各种 iterable 使用 map/apply ,传参 encoding 就够了
    web 的东西,除非是某个网站独有的处理过程,不然复用可能性很高
    lanlanye
        7
    lanlanye  
       2023-07-15 01:18:44 +08:00
    参数是全都用这种形式传递吗?还是说混合了多种不同的编码方式?

    前者的话自己写个工具函数切一下也不是很费劲,后者最好考虑一下换种传参方式?
    Trim21
        8
    Trim21  
    OP
       2023-07-15 01:40:51 +08:00
    @lanlanye #7 只有没编码的 bytes 和 ascii 编码两种情况。

    呃,这么一说我才发现其实就是 `latin-1` 编码?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2640 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 07:18 · PVG 15:18 · LAX 23:18 · JFK 02:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.