gpt4 book ai didi

python - 从 Tableau map 中抓取数据

转载 作者:行者123 更新时间:2023-12-04 01:17:57 24 4
gpt4 key购买 nike

我正试图为阿片类药物危机的研究项目提取伊利诺伊州纳洛酮配送中心的位置和名称。

此画面生成的仪表板可从公共(public)卫生部访问此处 https://idph.illinois.gov/OpioidDataDashboard/

我已经尝试了我能找到的一切。首先更改 url 以使用 Tableau 的界面“下载”数据。那只能让我下载 pdf map ,而不是它背后的实际数据集。其次,我修改了我在 Stack overflow 上看到过几次的 python 脚本,以尝试请求数据。但是,我认为它遇到了某种错误。代码如下。

url = "https://interactive.data.illinois.gov/t/DPH/views/opioidTDWEB_prod/NaloxoneDistributionLocations"

r = requests.get(
url,
params= {
":embed":"y",
":showAppBanner":"false",
":showShareOptions":"true",
":display_count":"no",
"showVizHome": "no"
}
)
soup = BeautifulSoup(r.text, "html.parser")
print(soup)
tableauData = json.loads(soup.find("textarea",{"id": "tsConfigContainer"}).text)

dataUrl = f'https://tableau.ons.org.br{tableauData["vizql_root"]}/bootstrapSession/sessions/{tableauData["sessionid"]}'

r = requests.post(dataUrl, data= {
"sheet_id": tableauData["sheetId"],
})

dataReg = re.search('\d+;({.*})\d+;({.*})', r.text, re.MULTILINE)
info = json.loads(dataReg.group(1))
data = json.loads(dataReg.group(2))

print(data["secondaryInfo"]["presModelMap"]["dataDictionary"]["presModelHolder"]["genDataDictionaryPresModel"]["dataSegments"]["0"]["dataColumns"])

感谢任何帮助。

最佳答案

编辑

我做了一个 tableau scraper library将工作表数据提取到 Pandas 数据框中。

代码更简单,但在您的情况下,您仍然需要使用 xsrf token 构建 URL:

from tableauscraper import TableauScraper as TS
import requests
from bs4 import BeautifulSoup

init_url = "https://idph.illinois.gov/OpioidDataDashboard/"
r = requests.get(init_url)
soup = BeautifulSoup(r.text, "html.parser")
paramTags = dict([
(t["name"], t["value"])
for t in soup.find("div", {"class": "tableauPlaceholder"}).findAll("param")
])

url = f'{paramTags["host_url"]}trusted/{paramTags["ticket"]}{paramTags["site_root"]}/views/{paramTags["name"]}'

ts = TS()
ts.loads(url)
dashboard = ts.getWorkbook()

for t in dashboard.worksheets:
# show worksheet name
print(f"WORKSHEET NAME : {t.name}")
# show dataframe for this worksheet
print(t.data)

Try this on repl.it


原帖

这有点复杂,因为有以下组合:

  • 有 tsconfig textarea 的画面“配置页面”不是原始页面的一部分。 url 是根据一些 param html 标签动态构建的
  • 它在 cookie 中使用交叉伪造 token ,但为了获取该 cookie,您需要调用特定的 api,其 url 是根据一些 param html 标记动态构建的
  • 从 tsconfig 参数,我们可以构建数据 url,正如您在其他 stackoverflow 帖子中发现的那样,例如 this , thisthis

流程如下:

  • 调用 GET https://idph.illinois.gov/OpioidDataDashboard/,在类 tableauPlaceholder 的 div 下抓取 param 标签>/li>

从那里主机是:https://interactive.data.illinois.gov

  • 根据之前的 param 标签,构建如下所示的“ session URL”:

    GET /trusted/{ticket}/t/DPH/views/opioidTDWEB_prod/MortalityandMorbidity

上面的url将只用于存储cookies(包括cookies中的xsrf token)

  • 从以前的 param 标签,构建如下所示的“配置 URL”:

    GET /t/DPH/views/opioidTDWEB_prod/MortalityandMorbidity

提取id为tsConfigContainer的textarea并从中解析json

  • 从上面提取的 json 构建“数据 url”,url 如下所示:

    POST /vizql/t/DPH/w/opioidTDWEB_prod/v/MortalityandMorbidity/bootstrapSession/sessions/{session_id}

然后你有一个 json 响应,它前面有一些字符串以防止 json hijacking .需要regex提取然后解析庞大的json数据

所有需要的 url 如下:

GET https://idph.illinois.gov/OpioidDataDashboard/
GET https://interactive.data.illinois.gov/trusted/yIm7jkXyRQuH9Ff1oPvz_w==:790xMcZuwmnvijXHg6ymRTrU/t/DPH/views/opioidTDWEB_prod/MortalityandMorbidity
GET https://interactive.data.illinois.gov/t/DPH/views/opioidTDWEB_prod/MortalityandMorbidity
POST https://interactive.data.illinois.gov/vizql/t/DPH/w/opioidTDWEB_prod/v/MortalityandMorbidity/bootstrapSession/sessions/2A3E3BA96A6C4E65B36AEDB4A536D09F-1:0

完整代码:

import requests
from bs4 import BeautifulSoup
import json
import re

s = requests.Session()

init_url = "https://idph.illinois.gov/OpioidDataDashboard/"
print(f"GET {init_url}")
r = s.get(init_url)
soup = BeautifulSoup(r.text, "html.parser")
paramTags = dict([
(t["name"], t["value"])
for t in soup.find("div", {"class":"tableauPlaceholder"}).findAll("param")
])

# get xsrf cookie
session_url = f'{paramTags["host_url"]}trusted/{paramTags["ticket"]}{paramTags["site_root"]}/views/{paramTags["name"]}'
print(f"GET {session_url}")
r = s.get(session_url)

config_url = f'{paramTags["host_url"][:-1]}{paramTags["site_root"]}/views/{paramTags["name"]}'
print(f"GET {config_url}")
r = s.get(config_url,
params = {
":embed": "y",
":showVizHome": "no",
":host_url": "https://interactive.data.illinois.gov/",
":embed_code_version": 2,
":tabs": "yes",
":toolbar": "no",
":showShareOptions": "false",
":display_spinner": "no",
":loadOrderID": 0,
})
soup = BeautifulSoup(r.text, "html.parser")
tableauData = json.loads(soup.find("textarea",{"id": "tsConfigContainer"}).text)

dataUrl = f'{paramTags["host_url"][:-1]}{tableauData["vizql_root"]}/bootstrapSession/sessions/{tableauData["sessionid"]}'
print(f"POST {dataUrl}")
r = s.post(dataUrl, data= {
"sheet_id": tableauData["sheetId"],
})
dataReg = re.search('\d+;({.*})\d+;({.*})', r.text, re.MULTILINE)
info = json.loads(dataReg.group(1))
data = json.loads(dataReg.group(2))

print(data["secondaryInfo"]["presModelMap"]["dataDictionary"]["presModelHolder"]["genDataDictionaryPresModel"]["dataSegments"]["0"]["dataColumns"])

Try this on repl.it

关于python - 从 Tableau map 中抓取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63025296/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com