1. ホーム
  2. python

s3 urls - バケット名とパスの取得

2023-08-27 02:48:18

質問

私はaws s3のURLを持つ変数を持っています。

s3://bucket_name/folder1/folder2/file1.json

バケツ名を変数に、残りの部分(/folder1/folder2/file1.json)を別の変数に取得したいのですが、どうすればよいでしょうか?正規表現を試したところ、以下のようにバケツ名を取得することができましたが、より良い方法があるかどうかはわかりません。

m = re.search('(?<=s3:\/\/)[^\/]+', 's3://bucket_name/folder1/folder2/file1.json')
print(m.group(0))

残りの部分、つまりfolder1/folder2/file1.jsonはどのように取得するのでしょうか?

boto3の機能で、バケット名とキーをURLから抽出するものがないか調べてみましたが、見つかりませんでした。

どのように解決すればよいのでしょうか?

普通のURLなので urlparse を使って、URLのすべての部分を取得することができます。

>>> from urlparse import urlparse
>>> o = urlparse('s3://bucket_name/folder1/folder2/file1.json', allow_fragments=False)
>>> o
ParseResult(scheme='s3', netloc='bucket_name', path='/folder1/folder2/file1.json', params='', query='', fragment='')
>>> o.netloc
'bucket_name'
>>> o.path
'/folder1/folder2/file1.json'

次の回答が示すように、キーから冒頭のスラッシュを削除する必要があるかもしれません。

o.path.lstrip('/')

Python 3を使用する場合 urlparse に移動しました。 urllib.parse に変更されたので、使用します。

from urllib.parse import urlparse


ここに、すべての詳細を引き受けるクラスがあります。

try:
    from urlparse import urlparse
except ImportError:
    from urllib.parse import urlparse


class S3Url(object):
    """
    >>> s = S3Url("s3://bucket/hello/world")
    >>> s.bucket
    'bucket'
    >>> s.key
    'hello/world'
    >>> s.url
    's3://bucket/hello/world'

    >>> s = S3Url("s3://bucket/hello/world?qwe1=3#ddd")
    >>> s.bucket
    'bucket'
    >>> s.key
    'hello/world?qwe1=3#ddd'
    >>> s.url
    's3://bucket/hello/world?qwe1=3#ddd'

    >>> s = S3Url("s3://bucket/hello/world#foo?bar=2")
    >>> s.key
    'hello/world#foo?bar=2'
    >>> s.url
    's3://bucket/hello/world#foo?bar=2'
    """

    def __init__(self, url):
        self._parsed = urlparse(url, allow_fragments=False)

    @property
    def bucket(self):
        return self._parsed.netloc

    @property
    def key(self):
        if self._parsed.query:
            return self._parsed.path.lstrip('/') + '?' + self._parsed.query
        else:
            return self._parsed.path.lstrip('/')

    @property
    def url(self):
        return self._parsed.geturl()