1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Tableau Serverにアクセスして画像、データを取得するプログラムを作ってみる(Python)

Last updated at Posted at 2024-07-13

はじめに

前回と同じく社内のTableauサーバに公開されているグラフの画像データとテキストデータをダウンロードします。

Tableau画面スクリーンショット 2024-07-13 140909.png

必要なライブラリ

・Pythonの実行環境 (v3.11.4で試しました)
・ライブラリ requests, json

ライブラリがない場合は以下でインストールしてください
(jsonはもとから入っているようです)

pip install requests

必要な情報

・個人用アクセストークン:Tableauサーバの「マイアカウントの設定」画面より設定してください。
 詳細は前回の記事に記載しています。

まず、認証してTokenを取得する

以下のsigninのAPIを利用して認証します。JSONのパースはResponse Bodyに書かれてあるタグを参考にしています。
POST /api/api-version/auth/signin
https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref.htm#sign_in
以下のコードです。TODOに書かれているサーバ情報とトークン情報を実行するサーバのものに修正してください。認証はrequests.postを実行します。このときにPersonal Access TokenをPayloadに設定します。実行した結果のHTTP Responseを分析してこの後の通信で使用するTokenとsite idを取得します。

sample1.py
# -*- coding: utf-8 -*-
import requests, json.

TABLEAU_TOKEN_VALUE = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'  #TODO Tableauの情報
TABLEAU_TOKEN_NAME = 'test'  #TODO  個人用アクセストークンの「トークン名」
TABLEAU_SERVER = 'tableauserver.tableauserver.jp'  #TODO Tableauサーバのアドレス
TABLEAU_VERSION = '3.19'  #TODO Tabeleau ServerのAPI version

#Tableauサーバーへサインインする
server_name = TABLEAU_SERVER
version = TABLEAU_VERSION
site_url_id = ""    # Site URLのパス、空白の場合はDefaultになる

# Personal Access Token を指定する
personal_access_token_name = TABLEAU_TOKEN_NAME      # Personal access tokenの名前
personal_access_token_secret = TABLEAU_TOKEN_VALUE   # Personal access token

signin_url = "https://{server}/api/{version}/auth/signin".format(server=server_name, version=version)   
payload = { "credentials": { "personalAccessTokenName": personal_access_token_name, "personalAccessTokenSecret": personal_access_token_secret, "site": {"contentUrl": site_url_id }}}

headers = {
	'accept': 'application/json',
	'content-type': 'application/json'
}
    
# サーバにRequestを送信する
req = requests.post(signin_url, json=payload, headers=headers, verify=False)
req.raise_for_status()

#HTTP Responseを取得
response = json.loads(req.content)

#credentialsのエレメントからTokenを取得する
token = response["credentials"]["token"]

#Site IDエレメントからSite IDを取得する
site_id = response["credentials"]["site"]["id"]

print('Sign in successful!')
print('Token: {token}'.format(token=token))
print('Site ID: {site_id}'.format(site_id=site_id))

view idを検索する

以下のAPIを使ってview_idを検索します。
GET /api/api-version/sites/site-id/views?filter=viewUrlName:eq:view-name
https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#get_view_by_path
検索結果はJSON形式で返るようにして、JSONデータをパースして最初のview idを取得しています。複数のviewを持つ結果が返る場合はプログラムを修正してください。

sample2.py
VIEW_URL_NAME = 'Order_Sales' #TODO viewUrlNameの値(シート名)を入れる
#view idを探す
query_value=  "filter=viewUrlName:eq:{viewUrlName}".format(viewUrlName=VIEW_URL_NAME)
headers = {'X-tableau-auth':token,
           'accept': 'application/json'}

#GET /api/api-version/sites/site-id/views?filter=viewUrlName:eq:view-name
view_get_url="https://{server}/api/{version}/sites/{siteid}/views?{query}".format(
        server=TABLEAU_SERVER, version=TABLEAU_VERSION, siteid=site_id,  query= query_value)

outDataOrig = requests.get(view_get_url,headers=headers).content
outDataDecode= outDataOrig.decode()
json_out = json.loads(outDataDecode)
view_id = json_out['views']['view'][0]['id']

print('view id: {view_id}'.format(view_id=view_id))

