# CY3761 | 2021-12-23 11:50
import os.path
import types
from urllib import parse
upDict = parse.__dict__
upDictKeys = upDict.keys()
"""
print('-' * 80)
print('parse.__dict__(keys)')
[print(str(k).zfill(2), _) for k, _ in enumerate(upDictKeys) if not _.startswith('_')]
"""
"""
print('-' * 80)
[print(str(k).zfill(2), _) for k, _ in enumerate(upDict.items()) if not _[0].startswith('_')] # 过滤私有
"""
"""
print('-' * 80)
[print(str(k).zfill(2), _) for k, _ in enumerate(upDict.items())
if not _[0].startswith('_') and isinstance(_[1], types.FunctionType)] # 过滤私有, 可调用的
"""
filePath = 'parse-func.txt'
if not os.path.exists(filePath):
with open(filePath, 'w', encoding='utf-8') as w:
[w.write(_[0] + '\n') for k, _ in enumerate(upDict.items())
if not _[0].startswith('_') and isinstance(_[1], types.FunctionType)] # 过滤私有, 可调用的
# https://docs.python.org/zh-cn/3.9/library/urllib.parse.html#urllib.parse.urlunparse
# 01 parse.urlparse 与 parse.urlsplit
u = 'https://www.baidu.com:80/s?wd=python&username=abc#1'
"""
scheme(请求协议) : 一般 http/https
netloc(请求域名)
path(请求路径[路由])
query(请求GET参数)
fragment(描点): URL #后的字符串
params: 提交数据, 感觉值传入一个URL视为空 (urlparse具有该属性)
port(端口号): 没提供返回None
"""
# scheme='https', netloc='www.baidu.com:80', path='/s', params='', query='wd=python&username=abc', fragment='1', port=80
print('-' * 80)
pup = parse.urlparse(u)
pus = parse.urlsplit(u)
print('parse.urlparse', pup, pup.port) # ParseResult(scheme, netloc, path, params, query, fragment) 80
print('parse.urlsplit', pus, pus.port) # SplitResult(scheme, netloc, path, query, fragment)
# 02 parse.urlunparse 与 parse.urlunsplit
"""
urllib.parse.urlunparse(parts)
根据 urlparse() 所返回的元组来构造一个 URL. parts 参数可以是任何包含六个条目的可迭代对象.
构造的结果可能是略有不同但保持等价的 URL, 如果被解析的 URL 原本包含不必要的分隔符(例如,带有空查询的 ?;RFC 已声明这是等价的)
"""
print('-' * 80)
print('parse.urlunparse', parse.urlunparse(pup)) # https://www.baidu.com:80/s?wd=python&username=abc#1
print('parse.urlunsplit', parse.urlunsplit(pus)) # https://www.baidu.com:80/s?wd=python&username=abc#1
# 03 parse.parse_qs 与 parse.parse_qsl
q = 'name=Tom&name=Jack&age=13&school=&home&cn=中文&msg=hello world'
print('-' * 80)
pqd = parse.parse_qs(q)
pql = parse.parse_qsl(q)
print(pqd) # 返回JSON {'k1':['v1','v2'],...} 字符串具有多个相同的参数则返回多个参数值(在列表中..) v为字符串
print(pql) # 返回列表 [('k1', 'v1'), ('k2', 'v2'), ...] v为字符串
"""
URL 转码
"""
print('-' * 80)
pqu = parse.quote(q)
pqup = parse.quote_plus(q)
print(pqu) # 转码为 %xx 形式的字符串 (完全转换, 包括=&)
print(pqup) # 转码为 %xx 形式的字符串, 空格使用 + 代替 (完全转换, 包括=&)
# unquote
print('-' * 80)
print(parse.unquote(pqu)) # 将转码后的字符串进行解码
print(parse.unquote_plus(pqup)) # 专门处理 parse.quote_plus 结果的解码
print(parse.urlencode({k: v[0] for (k, v) in pqd.items()})) # 参数传入字典, 对中文等进行转码 (正常转换, 不处理=&)
# 官方文档源码: https://github.com/python/cpython/tree/3.9/Doc
print('-' * 80)
u = ('https://image.baidu.com/search/acjson?tn=resultjson_com&logid=10363389854672847255&ipn=rj&ct=201326592&is='
'&fp=result&queryWord=%E7%BE%8E%E5%A5%B3&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&hd=&latest='
'©right=&word=%E7%BE%8E%E5%A5%B3&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&expermode='
'&nojc=&cg=girl&pn=30&rn=30&gsm=1e&1635132340880=')
pup = parse.urlparse(u)
pupQuery = pup.query
[print(k, v[0]) for (k, v) in parse.parse_qs(pupQuery).items()]
"""
返回 GET参数数据
{'tn': 'resultjson_com', 'logid': '10363389854672847255', 'ipn': 'rj', 'ct': '201326592', 'fp': 'result',
'queryWord': '美女', 'cl': '2', 'lm': '-1', 'ie': 'utf-8', 'oe': 'utf-8', 'st': '-1', 'ic': '0', 'word': '美女',
'face': '0', 'istype': '2', 'nc': '1', 'cg': 'girl', 'pn': '30', 'rn': '30', 'gsm': '1e'}
"""