tableau报表备份(下载)twbx文件

166 阅读3分钟

方案一:TSM命令行方式

1.登录tableau, 命令:tabcmd login -s localhost -u userName -p passWord

image.png

2.下载twbx文件,命令:

tabcmd get "/workbooks/test_01.twbx" -f "/usr/local/back-up/test_01_down.twbx"

image.png

注意:“test_01.twbx”,为工作簿名称,且不能含有中文

方案二:REST API方式

1.登录tableau sever,获取token,site_id,user_id

{server_address}/api/{api_version}/auth/signin

server_address: tableau服务器地址

api_version:api版本号,需要和tableau server版本对应,具体对应关系:help.tableau.com/current/api…

image.png

例子:

image.png

2.获取工作簿列表 123.com/api/3.17/si…

image.png

3.下载twbx文件,命令:

curl "{server_address}/api/3.17/sites/{site_id}/workbooks/{workbook_id}/content" -X GET -H "X-Tableau-Auth:{token}" > /use/local/back_up/test(这里可以写中文).twbx

参考资料:

help.tableau.com/current/api…

help.tableau.com/current/api…

help.tableau.com/current/api…

python脚本实现


#!/usr/bin/env python
# -*- coding: utf-8 -*-

# REST API 方式,下载工作簿,保存为.twbx文件,参考文档
# https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_concepts_auth.htm
# https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#download_workbook

import requests, json
import datetime
import os,shutil
import sys
import time

 # tableau server 地址
server_name = "http://abcd.com"  
# API 版本,需要和tableau server 版本对应。具体版本对应关系: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_concepts_versions.htm
version = "3.17"  
user_name = "admin"   
password = "1234"
# 全局变量
token = ""
site_id = ""
# 保存备份文件的目录
file_path = "/usr/local/tableau_bakup/"
now = datetime.datetime.now().date()



# 打印日志,每4kb刷新一次文件
class Logger(object):

    def __init__(self, stream=sys.stdout):
        output_dir = "{file_path}{now}".format(file_path=file_path, now=now)  # folder 
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        #log_name = '{}.txt'.format(time.strftime('%Y-%m-%d-%H-%M',time.localtime(time.time())))
        log_name_time = time.strftime('%Y-%m-%d-%H-%M-%S',time.localtime(time.time()))
        log_name = log_name_time + ".txt"
        filename = os.path.join(output_dir, log_name)

        self.terminal = stream
        self.log = open(filename, 'a+')

    def write(self, message):
        self.terminal.write(message)
        self.log.write(message)

    def flush(self):
        pass

#登录,获取token和site_id
def signin():

    signin_url = "{server}/api/{version}/auth/signin".format(server=server_name, version=version)
    payload = { "credentials": { "name": user_name, "password": password, "site": {"contentUrl": "" }}}
    headers = {
        'accept': 'application/json',
        'content-type': 'application/json'
    }
    # Send the request to the server
    req = requests.post(signin_url, json=payload, headers=headers, verify=False)
    req.raise_for_status()
    # Get the response
    response = json.loads(req.content)

    # Get the authentication token from the credentials element
    global token
    token = response["credentials"]["token"]

    # Get the site ID from the <site> element
    global site_id
    site_id = response["credentials"]["site"]["id"]
    print('---------------登录成功!-----------------')
    return

# 退出
def signout():

    signout_url = "{server}/api/{version}/auth/signout".format(server=server_name, version=version)
    headers = {
    'accept': 'application/json',
    'content-type': 'application/json',
    'X-Tableau-Auth': token
    }
    req = requests.post(signout_url, data=b'', headers=headers, verify=False)
    req.raise_for_status()
    print('---------------退出成功!------------------')
    return

# 目录不存在,创建
def create_dir():
    path = "{file_path}{now}".format(file_path=file_path, now=now)
    #path = path.strip()
    path = path.rstrip("\\")
    isExists = os.path.exists(path)
    if not isExists:
        os.makedirs(path) 
        print path+'目录创建成功'
        return True
    else:
        print path+'目录已存在'
        return False

# 下载.twbx文件
def download_file(workbook_id,workbook_name):

    workbook_name = workbook_name.encode('utf-8')
    print('\t开始备份: {workbook_name},{current_time}'.format(workbook_name=workbook_name,current_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
    url = "{server}/api/{version}/sites/{site_id}/workbooks/{workbook_id}/content".format(server=server_name, version=version,site_id=site_id,workbook_id=workbook_id)
    headers = {
        "X-Tableau-Auth": token
    }
    response = requests.get(url, headers = headers)
    with open('{file_path}{now}/{workbook_name}.twbx'.format(file_path=file_path,now=now,workbook_name=workbook_name), 'wb') as f:
        f.write(response.content)
    
    print('\t报表备份完成----------------: {workbook_name}'.format(workbook_name=workbook_name))
    return

# 获取工作簿列表
def download_all_workbooks():

    # http://127.0.0.1/api/3.17/sites/671944ca-3e72-45c2-bba7-23b837d61744/workbooks?pageSize=500
    download_all_workbooks_url = "{server}/api/{version}/sites/{site_id}/workbooks?pageSize=500".format(server=server_name, version=version,site_id=site_id)
    headers = {
    'accept': 'application/json',
    'content-type': 'application/json',
    'X-Tableau-Auth': token
    }
    req = requests.get(download_all_workbooks_url,headers=headers)
    req.raise_for_status()
    # Get the response
    response = json.loads(req.content)
    create_dir()
    for key in range(len(response['workbooks']['workbook'])):
        workbook_id = response['workbooks']['workbook'][key]['id']
        workbook_name = response['workbooks']['workbook'][key]['name']
        download_file(workbook_id,workbook_name)
    return


#计算两个日期相差天数,自定义函数名,和两个日期的变量名。
def caltime(date1,date2):
    #%Y-%m-%d为日期格式,其中的-可以用其他代替或者不写,但是要统一,同理后面的时分秒也一样;可以只计算日期,不计算时间。
    #date1=time.strptime(date1,"%Y-%m-%d %H:%M:%S") 
    date1=time.strptime(date1,"%Y-%m-%d")
    date2=time.strptime(date2,"%Y-%m-%d")
    #根据上面需要计算日期还是日期时间,来确定需要几个数组段。下标0表示年,小标1表示月,依次类推...
    #date1=datetime.datetime(date1[0],date1[1],date1[2],date1[3],date1[4],date1[5])
    date1=datetime.datetime(date1[0],date1[1],date1[2])
    date2=datetime.datetime(date2[0],date2[1],date2[2])
    #返回两个变量相差的值,就是相差天数
    return date2-date1

def delete_dir():

    sys.stdout = Logger(sys.stdout)  #  将输出记录到log
    sys.stderr = Logger(sys.stderr)  # 将错误信息记录到log 

    nowStr = now.strftime("%Y-%m-%d")
    print '当前日期:'+nowStr
    for files in os.listdir(file_path):
        day = caltime(files,nowStr)
        if day.days > 60:
            path = os.path.join(file_path, files)
            print '删除超过60天的数据:'+path
            try:
                shutil.rmtree(path)
                print('---------------------delete successful!-----------------------------')
            except OSError:
                os.remove(path)
    return


#删除历史数据
delete_dir()
# 登录
signin()
# 下载
download_all_workbooks()
# 退出
signout()