1 回答

TA貢獻(xiàn)1827條經(jīng)驗(yàn) 獲得超8個(gè)贊
編輯
我制作了一個(gè)tableau scraper 庫來將工作表數(shù)據(jù)提取到 pandas 數(shù)據(jù)框中。
代碼更簡單,但在您的情況下,您仍然需要使用 xsrf 令牌構(gòu)建 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)
原帖
這有點(diǎn)復(fù)雜,因?yàn)橛幸韵陆M合:
有 tsconfig textarea 的畫面“配置頁面”不是原始頁面的一部分。url 是從一些
param
html 標(biāo)簽動態(tài)構(gòu)建的它在 cookie 中使用交叉?zhèn)卧炝钆?,但為了獲取該 cookie,您需要調(diào)用特定的 api,其 url 是從某些
param
html 標(biāo)記動態(tài)構(gòu)建的從 tsconfig 參數(shù),我們可以構(gòu)建數(shù)據(jù) url,正如您在其他 stackoverflow 帖子中發(fā)現(xiàn)的那樣,例如this,this和this
流程如下:
call
GET https://idph.illinois.gov/OpioidDataDashboard/
,param
用class抓取div下的標(biāo)簽tableauPlaceholder
從那里主機(jī)是: https: //interactive.data.illinois.gov
從前面的
param
標(biāo)簽中,構(gòu)建如下所示的“會話 URL”:GET /trusted/{ticket}/t/DPH/views/opioidTDWEB_prod/MortalityandMorbidity
上面的url將只用于存儲cookies(包括cookies中的xsrf token)
從前面的
param
標(biāo)簽中,構(gòu)建如下所示的“配置 URL”:GET /t/DPH/views/opioidTDWEB_prod/MortalityandMorbidity
使用 id 提取 textareatsConfigContainer
并從中解析 json
從上面提取的 json 構(gòu)建“數(shù)據(jù) url”,url 如下所示:
POST /vizql/t/DPH/w/opioidTDWEB_prod/v/MortalityandMorbidity/bootstrapSession/sessions/{session_id}
然后你有一個(gè) json 響應(yīng),它前面有一些字符串以防止json 劫持。你需要正則表達(dá)式來提取它然后解析巨大的json數(shù)據(jù)
所有需要的 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"])
添加回答
舉報(bào)