0

我正在编写一个简单的 Python 脚本,利用 SQL Server 中的 Python 机器学习服务功能。目标是我的 SQL 服务器可以使用 python 脚本 ping 外部 API 并将结果读入变量。

我已经成功构建了 GET 请求,我只是在努力将 API 的输出反馈到数据库中

到目前为止我所拥有的:

EXECUTE sp_execute_external_script @language = N'Python', 
@script = N'

import requests 
import pandas as pd
URL = "https://api.website.io/verify?email=dave@davidson.com&apikey=test_44fbcce85ba0f270273f4452bea2311de50f9c"
r = requests.get(url = URL)
data = r.text
print(data)
'
, @input_data_1 = N''
WITH RESULT SETS(([Col1] varchar(MAX) NOT NULL));

所以 print(data) 在 SSMS 中给了我以下输出:

{"success":false,"message":"Invalid API key"}

但我不想打印它,我想将它读入 SQL。我真的不在乎它是怎么出来的,所以现在我只指定了一个名为“Col1”的列来保存输出,但我最终需要将“False”和“Invalid API key”加载到两个变量中我的 SQL Server 存储过程,以便我可以在下一步中使用这些值。如果我必须手动从 JSON 中解析出来,那我很好,但理想情况下,它们会在 SQL 输出中作为单独的列出现。

我尝试在各种排列中使用 r.json() 但我得到了很多不同的错误:

对于 SQL Server 机器学习,我知道我需要创建一个名为“OutputDataSet”的变量,并且需要属于“pandas 数据框”类型,因此我需要将“r”中保存的 JSON 数据转换为 pandas 数据框。然而,我在这方面尝试的一切都给了我神秘的错误代码

例如:

OutputDataSet = pd.DataFrame.from_dict(r.json(), orient="index")

给出:“执行错误。”

或者

OutputDataSet = pd.DataFrame.from_dict(r.text, orient="index")

给出“AttributeError:‘str’对象没有属性‘values’”

将 JSON 转换为我没有得到的 DataFrame 的语法是什么?或者是否需要额外的步骤或库来将 Requests 库的输出转换为 Pandas 库可以接受的东西?

4

1 回答 1

1

经过多次反复试验,我有了一个可行的解决方案:

我的数据库中有一个 InputData 表,我的存储过程从 InputData 读取所有行,使用 Python 通过 API 运行它们,然后将 API 结果返回到一个临时表中,我可以像使用 SQL 中的任何表一样使用它。

在我的“InputData”表中,我有以下列:

参考- 我公司的专有参考号,因此我可以知道此 API 数据与哪个公司记录相关。

APIURL - 我的 API 请求的预配置 URL。此字段包含此参考的 API 请求的所有参数,以及此 API 的 API 密钥。基本上整个 HTTP API 请求都在这里。我在前面的 SQL 步骤中创建了这个 URL,因为用 Python 做这件事对我来说很尴尬,而且在这种情况下也没有真正的必要。

JSONDATA - 数据类型为 nvarchar(MAX) 的空列,此列中的所有记录均为 NULL。一种作弊的方式来做到这一点。通过将此 NULL 值作为输入数据中的列传递,我们不必在输出数据中指定或命名它。由于在 SQL 表中有一个空列几乎没有区别,因此我选择了这种方式来简化从 Python 中获取输出数据并进入 SQL 的过程。

-- Define query
DECLARE @sqlscript NVARCHAR(MAX);
    SET @sqlscript = N'SELECT Reference, APIURL, JSONData FROM dbo.InputData';

-- Define Python script
DECLARE @pscript NVARCHAR(MAX);
    SET @pscript = N'
import requests                       # Import the "requests" library that contains the requests.get command we will use to query the API (supports SSL, https etc)
InputDF = InputDataSet                # Assign the input data (named InputDataSet by default in SQL Python) to a Python dataframe object named "InputDF"
OutputDF = InputDF                    # Copy all the input data to a new Python dataframe object named "OutputDF" 
for row in InputDF.itertuples():      # Start a loop which iterates over every row in InputDF, using "itertuples" Python function
    URL = row.KickBoxURL              # Read the KickBox API URL for this case/email address from the input dataframe
    r = requests.get(url = URL)       # Use the "get" command from the requests library to send our request to the API using that URL
    OutputDF.at[row.Index,4]= r.text  # Update column 4 (JSONData) of the output dataframe for the current iteruples row index, with the output JSON text from the .get command (stored in "r")
OutputDataSet = OutputDF              # Return the OutputDF dataset as a SQL Server "OutputDataSet" (the default name in SQL Python) which returns the data as a query output, which we will INSERT into #Results
';
 
-- Declare temp table to hold results
  DROP TABLE IF EXISTS #Results
CREATE TABLE #Results (Reference varchar(10) NOT NULL PRIMARY KEY CLUSTERED,
                       APIURL varchar(1000) NOT NULL,
                       JSONOutput nvarchar(MAX) NULL)
 
-- Run procedure using Python script and T-SQL query and Insert results to #Results
 INSERT #Results
   EXEC sp_execute_external_script
        @language = N'Python',
        @script = @pscript,
        @input_data_1 = @sqlscript;  

运行上述内容后,我现在有一个名为 #Results 的临时表,其中包含我发送的每个单独请求的所有参考编号和来自 API 的响应 JSON。

然后,我可以对该临时表执行一些 JSON 查询,以从 JSON 中提取包含我需要的数据的特定字段。由于那时我不再查询 API,我现在可以执行任意数量的 SELECT 查询,但我只在每条记录中访问过外部 API 一次。

于 2021-02-26T14:19:21.070 回答