如何使用Python从AWS Lambda检索格式正确的JSON

时间:2018-09-12 14:24:09

标签: python json aws-lambda

我在AWS Lambda中具有一个函数,该函数连接到Twitter API并返回与通过事件提供的特定搜索查询匹配的推文。下面是该功能的简化版本。我使用了一些辅助功能,例如get_secret来管理API密钥,而process_tweet则用于限制发送回什么数据以及执行将创建的日期转换为字符串的操作。最终结果是我应该重新获得字典列表。

def lambda_handler(event, context):
    twitter_secret = get_secret("twitter")

    auth = tweepy.OAuthHandler(twitter_secret['api-key'],
                               twitter_secret['api-secret'])
    auth.set_access_token(twitter_secret['access-key'],
                          twitter_secret['access-secret'])
    api = tweepy.API(auth)

    cursor = tweepy.Cursor(api.search,
                           q=event['search'],
                           include_entities=True,
                           tweet_mode='extended',
                           lang='en')

    tweets = list(cursor.items())
    tweets = [process_tweet(t) for t in tweets if not t.retweeted]

    return json.dumps({"tweets": tweets})

然后,在我的桌面上,我有调用lambda函数的代码。

aws_lambda = boto3.client('lambda', region_name="us-east-1")
payload = {"search": "paint%20protection%20film filter:safe"}
lambda_response = aws_lambda.invoke(FunctionName="twitter-searcher",
                                    InvocationType="RequestResponse",
                                    Payload=json.dumps(payload))
results = lambda_response['Payload'].read()
tweets = results.decode('utf-8')

问题是json.dumps在lambda中的输出与在Python中读取有效载荷之间的某个地方,数据变得很麻烦。例如,一个应该为\n的换行符变为\\\\n,所有双引号都存储为\\",而Unicode字符都以\\为前缀。因此,当我的桌面上的Python接收到转义字符时,所有被转义的字符都会被转义。考虑返回的列表的此元素(使用手动格式设置)。

'{\\"userid\\": 190764134,
  \\"username\\": \\"CapitalGMC\\",
  \\"created\\": \\"2018-09-02 15:00:00\\",
  \\"tweetid\\": 1036267504673337344,
  \\"text\\": \\"Protect your vehicle\'s paint! Find out how on this week\'s blog.
              \\\\ud83d\\\\udc47\\\\n\\\\nhttps://url/XYMxPhVhdH https://url/mFL2Zv8nWW\\"}'

我可以使用正则表达式来解决某些问题(\\"\\\\n),但是Unicode是棘手的,因为即使我将其匹配,如何用适当转义的字符替换它?当我在R中使用aws.lambda包进行此操作时,一切都很好,没有奇怪的转义转义符。

我的台式机在做什么,而AWS Lambda的响应却在破坏数据?

更新

进程鸣叫功能如下。从字面上看,它只是取出我想要保留的位,将datetime对象格式化为字符串并返回字典。

def process_tweet(tweet):
    bundle = {
        "userid": tweet.user.id,
        "username": tweet.user.screen_name,
        "created": str(tweet.created_at),
        "tweetid": tweet.id,
        "text": tweet.full_text
    }
    return bundle

仅供参考,在R中,代码如下所示。

payload = list(search="paint%20protection%20film filter:safe")
results = aws.lambda::invoke_function("twitter-searcher"
                                      ,payload = jsonlite::toJSON(payload
                                                              ,auto_unbox=TRUE)
                                      ,type = "RequestResponse"
                                      ,key = creds$key
                                      ,secret = creds$secret
                                      ,session_token = creds$session_token
                                      ,region = creds$region)
tweets = jsonlite::fromJSON(results)
str(tweets)

#> 'data.frame':    133 obs. of  5 variables:
#>  $ userid  : num  2231994854 407106716 33553091 7778772 782310 ...
#>  $ username: chr  "adaniel_080213" "Prestige_AdamL" "exclusivedetail" "tedhu" ...
#>  $ created : chr  "2018-09-12 14:07:09" "2018-09-12 11:31:56" "2018-09-12 10:46:55" "2018-09-12 07:27:49" ...
#>  $ tweetid : num  1039878080968323072 1039839019989983232 1039827690151444480 1039777586975526912 1039699310382931968 ...
#>  $ text    : chr  "I liked a @YouTube video https://url/97sRShN4pM Tesla Model 3 - Front End Package - Suntek Ultra Paint Protection Film" "Another #Corvette #ZO6 full body clearbra wrap completed using @xpeltech ultimate plus PPF ... Paint protection"| __truncated__ "We recently protected this Tesla Model 3 with Paint Protection Film and Ceramic Coating.#teslamodel3 #charlotte"| __truncated__ "Tesla Model 3 - Front End Package - Suntek Ultra Paint Protection Film https://url/AD1cl5dNX3" ...

tweets[131,]
#>        userid   username             created             tweetid
#> 131 190764134 CapitalGMC 2018-09-02 15:00:00 1036267504673337344
#>          text
#> 131 Protect your vehicle's paint! Find out how on this week's blog.\n\nhttps://url/XYMxPhVhdH https://url/mFL2Zv8nWW

2 个答案:

答案 0 :(得分:2)

在lambda函数中,您应该返回一个响应对象,该响应对象的响应主体中带有JSON对象。

# Lambda Function
def get_json(event, context):
    """Retrieve JSON from server."""
    # Business Logic Goes Here.
    response = {
        "statusCode": 200,
        "headers": {},
        "body": json.dumps({
            "message": "This is the message in a JSON object."
        })
    return response
}

答案 1 :(得分:1)

不要使用json.dumps()

我有一个类似的问题,当我刚返回“ body”:content而不是“ body”:json.dumps(content)时,我可以轻松地访问和操纵我的数据。在此之前,我得到了一种看起来像JSON的怪异形式,但事实并非如此。