viewUrlNameからうまく検索できない場合は以下のコードのようにフィルタなしでviewの一覧を出すこともできます。この場合はprintされたXMLから目的のシートのview idを探してview_idセットしてください

sample2-2.py
headers = {'X-tableau-auth':token}

#GET /api/api-version/sites/site-id/views?filter=viewUrlName:eq:view-name
view_get_url="https://{server}/api/{version}/sites/{siteid}/views".format(
        server=TABLEAU_SERVER, version=TABLEAU_VERSION, siteid=site_id)

outDataOrig = requests.get(view_get_url,headers=headers).content
print(outDataOrig.decode())

画像ファイルを取得する

以下のAPIでイメージを取得します。
GET /api/api-version/sites/site-id/views/view-id/image
https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#query_view_image
必要なものはsite-idとview-idなので取得した値をURLに入れます。
requests.getを実行するとファイルをダウンロードできます。認証情報はHTTPヘッダーの中にSignin時に取得したTokenを入れます。

sample3.py
DOWNLOAD_IMAGE_PATH = 'sample.png'   #TODO 保存先のファイル名

query_value = "resolution=high" 
headers = {'X-tableau-auth':token}
  
#GET /api/api-version/sites/site-id/views/view-id/image?vf_<fieldname>=filter-value
image_get_url="https://{server}/api/{version}/sites/{siteid}/views/{viewid}/image?{query}".format(
        server=TABLEAU_SERVER, version=TABLEAU_VERSION, siteid=site_id, viewid=view_id, query= query_value)

urlData = requests.get(image_get_url,headers=headers).content
   
with open(DOWNLOAD_IMAGE_PATH, mode='wb') as f:
    f.write(urlData)

テキストファイル(CSV)をダウンロードする

テキストファイルの取得は以下になります。
#GET /api/api-version/sites/site-id/views/view-id/data
https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#query_view_data
取得方法はイメージと同じですが、URLDecodeしないと文字化けするケースがありました。
サンプルではそのままCSVファイルに書き出していますが、openpyxlパッケージを使うとExcelファイルに書き出すこともできます。(もちろん、そのままファイル出力するだけでなくExcel表を読み込んである列に合うデータを入れるといったプログラムを書くこともできます。)

sample4.py
DOWNLOAD_TEXT_PATH = 'sample.csv'   #TODO 保存先のファイル名

query_value = ""
    
headers = {'X-tableau-auth':token}
  
#GET /api/api-version/sites/site-id/views/view-id/data?vf_<fieldname>=filter-value
data_get_url="https://{server}/api/{version}/sites/{siteid}/views/{viewid}/data?{query}".format(
    server=TABLEAU_SERVER, version=TABLEAU_VERSION, siteid=site_id, viewid=view_id, query= query_value)
urlData = requests.get(data_get_url,headers=headers).content  
outtext = urlData.decode()

#取得したデータを出力してみる
print(outtext)

#ファイルに出力する
with open(DOWNLOAD_TEXT_PATH, mode='w') as f:
    f.write(outtext)

サインアウトする

Tokenはタイムアウトまで有効なためデータ取得できたらサインアウトします。
以下のHTTP POSTの通信を行いますが、RequestのBodyは空になります。
POST /api/api-version/auth/signout
https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref.htm#sign_out

sample5.py
server_name = TABLEAU_SERVER  #Tableau Serverの情報(Name/IPアドレス)
version = TABLEAU_VERSION     #Tabeleau ServerのAPI version
    
headers = {
	'accept': 'application/json',
	'content-type': 'application/json'
}
    
#サインイン時に取得した認証のTokenをヘッダにセットする
headers['X-tableau-auth']=token
    
#サインアウトのクエリをセット
signout_url = "https://{server}/api/{version}/auth/signout".format(server=server_name, version=version)

req = requests.post(signout_url, data=b'', headers=headers, verify=False)
req.raise_for_status()
print('Sign out successful!')

まとめ

ソースコードをまとめておきます

sample_all.py
# -*- coding: utf-8 -*-
import requests, json

#環境に応じて変更する箇所#######################
TABLEAU_TOKEN_VALUE = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'  #TODO Tableauの情報
TABLEAU_TOKEN_NAME = 'test'  #TODO  個人用アクセストークンの「トークン名」
TABLEAU_SERVER = 'tableauserver.tableauserver.jp'  #TODO Tableauサーバのアドレス
TABLEAU_VERSION = '3.19'  #TODO Tabeleau ServerのAPI version

