解析URL路径时python和ruby之间的不同,哪个有效?

Posted

技术标签:

【中文标题】解析URL路径时python和ruby之间的不同,哪个有效?【英文标题】:different between python and ruby when parsing URL path, which is valid? 【发布时间】:2021-09-21 07:11:16 【问题描述】:

我有一个 URL 字符串:

url = "https://foo.bar.com/path/to/aaa.bbb/ccc.ddd;dc_trk_aid=486652617;tfua=;gdpr=;gdpr_consent=?&339286293"

使用 Python 时

from urllib.parse import urlparse

url_obj = urlparse(url)
url_obj.path  # `path/to/aaa.bbb/ccc.ddd`

使用红宝石时

url_obj = URI.parse(url)

url_obj.path # `path/to/aaa.bbb/ccc.ddd;dc_trk_aid=486652617;tfua=;gdpr=;gdpr_consent=`

我猜python认为;不是url路径的一部分,哪一个是“正确的”?

【问题讨论】:

根据 rfc 它应该被允许......也许是 urlparse 的一个错误(但它似乎在url_obj.params 中可用 @JoranBeasley AFAIK ; 被推荐(至少在过去的某个时间点)作为& 的替代品作为查询参数分隔符。这只会在 ? 之后应用,但也许这就是 Python 正在做的事情。 @muistooshort 明白了,我给出的这个示例url是从浏览器中捕获的,我必须解析和使用它,所以我别无选择,只能处理它。 【参考方案1】:

urlparse在第一个分号后的path部分为params

url_obj.path   # '/path/to/aaa.bbb/ccc.ddd'
url_obj.params # 'dc_trk_aid=486652617;tfua=;gdpr=;gdpr_consent='

要复制 Ruby 的行为,请改用 urlsplit

这类似于urlparse(),但不会从 URL 中拆分参数。如果需要更新的 URL 语法,允许将参数应用于 URL 的 path 部分的每个段(请参阅 RFC 2396),则通常应使用该语法而不是 urlparse()

from urllib.parse import urlsplit

url_obj = urlsplit(url)
url_obj.path  # '/path/to/aaa.bbb/ccc.ddd;dc_trk_aid=486652617;tfua=;gdpr=;gdpr_consent='

【讨论】:

感谢 Amadan,我的问题是我正在将 python 脚本翻译成 ruby​​ 等价物,所以我想我们发现了原始 python 脚本的“错误”并在 ruby​​ 版本中执行正确的行为.至少这有助于解决这个问题。【参考方案2】:

Python 的urllib 是错误的。 RFC 3986 Uniform Resource Identifier (URI): Generic Syntax, Section 3.3 Path 明确给出了这个确切的语法作为有效路径的示例[bold强调我的]:

除了层次路径中的点段之外,路径段被通用语法认为是不透明的。生成 URI 的应用程序通常使用段中允许的保留字符来分隔特定于方案或特定于解引用处理程序的子组件。例如,分号 (";") 和等号 ("=") 保留字符通常用于分隔适用于该段的参数和参数值。逗号 (",") 保留字符通常用于类似目的。例如,一个 URI 生产者可能使用诸如“name;v=1.1”之类的片段来指示对“name”的 1.1 版的引用,而另一个可能使用诸如“name,1.1”之类的片段"表示相同。参数类型可以由特定于方案的语义定义,但在大多数情况下,参数的语法特定于 URI 的解引用算法的实现。

您发布的示例 URI 的正确解释如下:

方案 = https 权限 = foo.bar.com 用户信息 = 空 主机 = foo.bar.com port = 空,从 scheme 派生为 443 路径 = /path/to/aaa.bbb/ccc.ddd;dc_trk_aid=486652617;tfua=;gdpr=;gdpr_consent=,由以下四个路径段组成:
    path to aaa.bbb ccc.ddd;dc_trk_aid=486652617;tfua=;gdpr=;gdpr_consent=
查询 = &339286293 片段 = 空

【讨论】:

没有错。 urlparse 通过将最后一个路径段的参数(根据引用的 RFC)拆分到其自己的字段中来“提供帮助”。 urllib 中有一个函数不这样做,所以我宁愿说 urlparse 是奇怪的,而不是 urllib 作为一个包是错误的。 感谢您提供的详细信息,至少现在我只是按照 ruby​​ 的解析结果表格并忽略 py 版本

以上是关于解析URL路径时python和ruby之间的不同,哪个有效?的主要内容,如果未能解决你的问题,请参考以下文章

Python 的 urllib.parse 库解析 URL

python 解析url并按路径对它们进行分组

Ruby on Rails 路由解析

使用 Nokogiri xpath 解析时未插入 Ruby 环境变量

python之路_day107_django中url反向解析及数据库连接

Python_xml模块_用ElementTree解析xml