Cách trích xuất dữ liệu từ báo cáo Power BI đã xuất bản lên web mà không có dữ liệu nguồn

Trong bài viết này Thanh sẽ chia sẻ với các bạn cách trích xuất dữ liệu từ báo cáo Power BI đã xuất bản lên web mà không có dữ liệu nguồn. Đây là một bài chia sẻ kiến thức nâng cao. Để có thể hiểu và triển khai được đoạn code trong bài này, bạn cần kiến thức ít nhất từ khóa học:

Lập trình tương tác Python Excel chìa khóa tối ưu công việc

Mời các bạn theo dõi video phân tích và giải thích code sử dụng ở đây:

YouTube video

Đoạn code Python sử dụng trong video là:


import re
import json
import base64
import requests
from bs4 import BeautifulSoup
from urllib.parse import unquote

url = 'https://app.powerbi.com/view?r=eyJrIjoiYjQzZDE1ZDgtNTI0NS00N2U5LThlM2QtMTljZTcwMTgyY2E4IiwidCI6IjQ0YmQ2NjgzLWI0MTQtNGFjNC1iY2VjLTY4NDFiZDNmMzlkMyIsImMiOjEwfQ%3D%3D'
token = url.split('=')[-1]
unquoted_token = unquote(token)

token_string = base64.b64decode(unquoted_token).decode('utf-8')
d = json.loads(token_string)
tenantId = d['t']
resourceKey = d['k']
html_data = requests.get(url).text
resolvedClusterUri = re.search(r"var resolvedClusterUri = '(.*?)'", html_data)[1].replace('-redirect', '-api')
requestId = re.search(r"var requestId = '(.*?)'", html_data)[1]
activityId = re.search(r"var telemetrySessionId =  '(.*?)'", html_data)[1]

url = resolvedClusterUri + "/public/reports/" + resourceKey + "/modelsAndExploration?preferReadOnlySession=true"
query_url = resolvedClusterUri + "/public/reports/querydata?synchronous=true"
headers={'ActivityId': activityId, 'RequestId': requestId, 'X-PowerBI-ResourceKey': resourceKey}
data = requests.get(url, headers=headers).json()

for s in data['exploration']['sections']:
    if 'query' in s['visualContainers'][0]:

        payload = {
          "version": "1.0.0",
          "queries": [
            {
              "Query": json.loads(s['visualContainers'][0]['query']),
              "CacheKey": '',
              "QueryId": "",
              "ApplicationContext": {
                "DatasetId": data['models'][0]['dbName'],
                "Sources": [
                  {
                    "ReportId": data['exploration']['report']['objectId']
                  }
                ]
              }
            }
          ],
          "cancelQueries": [],
          "modelId": data['models'][0]['id']
        }

        section_data = requests.post(query_url, json=payload, headers=headers).json()

        print(section_data['results'][0]['result']['data']['dsr']['DS'][0]['ValueDicts']['D0'])
        print('-' * 80)
        print(section_data['results'][0]['result']['data']['dsr']['DS'][0]['PH'][0]['DM0'])