DOWNLOAD_IMAGE_PATH = 'sample.png'   #TODO 保存先のファイル名
DOWNLOAD_TEXT_PATH = 'sample.csv'    #TODO 保存先のファイル名
VIEW_URL_NAME = 'Order_Sales' #TODO viewUrlNameの値(シート名)を入れる
##############################################

#Tableauサーバーへサインインする
signin_url = "https://{server}/api/{version}/auth/signin".format(server=TABLEAU_SERVER, version=TABLEAU_VERSION)   
payload = { "credentials": { "personalAccessTokenName": TABLEAU_TOKEN_NAME, "personalAccessTokenSecret": TABLEAU_TOKEN_VALUE, "site": {"contentUrl": SITE_URL_ID }}}

headers = {
	'accept': 'application/json',
	'content-type': 'application/json'
}
    
# サーバにRequestを送信する
req = requests.post(signin_url, json=payload, headers=headers, verify=False)
req.raise_for_status()

#HTTP Responseを取得
response = json.loads(req.content)

#credentialsのエレメントからTokenを取得する
token = response["credentials"]["token"]

#Site IDエレメントからSite IDを取得する
site_id = response["credentials"]["site"]["id"]

print('Sign in successful!')
print('Token: {token}'.format(token=token))
print('Site ID: {site_id}'.format(site_id=site_id))

###########################################################################################
#view idを探す
query_value=  "filter=viewUrlName:eq:{viewUrlName}".format(viewUrlName=VIEW_URL_NAME)
headers = {'X-tableau-auth':token,
           'accept': 'application/json'}

#GET /api/api-version/sites/site-id/views?filter=viewUrlName:eq:view-name
view_get_url="https://{server}/api/{version}/sites/{siteid}/views?{query}".format(
        server=TABLEAU_SERVER, version=TABLEAU_VERSION, siteid=site_id,  query= query_value)

outDataOrig = requests.get(view_get_url,headers=headers).content
outDataDecode= outDataOrig.decode()
json_out = json.loads(outDataDecode)
view_id = json_out['views']['view'][0]['id']

print('view id: {view_id}'.format(view_id=view_id))

###########################################################################################
#Imageファイルのダウンロード
query_value = "resolution=high" 
headers = {'X-tableau-auth':token}
  
#GET /api/api-version/sites/site-id/views/view-id/image?vf_<fieldname>=filter-value
image_get_url="https://{server}/api/{version}/sites/{siteid}/views/{viewid}/image?{query}".format(
        server=TABLEAU_SERVER, version=TABLEAU_VERSION, siteid=site_id, viewid=VIEW_ID, query= query_value)

urlData = requests.get(image_get_url,headers=headers).content
   
with open(DOWNLOAD_IMAGE_PATH ,mode='wb') as f:
    f.write(urlData)

###########################################################################################
#テキストファイルのダウンロード
query_value = ""
    
headers = {'X-tableau-auth':token}
  
#GET /api/api-version/sites/site-id/views/view-id/data?vf_<fieldname>=filter-value
data_get_url="https://{server}/api/{version}/sites/{siteid}/views/{viewid}/data?{query}".format(
    server=TABLEAU_SERVER, version=TABLEAU_VERSION, siteid=site_id, viewid=VIEW_ID, query= query_value)
urlData = requests.get(data_get_url,headers=headers).content  
outtext = urlData.decode()

#取得したデータを出力してみる
#print(outtext)

with open(DOWNLOAD_TEXT_PATH ,mode='w') as f:
    f.write(outtext)

######################################################################################
#Signout   
headers = {
	'accept': 'application/json',
	'content-type': 'application/json'
}
    
#サインイン時に取得した認証のTokenをヘッダにセットする
headers['X-tableau-auth']=token
    
#サインアウトのクエリをセット
signout_url = "https://{server}/api/{version}/auth/signout".format(server=TABLEAU_SERVER, version=TABLEAU_VERSION)

req = requests.post(signout_url, data=b'', headers=headers, verify=False)
req.raise_for_status()
print('Sign out successful!')
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?