我正在研究一个项目,其中一部分涉及从python脚本插入到项目的谷歌融合表。我花了几天时间试图弄清楚如何做到这一点,我真的很困惑。
我的研究似乎表明我需要使用Oauth 2.0来访问API。在这样做时,我可以成功地获得访问令牌,但我似乎无法成功地获得刷新令牌。我不确定这是否会妨碍我成功地将对Fusion Table的访问与Python代码集成在一起的能力。
我遇到的第二个问题是,我真的不明白如何准确地在我的表中插入一行代码。我在上面找到的大部分材料都来自已弃用的Fusion Tables SQL API,我不完全理解这种新方法。
我是这种事情的初学者,任何帮助我的方向都是非常感激的!
编辑:到目前为止,我运行的代码是这样的:
client_id = "<client_i>"
client_secret = "<client_secret>"
table_id = "<table_id>"
access_token = ""
refresh_token = "<refresh_token>"
# the refresh token is used to request a new access token
data = urllib.urlencode({
'client_id': client_id,
'client_secret': client_secret,
'refresh_token': refresh_token,
'grant_type': 'refresh_token'})
request = urllib2.Request(
url='https://accounts.google.com/o/oauth2/token',
data=data)
request_open = urllib2.urlopen(request)
response = request_open.read()
request_open.close()
tokens = json.loads(response)
access_token = tokens['access_token']
# Read the table
request_read = urllib2.Request(
url='https://www.google.com/fusiontables/api/query?%s' %
(urllib.urlencode({'access_token': access_token,
'sql': 'SELECT * FROM table_id'})))
request_open = urllib2.urlopen(request_read)
response = request_open.read()
request_open.close()
print response
和我的代码试图插入一个新行到我的表:
date = str(datetime.now().date())
time = str(datetime.now().time())
query = 'INSERT INTO table_id (Date,Time,Saskatoon,Regina,MeadowLake)VALUES(date,time,60.01,60.02,59.99)'
data = urllib2.Request(
url='https://www.google.com/fusiontables/api/query?%s' %
(urllib.urlencode({'access_token': access_token,
'sql': query})))
request_open = urllib2.urlopen(data)
当我运行这个时,我得到
HTTP错误400:HTTP GET只能用于select查询。
我知道我应该做一个POST而不是GET的INSERT,我只是不确定我的代码需要改变什么。对不起,我是个新手。
第二次编辑:
很抱歉让这个更长,但我觉得这是相关的,以显示我已经得到了到目前为止。我切换到库请求,事情变得更容易,但我仍然没有成功地进行POST。我用于导入行的新代码如下:
def importRows(self):
print 'IMPORT ROWS'
date = str(datetime.now().date())
time = str(datetime.now().time())
data = {'Date': date,
'Time': time,
'Saskatoon': '60.01',
'Regina': '59.95'}
url = 'https://www.googleapis.com/upload/fusiontables/v1/tables/%s/import/%s' %
(tableid, self.params) # self.params is access token
importRow = requests.post(url, params=data)
print importRow.status_code
print importRow.text
得到
400
{
"error": {
"errors": [
{
"domain": "fusiontables",
"reason": "badImportInputEmpty",
"message": "Content is empty."
}
],
"code": 400,
"message": "Content is empty."
}
}
如果您的应用程序需要脱机访问Google API,那么对授权码的请求应该包括access_type参数,该参数的值是脱机的。
https://developers.google.com/accounts/docs/OAuth2WebServer离线
然后,为了使用刷新令牌获得访问令牌,您发送包含grant_type
的POST请求,其值为refresh_token
。
基本上,SQL的工作方式是你发送POST请求使用SQL语句的子集https://www.googleapis.com/fusiontables/v1/query?sql=STATEMENT_HERE
引用
https://developers.google.com/fusiontables/docs/v1/reference/queryhttps://developers.google.com/fusiontables/docs/v1/sql-reference
编辑:由于您使用的是没有数据参数的urllib2
,因此默认为GET。要解决这个问题,您应该使用另一个允许显式指定方法的HTTP库(如requests
或httplib
)或执行以下操作:
query = "INSERT INTO %s(EXAMPLE_COL1,EXAMPLE_COL2) VALUES"
"('EXAMPLE_INFO1','EXAMPLE_INFO2')" % table_id # Single quotes
opener = urllib2.build_opener(urllib2.HTTPHandler)
request = urllib2.Request('https://www.google.com/fusiontables/api/query?%s' %
(urllib.urlencode({'access_token': access_token,
'sql': query})),
headers={'Content-Length':0}) # Manually set length to avoid 411 error
request.get_method = lambda: 'POST' # Change HTTP request method
response = opener.open(request).read()
print response
注意事项:
猴子补丁的方法做我们想要的(POST与空体),否则我们会收到
HTTP Error 400: HTTP GET can only be used for SELECT queries
。手动指定我们没有body (
Content-Length
是0
),否则我们将接收HTTP Error 411: Length Required
。必须使用双引号和内单引号或者转义内引号来通过查询提交字符串。换句话说,
"INSERT INTO %s(EXAMPLE_COL1,EXAMPLE_COL2) VALUES(EXAMPLE_INFO1,EXAMPLE_INFO2)" % table_id
不工作。如果我们尝试使用前一行,我们会得到类似
的内容HTTP Error 400: Parse error near 'SOME_STRING' (line X, position Y)
参见urllib2:
更改方法的信息有没有办法在python中做HTTP PUT