Python小酷库系列:furl、yarl,功能强大的url路径操作库


Python小酷库系列:pathlib,全面取代os.path的路径操作小能手 一节里,我们介绍了Python 3.4+ 标准库中内置的pathlib,它在文件路径操作方面的能力让人印象深刻。本节我们再来看看url路径解析与拼接方面的有哪些惊艳的小酷库。

url路径作为一段普通的字符串,常常可以通过正则表达式进行解析,而普通的字符串拼接技术也能胜任url路径的拼接,乍看之下没有必要使用什么特殊的Python库。然而,经常进行url路径操作的小伙伴都知道,相对复杂一些url操作就会面临正斜杠、反斜杠、结尾留不留斜杆的斜杆问题;路径参数查询参数的参数混淆问题;URL 编码/解码、再编码再解码的问题。以上种种问题虽然不是不能解决,但是总让人不能踏实,生怕一段冷僻的url路径搞崩了整个程序,这时找一个好用的小酷库就很有必要了。

非专业的urllib.parse和requests

常用http请求库中也往往自带了url的解析和拼接功能,如标准库中的urllib和大名鼎鼎的requests,它们都有不错的url解析和拼接能力。

urllib.parse

1、urlparse():分解 URL 成组件

from urllib.parse import urlparse

result = urlparse("https://example.com:8080/path?query=1#frag")
print(result.scheme)  # https
print(result.netloc)  # example.com:8080
print(result.path)    # /path

2、urlunparse():把解析后的组件组装回 URL

from urllib.parse import urlunparse

components = ('https', 'example.com', '/path', '', 'query=1', 'frag')
print(urlunparse(components))  # https://example.com/path?query=1#frag

3、urljoin():合并 base URL 与相对路径

from urllib.parse import urljoin

base = "https://example.com/api/"
print(urljoin(base, "v1/data"))  # https://example.com/api/v1/data

4、urlencode():构造查询字符串

from urllib.parse import urlencode

params = {'q': 'python urllib', 'page': 1}
query_str = urlencode(params)
print(query_str)  # q=python+urllib&page=1

requests

1、使用 params 自动构造带查询字符串的 URL

import requests

params = {'q': 'python requests', 'page': 2}
response = requests.get('https://www.google.com/search', params=params)

print(response.url)
# 输出: https://www.google.com/search?q=python+requests&page=2

2、自动编码参数(中文、特殊字符)

params = {'query': '你好 世界'}
r = requests.get('https://httpbin.org/get', params=params)
print(r.url)
# 输出: https://httpbin.org/get?query=%E4%BD%A0%E5%A5%BD+%E4%B8%96%E7%95%8C

3、使用 urllib.parse 搭配 requests 做高级 URL 操作

from urllib.parse import urlparse, urlunparse, urljoin
import requests

# 解析原始 URL
url = "https://example.com/api/data?query=test"
parsed = urlparse(url)
print(parsed.scheme)   # https
print(parsed.netloc)   # example.com

# 添加路径或构造完整 URL
base = "https://example.com/api/"
endpoint = "v1/items"
full_url = urljoin(base, endpoint)
print(full_url)  # https://example.com/api/v1/items

# 请求 + 打印最终访问的 URL
res = requests.get(full_url, params={"search": "book"})
print(res.url)

furl

相比于urllib.parse,furl 是一个非常 直观、强大、专注于 URL 构造与解析的第三方 Python 库,它支持链式调用、自动编码、路径/参数/锚点操作,非常适合构造 API URL、爬虫跳转等用途。

基本使用

1、构造和解析 URL

from furl import furl

f = furl("https://example.com/api?search=test#section")
print(f.scheme)     # https
print(f.host)       # example.com
print(f.path)       # /api
print(f.args)       # {'search': 'test'}
print(f.fragment)   # section

2、添加或修改路径段(Path)

f = furl("https://example.com")
f.path.add("v1")
f.path.add("users")
print(f.url)  # https://example.com/v1/users

你也可以使用 .path.segments 直接访问列表:

f.path.segments  # ['v1', 'users']

3、添加或修改查询参数(Query Args)

f = furl("https://example.com/api")
f.args["page"] = 2
f.args["q"] = "python"
print(f.url)  # https://example.com/api?page=2&q=python

支持重复参数值(一个键多个值):

f.args.add("tag", "python")
f.args.add("tag", "ai")
print(f.url)  # https://example.com/api?page=2&q=python&tag=python&tag=ai

4、删除参数或路径

f.args.remove("page")
f.path.segments.pop()  # 删除最后一个路径段

5、添加锚点(fragment)

f.fragment = "section1"
print(f.url)  # https://example.com/api?q=python#section1

6、合并 base URL 和子路径(链式构造)

base = furl("https://example.com/api")
child = base.copy().path.add("v1").add("item")
child.args["id"] = 42
print(child.url)  # https://example.com/api/v1/item?id=42

综合示例

构造分页 API 链接列表

from furl import furl

for page in range(1, 4):
    f = furl("https://api.example.com/data")
    f.args["page"] = page
    f.args["limit"] = 20
    print(f.url)

