2012-06-21 2 views
2

Я пытаюсь получить доступ к ведру http://s3.amazonaws.com/commoncrawl/parse-output/segment/ с помощью boto. Я не могу понять, как перевести это в имя для boto.s3.bucket.Bucket().Как перевести AWS S3 url в имя ведра для boto?

Это суть того, что я иду:

s3 = boto.connect_s3() 
cc = boto.s3.bucket.Bucket(connection=s3, name='commoncrawl/parse-output/segment') 
requester = {'x-amz-request-payer':'requester'} 
contents = cc.list(headers=requester) 
for i,item in enumerate(contents): 
    print item.__repr__() 

Я получаю "boto.exception.S3ResponseError: S3ResponseError: 400 Bad Request ... Указанный ковш не действует ..."

ответ

1

Название ведра было бы общим. Все, что появляется после этого, на самом деле является лишь частью имени ключей, которые появляются в ковше.

+4

мне было бы интересно узнать о Boto интерфейсов для анализа S3 URL. Существует как минимум три разных соглашения по URL, и было бы неплохо иметь стандартную реализацию синтаксического анализа в библиотеке. Есть ли один? –

+0

Я не мог найти его ни в boto, поэтому написал парсер - см. Мой ответ. –

9

AWS documents list four possible url formats for S3 - вот что я только что собрал, чтобы извлечь ведро и область для всех разных форматов url.

import re 

def bucket_name_from_url(url): 
    """ Gets bucket name and region from url, matching any of the different formats for S3 urls 
    * http://bucket.s3.amazonaws.com 
    * http://bucket.s3-aws-region.amazonaws.com 
    * http://s3.amazonaws.com/bucket 
    * http://s3-aws-region.amazonaws.com/bucket 

    returns bucket name, region 
    """  
    match = re.search('^https?://([^.]+).s3.amazonaws.com/', url) 
    if match: 
     return match.group(1), None 

    match = re.search('^https?://([^.]+).s3-([^.]+).amazonaws.com/', url) 
    if match: 
     return match.group(1), match.group(2) 

    match = re.search('^https?://s3.amazonaws.com/([^\/]+)', url) 
    if match: 
     return match.group(1), None 

    match = re.search('^https?://s3-([^.]+).amazonaws.com/([^\/]+)', url) 
    if match: 
     return match.group(2), match.group(1) 

    return None, None 

Что-то, как это должно действительно пойти в Бото ... Amazon, я надеюсь, что вы слушаете

0

Опираясь на ответ Марка я сделал небольшой pyparsing сценарий, который мне яснее (в том числе возможно ключевые матчи):

#!/usr/bin/env python 

from pyparsing import Word, alphanums, Or, Optional, Combine 

schema = Or(['http://', 'https://']).setResultsName('schema') 
word = Word(alphanums + '-', min=1) 
bucket_name = word.setResultsName('bucket') 
region = word.setResultsName('region') 

key = Optional('/' + word.setResultsName('key')) 

"bucket.s3.amazonaws.com" 
opt1 = Combine(schema + bucket_name + '.s3.amazonaws.com' + key) 

"bucket.s3-aws-region.amazonaws.com" 
opt2 = Combine(schema + bucket_name + '.' + region + '.amazonaws.com' + key) 

"s3.amazonaws.com/bucket" 
opt3 = Combine(schema + 's3.amazonaws.com/' + bucket_name + key) 

"s3-aws-region.amazonaws.com/bucket" 
opt4 = Combine(schema + region + ".amazonaws.com/" + bucket_name + key) 

tests = [ 
    "http://bucket-name.s3.amazonaws.com", 
    "https://bucket-name.s3-aws-region-name.amazonaws.com", 
    "http://s3.amazonaws.com/bucket-name", 
    "https://s3-aws-region-name.amazonaws.com/bucket-name", 
    "http://bucket-name.s3.amazonaws.com/key-name", 
    "https://bucket-name.s3-aws-region-name.amazonaws.com/key-name", 
    "http://s3.amazonaws.com/bucket-name/key-name", 
    "https://s3-aws-region-name.amazonaws.com/bucket-name/key-name", 
] 

s3_url = Or([opt1, opt2, opt3, opt4]).setResultsName('url') 

for test in tests: 
    result = s3_url.parseString(test) 
    print "found url: " + str(result.url) 
    print "schema: " + str(result.schema) 
    print "bucket name: " + str(result.bucket) 
    print "key name: " + str(result.key) 

Первоначально я сделал сценарий Марка также получить ключ (объект):

def parse_s3_url(url): 
    """ Gets bucket name and region from url, matching any of the different formats for S3 urls 
    * http://bucket.s3.amazonaws.com 
    * http://bucket.s3-aws-region.amazonaws.com 
    * http://s3.amazonaws.com/bucket 
    * http://s3-aws-region.amazonaws.com/bucket 

    returns bucket name, region 
    """ 
    match = re.search('^https?://([^.]+).s3.amazonaws.com(/\([^.]+\))', url) 
    if match: 
     return match.group(1), None, match.group(2) 

    match = re.search('^https?://([^.]+).s3-([^.]+).amazonaws.com/', url) 
    if match: 
     return match.group(1), match.group(2), match.group(3) 

    match = re.search('^https?://s3.amazonaws.com/([^\/]+)', url) 
    if match: 
     return match.group(1), None, match.group(2) 

    match = re.search('^https?://s3-([^.]+).amazonaws.com/([^\/]+)', url) 
    if match: 
     return match.group(2), match.group(1), match.group(3) 

    return None, None, None 
1

Расширенные метки ответа вернуть ключи

#!/usr/bin/env python 

import re 

def parse_s3_url(url): 
    # returns bucket_name, region, key 

    bucket_name = None 
    region = None 
    key = None 

    # http://bucket.s3.amazonaws.com/key1/key2 
    match = re.search('^https?://([^.]+).s3.amazonaws.com(.*?)$', url) 
    if match: 
     bucket_name, key = match.group(1), match.group(2) 

    # http://bucket.s3-aws-region.amazonaws.com/key1/key2 
    match = re.search('^https?://([^.]+).s3-([^\.]+).amazonaws.com(.*?)$', url) 
    if match: 
     bucket_name, region, key = match.group(1), match.group(2), match.group(3) 

    # http://s3.amazonaws.com/bucket/key1/key2 
    match = re.search('^https?://s3.amazonaws.com/([^\/]+)(.*?)$', url) 
    if match: 
     bucket_name, key = match.group(1), match.group(2) 

    # http://s3-aws-region.amazonaws.com/bucket/key1/key2 
    match = re.search('^https?://s3-([^.]+).amazonaws.com/([^\/]+)(.*?)$', url) 
    if match: 
     bucket_name, region, key = match.group(2), match.group(1), match.group(3) 

    return list(map(lambda x: x.strip('/') if x else None, [bucket_name, region, key])) 
0

Вот это моя версия JS:

function parseS3Url(url) { 
    // Process all aws s3 url cases 

    url = decodeURIComponent(url); 
    let match = ""; 

    // http://s3.amazonaws.com/bucket/key1/key2 
    match = url.match(/^https?:\/\/s3.amazonaws.com\/([^\/]+)\/?(.*?)$/); 
    if (match) { 
    return { 
     bucket: match[1], 
     key: match[2], 
     region: "" 
    }; 
    } 

    // http://s3-aws-region.amazonaws.com/bucket/key1/key2 
    match = url.match(/^https?:\/\/s3-([^.]+).amazonaws.com\/([^\/]+)\/?(.*?)$/); 
    if (match) { 
    return { 
     bucket: match[2], 
     key: match[3], 
     region: match[1] 
    }; 
    } 

    // http://bucket.s3.amazonaws.com/key1/key2 
    match = url.match(/^https?:\/\/([^.]+).s3.amazonaws.com\/?(.*?)$/); 
    if (match) { 
    return { 
     bucket: match[1], 
     key: match[2], 
     region: "" 
    }; 
    } 

    // http://bucket.s3-aws-region.amazonaws.com/key1/key2 
    match = url.match(/^https?:\/\/([^.]+).s3-([^\.]+).amazonaws.com\/?(.*?)$/); 
    if (match) { 
    return { 
     bucket: match[1], 
     key: match[3], 
     region: match[2] 
    }; 
    } 

    return { 
    bucket: "", 
    key: "", 
    region: "" 
    }; 
}