简体   繁体   English

使用AWS Lambda和api-gateway创建API时出错(python)

[英]Error when creating API using AWS Lambda and api-gateway (python)

TL;DR: getting errors using AWS Lambda and API-Gateway TL; DR:使用AWS Lambda和API-Gateway出错

Background 背景

I wrote a python script to help me track some index funds I am using. 我写了一个python脚本来帮助我跟踪一些正在使用的指数基金。 It basically scrapes (using requests and bs4) the price from different websites. 它基本上是从其他网站(使用请求和bs4)抓取价格。

I wanted to turn this into an API so I can use it anywhere, so I used Flask and Connexion to make this (followed this https://realpython.com/flask-connexion-rest-api/ ). 我想将其转换为API,以便可以在任何地方使用它,因此我使用了Flask和Connexion来实现(紧随https://realpython.com/flask-connexion-rest-api/ )。 That's all working perfectly fine locally, but I'm having trouble implementing this on AWS. 在本地这一切都工作得很好,但是我在AWS上实现它遇到了麻烦。

I have zipped up my code and the corresponding app packages to AWS Lambda and using that in the API Gateway. 我已将我的代码和相应的应用程序包压缩到AWS Lambda,并在API Gateway中使用了它。 However I am getting the following errors: 但是我收到以下错误:

Endpoint response body before transformations: {"errorMessage": "module initialization error"} Method response body after transformations: {"errorMessage": "module initialization error"}

I've googled for this, followed the steps here ( Amazon API Gateway : response body is not transformed when the API is called via Postman? ), deployed the app etc - not sure why this is happening. 我为此进行了谷歌搜索,请按照此处的步骤操作( 通过Postman调用API时,Amazon API Gateway:响应主体未转换? ),部署了应用程序等-不确定为什么会这样。

here is a snippet of the code: 这是代码片段:

import requests
from bs4 import BeautifulSoup
from datetime import date, timedelta
import datetime
import json


def CurrentPortfolioValue(event, context):
    initial_porfolio_price = float (100)
    initial_date = date(2018, 8, 19) #set the initial date to a date where the fortnightly payment has gone
    num_of_shares_vanguard = float(500)
    num_of_shares_AMPNZShares = float(300)
    num_of_shares_AMPAustralisianProperty = float(100)
    fortnightly_contrib = float(100)
    current_value = initial_porfolio_price
    #print(initial_date)

    #sets a user-agent    
    example_headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0'} #can make this better by having a list of random header


    #vanguard
    vanguard = requests.get("https://www.bloomberg.com/quote/VAN1579:AU",headers=example_headers) #need to have headers to avoid being blocked
    soup = BeautifulSoup(vanguard.content, 'html.parser')
    vanguard_price = soup.find_all("span", class_ = 'priceText__1853e8a5')[0].get_text()
    #print("Vanguard Price:\n" + vanguard_price+"AUD")

    #AMP Capital NZ Index 
    ampnzshares = requests.get("https://www.ampcapital.com/nz/en/investments/funds/index-funds/nz-shares-index-fund",headers=example_headers) #need to have headers to avoid being blocked
    soup1 = BeautifulSoup(ampnzshares.content, 'html.parser')
    ampnzshares_price = soup1.find_all("div", class_ = 'ht-module_title ht-highlight_color')[1].get_text()
    #print("AMP Capital NZ Index Price:\n" + ampnzshares_price+"NZD")

    #AMP Capital Australisian Property Index Fund
    ampAustralisianProperty = requests.get("https://www.ampcapital.com/nz/en/investments/funds/index-funds/australasian-property-index-fund",headers=example_headers) #need to have headers to avoid being blocked
    soup2 = BeautifulSoup(ampAustralisianProperty.content, 'html.parser')
    ampAustralianProperty_price = soup2.find_all("div", class_ = 'ht-module_title ht-highlight_color')[1].get_text()
    #print("AMP Capital Australisian Property Index Fund:\n" + ampAustralianProperty_price+"NZD")

    #get day difference between today and initial date
    current_date = date.today()
    days_difference = (current_date - initial_date).days #.days shows just the number of days
    #print(days_difference)

    count = days_difference
    while count > 14: #while difference is less than 14 days i.e forntightly payment hasnt been made
        current_value += initial_porfolio_price + (float(50) * float(vanguard_price)) + (float(50) * float(ampnzshares_price))
        count = count - 14
    print("Current Portfolio value is $" + str(current_value))
    return {
        "statusCode": 200,
        "body": json.dumps(current_value)}

CurrentPortfolioValue() #retrieves current portfolio value




my yaml file looks like ths: 我的yaml文件看起来像这样:

swagger: "2.0"
info:
  description: This is the swagger file that goes with our server code
  version: "1.0.0"
  title: Swagger REST Article
consumes:
  - "application/json"
produces:
  - "application/json"

basePath: "/api"

paths:
  /value: #name of the endpoint
    get:
      operationId: "ShareScraper.CurrentPortfolioValue" #link to the module - this is called when you navigate to /value
      tags:
        - "Portfolio"
      summary: "The portfolio data structure supported by the server application"
      description: "Read the current portfolio value"
      responses:
        200:
          description: "Successful read current portfolio value"
          schema:
            type: "string"
            items:
              properties:
                portfolio_value:
                  type: "string"

Thanks in advance! 提前致谢!

[Edit] This is my first time creating an api and using AWS so sorry if I am missing something fairly simple/obvious [编辑]这是我第一次创建api并使用AWS,所以很抱歉,如果我缺少相当简单/显而易见的内容

Your lambda code doesn't have the event and context argument. 您的lambda代码没有eventcontext参数。 Which are required arguments for a lambda python handler. 这是lambda python处理程序的必需参数。 You can modify your code as, 您可以将代码修改为

def CurrentPortfolioValue(event, context):

    current_value += initial_porfolio_price + (float(50) * float(vanguard_price)) + (float(50) * float(ampnzshares_price))
    count = count - 14
    print("Current Portfolio value is $" + str(current_value))
    return {
        "statusCode": 200,
        "body": json.dumps(current_value)}

CurrentPortfolioValue() #retrieves current portfolio value

Your Lambda function doesn't appear to be correctly formatted as a Lambda. 您的Lambda函数似乎没有正确设置为Lambda格式。 As per the AWS documentation, here , your Lambda must be formatted as a handler and must accept the event and context arguments. 根据AWS文档的此处 ,您的Lambda必须格式化为处理程序,并且必须接受事件和上下文参数。

You will need to edit your code to look more like this in order to get it to run: 您需要编辑代码使其看起来更像这样才能使其运行:

from botocore.vendored import requests
from bs4 import BeautifulSoup
import datetime
from datetime import date, timedelta
import json


def lambda_handler(event, context):

    initial_porfolio_price = float (100)
    initial_date = date(2018, 8, 19) #set the initial date to a date where the fortnightly payment has gone
    num_of_shares_vanguard = float(500)
    num_of_shares_AMPNZShares = float(300)
    num_of_shares_AMPAustralisianProperty = float(100)
    fortnightly_contrib = float(100)
    current_value = initial_porfolio_price
    #print(initial_date)

    #sets a user-agent
    example_headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0'} #can make this better by having a list of random header

    #vanguard
    vanguard = requests.get("https://www.bloomberg.com/quote/VAN1579:AU",headers=example_headers) #need to have headers to avoid being blocked
    soup = BeautifulSoup(vanguard.content, 'html.parser')
    print(soup)
    vanguard_price = soup.find_all("span", class_ = 'priceText__1853e8a5')[0].get_text()
    #print("Vanguard Price:\n" + vanguard_price+"AUD")

    #AMP Capital NZ Index
    ampnzshares = requests.get("https://www.ampcapital.com/nz/en/investments/funds/index-funds/nz-shares-index-fund",headers=example_headers) #need to have headers to avoid being blocked
    soup1 = BeautifulSoup(ampnzshares.content, 'html.parser')
    ampnzshares_price = soup1.find_all("div", class_ = 'ht-module_title ht-highlight_color')[1].get_text()
    #print("AMP Capital NZ Index Price:\n" + ampnzshares_price+"NZD")

    #AMP Capital Australisian Property Index Fund
    ampAustralisianProperty = requests.get("https://www.ampcapital.com/nz/en/investments/funds/index-funds/australasian-property-index-fund",headers=example_headers) #need to have headers to avoid being blocked
    soup2 = BeautifulSoup(ampAustralisianProperty.content, 'html.parser')
    ampAustralianProperty_price = soup2.find_all("div", class_ = 'ht-module_title ht-highlight_color')[1].get_text()
    #print("AMP Capital Australisian Property Index Fund:\n" + ampAustralianProperty_price+"NZD")

    #get day difference between today and initial date
    current_date = date.today()
    days_difference = (current_date - initial_date).days #.days shows just the number of days
    #print(days_difference)

    count = days_difference
    while count > 14: #while difference is less than 14 days i.e forntightly payment hasnt been made
        current_value += initial_porfolio_price + (float(50) * float(vanguard_price)) + (float(50) * float(ampnzshares_price))
    count = count - 14
    print("Current Portfolio value is $" + str(current_value))
    return {
       "statusCode": 200,
       "body": json.dumps(current_value)}


You didn't post your import statements but at the very least you'll need to import json. 您没有发布导入语句,但至少需要导入json。

Note that the call to the function is also removed. 请注意,对该函数的调用也已删除。 I've assumed that this function is running in isolation (ie nothing else running with it) and therefore you do not need to call it within the Lambda itself, as it will get executed in the Lambda environment. 我假设此函数是独立运行的(即没有其他函数与之一起运行),因此您无需在Lambda本身中调用它,因为它将在Lambda环境中执行。

EDIT: 编辑:

I've updated the code block and run it. 我已经更新了代码块并运行它。 It is indeed running in Lambda, however, at line 27 it is trying to find "span", class_ = 'priceText__1853e8a5' which doesn't exist in the response to the vanguard = requests.get... request. 它确实在Lambda中运行,但是,在第27行,它试图查找"span", class_ = 'priceText__1853e8a5' ,该值在对vanguard = requests.get... "span", class_ = 'priceText__1853e8a5' vanguard = requests.get...请求的响应中不存在。 Instead, as you can see in the screenshot below, we're receiving something else, and Lambda is giving us the error "errorMessage": "list index out of range" . 相反,如下面的屏幕快照所示,我们收到了其他消息,Lambda给了我们错误"errorMessage": "list index out of range"

To find out why, we have to look in the Log Output. 要找出原因,我们必须查看日志输出。 When we look at the output we see that instead of a page with the pricing information that we're trying to scrape, what is being received is actually a Captcha page; 当我们查看输出时,我们看到的不是接收到要抓取的包含定价信息的页面,而是实际收到的验证码页面。 Bloomberg recognize that you're scraping the data and they don't want people scraping their data, so to prevent this they want you to complete a Captcha, and because haven't built a way to handle this situation the Lambda is erroring out. 彭博社认为您正在抓取数据,他们不希望人们抓取数据,因此要防止这种情况,他们希望您完成验证码,并且由于尚未建立处理这种情况的方法,Lambda会出错。

Lambda图片

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM