在 SQL 服务器机器学习服务中读取我的 Python GET 请求的结果

Reading the results of my Python GET request in SQL Server Machine Learning Services

我正在整理一个简单的 Python 脚本,利用 SQL 服务器中的 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 服务器存储过程中的两个变量中,以便我可以在下一步中使用这些值。如果我必须手动从 JSON 中解析出那些,那么我很好,但理想情况下,它们会在 SQL 输出中作为单独的列出现。

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

对于 SQL 服务器机器学习,我知道我需要创建一个名为“OutputDataSet”的变量,并且必须是“pandas 数据帧”类型,所以我需要转换JSON 保存在“r”中的数据进入 pandas 数据帧。然而,我在这方面尝试的一切都给我神秘的错误代码

例如:

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

给出:“执行错误。”

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

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

将 JSON 转换为我没有得到的 DataFrame 的语法是什么? 或者是否需要额外的步骤或库来将请求库的输出转换为 Pandas 库将接受的内容?

经过反复试验,我找到了一个可行的解决方案:

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

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

参考文献 - 我公司的专有参考编号,因此我可以分辨出此 API 数据与哪个公司记录相关。

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

JSONDATA - 数据类型为 nvarchar(MAX) 的空列,该列中的所有记录均为 NULL。一种作弊的方式来做到这一点。通过将此 NULL 值作为输入数据中的列传递,我们不必在输出数据中指定或命名它。由于在 SQL table 中有一个空列几乎没有什么区别,这就是我选择的简化从 Python 和 [=52= 中获取输出数据的方法].

-- 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 的临时文件 table,其中包含每个人的 API 的所有参考编号和响应 JSON请求我发送它。

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