【发布时间】:2019-02-17 05:32:41
【问题描述】:
我在 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
【问题讨论】:
-
看起来
tweetsin{"tweets": tweets}可能作为字符串或字符串列表进入。process_tweet是做什么的?另外,for t in tweets中的样本t是什么样的?我想这是一个字典,但我想确定一下。 -
@wholevinski 我发布了
process_tweet的代码,t in tweets的t是一个tweepy对象,您可以在process_tweet中查看我是如何访问它的。我还展示了如何从另一种语言连接到相同的 AWS Lambda 函数不会产生相同的问题。 -
我完全错过了一些东西...您可以在收到响应负载时添加
json.loads(lambda_response['Payload'].read())吗? -
return json.dumps({"tweets": tweets})是错误的。你想return {"tweets": tweets}。该函数返回一个字典; Lambda 返回它的 JSON 表示形式。 -
@DaveRGP 我从未编写过运行 R 的 lambda 函数。我不可知地使用 lambda 输出,只需使用对项目最有意义的任何语言。我认为在这种情况下,这只是想出如何在 Python 中做到这一点的一个借口,这样我就可以亲自学习并教我的同事如何做到这一点。
标签: python json aws-lambda