常用属性/方法速查表

功能示例
创建 URLf = furl(“https://…”)
访问部分f.scheme, f.path, f.args, f.fragment
添加路径段f.path.add(“v1”)
修改参数f.args[“q”] = “value”
删除参数f.args.remove(“q”)
设置锚点f.fragment = “top”
输出完整 URLf.url
拷贝new_f = f.copy()

yarl

yarl 是一个功能强大且高性能的 Python 库,用于处理 URL 构造、解析和修改,它特别适合异步项目(比如配合 aiohttp),但也可以在任何 Python 项目中使用。相比标准库的 urllib.parse,yarl 提供了更加直观、链式、安全的 API。

基本使用

1、基本解析功能

from yarl import URL

url = URL("https://user:pass@example.com:8080/api/v1/items?id=10#top")

print(url.scheme)    # https
print(url.user)      # user
print(url.password)  # pass
print(url.host)      # example.com
print(url.port)      # 8080
print(url.path)      # /api/v1/items
print(url.query)     # <MultiDictProxy('id': '10')>
print(url.fragment)  # top

2、构造/拼接 URL(推荐用 .with_*()

url = URL("https://example.com")

# 添加路径
url = url / "api" / "v1"
print(url)  # https://example.com/api/v1

# 添加查询参数
url = url.update_query(page=2, search="python")
print(url)  # https://example.com/api/v1?page=2&search=python

# 添加锚点
url = url.with_fragment("section1")
print(url)  # https://example.com/api/v1?page=2&search=python#section1

3、操作查询参数(.query 是一个 MultiDictProxy)

url = URL("https://example.com/?a=1&b=2")

print(url.query["a"])         # 1
print(list(url.query.items()))  # [('a', '1'), ('b', '2')]

# 修改参数(返回新 URL)
url2 = url.update_query(a="100", c="new")
print(url2)  # https://example.com/?a=100&b=2&c=new

# 删除参数
url3 = url2.with_query({})
print(url3)  # https://example.com/

4、处理多值参数(重复 key)

url = URL("https://example.com/?tag=python&tag=ai")
print(url.query.getall("tag"))  # ['python', 'ai']

5、路径分段和操作

url = URL("https://example.com/api/v1")
print(url.parts)  # ('/', 'api', 'v1')

# 添加路径(返回新 URL)
url2 = url / "items"
print(url2)  # https://example.com/api/v1/items

6、序列化为字符串

url = URL("https://example.com/api")
print(str(url))  # https://example.com/api

7、与 aiohttp 搭配

import aiohttp
from yarl import URL

url = URL("https://httpbin.org/get").update_query(key="value")

async with aiohttp.ClientSession() as session:
    async with session.get(url) as resp:
        print(await resp.text())

完整示例

构造分页 API URL 列表

from yarl import URL

base_url = URL("https://api.example.com/v1/items")

for page in range(1, 4):
    url = base_url.update_query(page=page, limit=20)
    print(url)

常用属性/方法速查表

yarl.URL常用属性

属性名说明示例值
.scheme协议部分‘https’
.host主机(无端口)‘example.com’
.port端口8080
.user用户名(如果 URL 中有)‘admin’
.password密码(如果 URL 中有)‘123’
.path路径字符串‘/api/v1/items’
.parts路径分段元组(‘/’, ‘api’, ‘v1’, ‘items’)
.query查询参数字典(MultiDictProxy){‘page’: ‘1’, ‘limit’: ‘20’}
.fragmentURL 锚点‘top’
.raw_host原始 Host,不带解析‘example.com’
.raw_path编码后的原始路径‘/api/v1/items’
.raw_query_string编码后的原始查询字符串‘page=1&limit=20’

构造与拼接方法

方法名 / 操作符功能说明示例
URL(url_str)创建 URL 对象URL(“https://example.com”)
url / “path”拼接路径段(不可变)URL(…) / “api” / “v1”
.with_path(path)设置完整路径(覆盖)url.with_path(“/new/path”)
.with_query(dict)替换所有查询参数url.with_query({‘q’: ‘python’})
.update_query(dict)添加或修改查询参数url.update_query(page=2)
.with_fragment(str)设置锚点url.with_fragment(“top”)
.with_host(host)替换主机名url.with_host(“api.example.com”)
.with_scheme(scheme)替换协议url.with_scheme(“http”)

查询参数操作(.query 是不可变的)

方法名功能说明示例
.query[“key”]获取单个参数值url.query[“page”] → ‘1’
.query.getall()获取重复参数的所有值url.query.getall(“tag”) → [‘a’, ‘b’]
.update_query()添加或更新参数url.update_query(page=2)
.with_query({})删除全部参数url.with_query({}) → 无参数

其他有用操作

操作示例说明
str(url)‘https://example.com/path’转换为字符串形式的 URL
url.name‘items’获取路径中的最后一段
url.parent‘https://example.com/api/v1’返回上一级路径的 URL
.is_absolute()判断是否是绝对路径 URL返回 True/False
.origin()返回 origin(scheme + host + port)https://example.com:8080
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值