从Tableau画布动态加载的页面中刮取与冠状病毒相关的数据(我认为...)

时间:2020-04-06 14:40:53

标签: python selenium web-scraping screen-scraping

我很乐意发现这个问题是重复的,但如果是这样-我找不到该问与答。

New York State Department of Health中有一个神秘的页面,其中包含“按县和年龄组分类的死亡人数”。顾名思义,它包含两个表(“按县” /“按年龄组”)。

出于某些奇怪的原因,此页面上的数据是超级安全的。无法选择,无法保存页面,也无法打印。数据不在页面源上。我还尝试了(但失败了)检查xhr数据调用。

显然,请求和beautifulsoup无法处理它。我尝试了常见的Selenium咒语(因此,除非另行通知,否则我不会用“我尝试过的内容”摘要来弄乱这个问题)。

期望输出:这两个表中的数据,采用任何可能的格式。

我唯一能想到的就是拍摄屏幕截图并尝试对图像进行ocr ...

我不知道是硒,Tableau,纽约州卫生局还是我本人,但是现在该召唤重型火炮了……

2 个答案:

答案 0 :(得分:3)

让我为您解释一下情况:

  1. 网站正在该参数session后面生成一个X-Session-Id id,一旦您访问main page页面索引,该参数就会动态生成。所以我通过GET请求将其调用,而我是从headers响应中提取的。
  2. 我发现了一个POST请求,该请求是在您击中所需的url之前自动生成的,该请求实际上使用的是我们之前收集的session ID。这是https://covid19tracker.health.ny.gov/vizql/w/NYS-COVID19-Tracker/v/NYSDOHCOVID-19Tracker-Fatalities/clear/sessions/{session id}

  3. 现在我们可以将您的目标称为https://covid19tracker.health.ny.gov/views/NYS-COVID19-Tracker/NYSDOHCOVID-19Tracker-Fatalities?%3Aembed=yes&%3Atoolbar=no&%3Atabs=n

  4. 现在我注意到向XHR back-end发出了另一个API请求。但是在进行调用之前,我们将解析HTML内容以拾取time对象,该对象负责从freshly生成数据API,因此我们将获得即时数据(实际上像实时聊天一样考虑)。在我们的情况下,它位于lastUpdatedAt

  5. 中的HTML后面
  6. 我也注意到,我们将需要提取从先前的X-Session-Id请求中生成的最新POST

  7. 现在,我们将使用拾起的sessionhttps://covid19tracker.health.ny.gov/vizql/w/NYS-COVID19-Tracker/v/NYSDOHCOVID-19Tracker-Fatalities/bootstrapSession/sessions/{session}

  8. 拨打电话

现在我们已收到完整回复。您可以解析它或做任何您想做的事情。

import requests
import re


data = {
    'worksheetPortSize': '{"w":1536,"h":1250}',
    'dashboardPortSize': '{"w":1536,"h":1250}',
    'clientDimension': '{"w":1536,"h":349}',
    'renderMapsClientSide': 'true',
    'isBrowserRendering': 'true',
    'browserRenderingThreshold': '100',
    'formatDataValueLocally': 'false',
    'clientNum': '',
    'navType': 'Reload',
    'navSrc': 'Top',
    'devicePixelRatio': '2.5',
    'clientRenderPixelLimit': '25000000',
    'allowAutogenWorksheetPhoneLayouts': 'true',
    'sheet_id': 'NYSDOH%20COVID-19%20Tracker%20-%20Fatalities',
    'showParams': '{"checkpoint":false,"refresh":false,"refreshUnmodified":false}',
    'filterTileSize': '200',
    'locale': 'en_US',
    'language': 'en',
    'verboseMode': 'false',
    ':session_feature_flags': '{}',
    'keychain_version': '1'
}


def main(url):
    with requests.Session() as req:
        r = req.post(url)
        sid = r.headers.get("X-Session-Id")

        r = req.post(
            f"https://covid19tracker.health.ny.gov/vizql/w/NYS-COVID19-Tracker/v/NYSDOHCOVID-19Tracker-Fatalities/clear/sessions/{sid}")

        r = req.get(
            "https://covid19tracker.health.ny.gov/views/NYS-COVID19-Tracker/NYSDOHCOVID-19Tracker-Fatalities?%3Aembed=yes&%3Atoolbar=no&%3Atabs=n")

        match = re.search(r"lastUpdatedAt.+?(\d+),", r.text).group(1)

        time = '{"featureFlags":"{\"MetricsAuthoringBeta\":false}","isAuthoring":false,"isOfflineMode":false,"lastUpdatedAt":xxx,"workbookId":9}'.replace(
            'xxx', f"{match}")

        data['stickySessionKey'] = time
        nid = r.headers.get("X-Session-Id")

        r = req.post(
            f"https://covid19tracker.health.ny.gov/vizql/w/NYS-COVID19-Tracker/v/NYSDOHCOVID-19Tracker-Fatalities/bootstrapSession/sessions/{nid}", data=data)

        print(r.text)


main("https://covid19tracker.health.ny.gov")

答案 1 :(得分:0)

我制作了一个 tableau scraper library 来从 Tableau 工作表中提取数据

您可以使用以下代码获取每个工作表的 pandas 数据框中的所有数据:

from tableauscraper import TableauScraper as TS

url = "https://covid19tracker.health.ny.gov/views/NYS-COVID19-Tracker/NYSDOHCOVID-19Tracker-Fatalities"

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