Очистка данных, связанных с коронавирусом, со страницы, которая динамически загружается с холста таблицы (я думаю ...) - PullRequest
0 голосов
/ 06 апреля 2020

Я буду более чем счастлив узнать, что этот вопрос является дубликатом, но если это так - я не могу найти, что вопросы и ответы.

Есть таинственная страница из Департамента штата Нью-Йорк. of Health с указанием «Смертность по округам и возрастным группам». Как видно из названия, он содержит две таблицы («По округам» / «По возрастным группам»).

По какой-то странной причине данные на этой странице сверхзащищены. Он не может быть выбран, страница не может быть сохранена и не может быть напечатана. Данные не на странице источника. Я также пытался (и не смог) проверить вызовы xhr для данных.

Очевидно, что запросы и BeautifulSoup не могут справиться с этим. Я попробовал обычные заклинания Selenium (поэтому, если мне не скажут иначе, я не буду загромождать этот вопрос фрагментами «что я пробовал»).

Желаемый вывод: данные из этих двух таблиц в любом возможном формате.

Единственное, о чем я могу думать, это сделать снимок экрана и попытаться получить изображение ...

Я не знаю, Селен ли, Табло, Департамент здоровья штата Нью-Йорк или только я, но пришло время вызвать тяжелую артиллерию ...

1 Ответ

2 голосов
/ 06 апреля 2020

Позвольте мне объяснить вам сценарий:

  1. Веб-сайт генерирует идентификатор session за этим параметром X-Session-Id, который генерируется динамически после посещения главной страницы индекс страницы. Поэтому я позвонил ему по запросу GET и взял его из ответа headers.
  2. Я выяснил запрос POST, который автоматически генерируется до того, как вы нажмете требуемый url, который фактически использует идентификатор session, который мы собрали ранее. вот оно 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 внутри HTML

  5. Я также заметил, что нам нужно будет взять последние X-Session-Id, сгенерированные из нашего предыдущего POST запроса.

  6. Теперь мы сделаем звонок, используя наш набранный session на https://covid19tracker.health.ny.gov/vizql/w/NYS-COVID19-Tracker/v/NYSDOHCOVID-19Tracker-Fatalities/bootstrapSession/sessions/{session}

Теперь мы получили полный ответ. Вы можете разобрать это или сделать что хотите.

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")
...