Python:连接多个组件以构建URL

Python:连接多个组件以构建URL,python,url-parsing,Python,Url Parsing,我试图通过加入一些动态组件来构建URL。我曾想过使用类似于os.path.join()的东西,但在我的例子中,它是用于URL的。通过研究,我发现urlparse.urljoin()也做了同样的事情。然而,它看起来一次只接受两个参数 到目前为止,我有以下几点可行,但看起来有些重复: a = urlparse.urljoin(environment, schedule_uri) b = urlparse.urljoin(a, str(events_to_hours)) c =

我试图通过加入一些动态组件来构建URL。我曾想过使用类似于
os.path.join()的东西,但在我的例子中,它是用于URL的。通过研究,我发现
urlparse.urljoin()
也做了同样的事情。然而,它看起来一次只接受两个参数

到目前为止,我有以下几点可行,但看起来有些重复:

    a = urlparse.urljoin(environment, schedule_uri)
    b = urlparse.urljoin(a, str(events_to_hours))
    c = urlparse.urljoin(b, str(events_from_date))
    d = urlparse.urljoin(c, str(api_version))
    e = urlparse.urljoin(d, str(id))
    url = e + '.json'
输出=
http://example.com/schedule/12/20160322/v1/1.json

上述方法有效,我试图通过这种方式将其缩短:

url_join_items = [environment, schedule_uri, str(events_to_hours),
                  str(events_from_date), str(api_version), str(id), ".json"]
new_url = ""
for url_items in url_join_items:
    new_url = urlparse.urljoin(new_url, url_items)
输出:
http://example.com/schedule/.json

但第二种实现方式并不奏效。请建议我如何解决这个问题或更好的方法

编辑1:
reduce
解决方案的输出如下(很遗憾):
输出:
http://example.com/schedule/.json

使用join如何
url=reduce(urlparse.urljoin,url\u join\u项目)

您是否尝试过简单的
“/”.join(url\u join\u items)
。http不总是使用正斜杠吗?不过,您可能需要手动设置前缀“https://”和后缀

比如:

url = "https://{}.json".format("/".join(url_join_items))
使用reduce和urljoin

下面是一个例子,从某种程度上解释了
urljoin
实现背后的思想。您的用例似乎不是最合适的

当使用
reduce
urljoin
时,我不确定它是否会达到问题的目的,这在语义上类似于
os.path.join
,但对于URL。考虑以下事项:

from urllib.parse import urljoin
from functools import reduce

parts_1 = ["a","b","c","d"]
parts_2 = ["https://","server.com","somedir","somefile.json"]
parts_3 = ["https://","server.com/","somedir/","somefile.json"]

out1 = reduce(urljoin, parts_1)
print(out1)
d

https:///somefile.json

https:///server.com/somedir/somefile.json


请注意,除了https前缀后面的额外“/”之外,第三个输出可能最接近询问者的意图,除了我们必须使用分隔符完成所有格式化部分的工作。

我还需要类似的东西,并提出了以下解决方案:

from urllib.parse import urljoin, quote_plus

def multi_urljoin(*parts):
    return urljoin(parts[0], "/".join(quote_plus(part.strip("/"), safe="/") for part in parts[1:]))

print(multi_urljoin("https://server.com", "path/to/some/dir/", "2019", "4", "17", "some_random_string", "image.jpg"))

这将打印
'https://server.com/path/to/some/dir/2019/4/17/some_random_string/image.jpg“

这里有一个有点愚蠢但可行的解决方案,因为
部分是按顺序排列的URL部分列表

my_url = '/'.join(parts).replace('//', '/').replace(':/', '://')
我希望
replace
会有一个
from
选项,但它没有,因此第二个选项是恢复
https://
双斜杠


很好的一点是,您不必担心部件已经有(或没有)任何斜杠了

@idjaw:在我的情况下,我已经确定我想使用
urlparse
,我只需要一种更干净、更短的方式将两个以上的组件连接到同一个urlparse,为什么它不起作用?对我来说,它看起来很好。输出是什么?有什么问题?您可能希望坚持使用
.json
的字符串连接,这样您的URL就不会以
/.json
结尾。另外,我不知道它将如何处理空字符串,因此您可能希望从
new\u url=url\u join\u items[0]
开始,然后迭代
url\u join\u items[1://code>。但是使用reduce的答案可能更好。@AlexHall:请查看我的编辑1和每个方法的输出OK,再次,将
.json
保留在
url\u join\u项目中。否则,我不明白为什么有这么多的零件丢失了。如果你
打印url\u join\u items
,会发生什么情况?@AlexHall:我明白了:
['http://example.com“,”schedule/“,”12“,”20160322“,”v1“,”100“,”.json“]
这是Python 3的
functools.reduce
。这产生了与我上面所做的列表迭代相同的结果:(您是否尝试删除“.json”形成列表并将其直接附加到url,同时保留reduce?是的,列表现在包含
[环境、计划uri、str(事件到小时)、str(事件从日期开始)、str(api版本)、str(id)]
,结果是
[“http://example.com“,”附表/“,”8“,”20160322“,”1“,”12“]
reduce
的结果是
http://example.com/schedule/12
downvoting,因为reduce的行为也不像文档所宣传的那样,它只是用第一个元素和最后一个元素调用urljoin,出于某种原因省略了所有中间元素。你认为这是一种比我已经使用的更干净的方法吗e工作?是的。我想是的,但那是主观的。
from urllib.parse import urljoin, quote_plus

def multi_urljoin(*parts):
    return urljoin(parts[0], "/".join(quote_plus(part.strip("/"), safe="/") for part in parts[1:]))

print(multi_urljoin("https://server.com", "path/to/some/dir/", "2019", "4", "17", "some_random_string", "image.jpg"))
my_url = '/'.join(parts).replace('//', '/').replace(':/', '://')