我很乐意发现这个问题是重复的,但如果是这样,我找不到该问答。
New York State Department of Health中有一个神秘的页面,其中包含“按县和年龄组分类的灾难”。顾名思义,它包含两个表(“按县” /“按年龄组”)。
出于某些奇怪的原因,此页面上的数据是超级安全的。无法选择,无法保存页面,也无法打印。数据不在页面源上。我也尝试过(但失败了)检查xhr数据的调用。
显然,请求和beautifulsoup无法处理它。我尝试了常见的Selenium咒语(因此,除非另行通知,否则我不会用“我尝试过的内容”摘要来弄乱这个问题)。
期望输出:这两个表中的数据,采用任何可能的格式。
我唯一能想到的就是截取屏幕截图并尝试对图像进行ocr ...
我不知道是硒,Tableau,NYS卫生部还是我本人,但现在该召唤重型火炮了……
让我为您解释情况:
session
后面生成一个X-Session-Id
ID,一旦您访问main page页面索引,该参数就会动态生成。所以我通过GET
请求将其调用,而我是从headers
响应中选择的。我想出了一个POST
请求,该请求在您击中所需的url
之前会自动生成,该请求实际上是使用我们之前收集的session
ID。这是https://covid19tracker.health.ny.gov/vizql/w/NYS-COVID19-Tracker/v/NYSDOHCOVID-19Tracker-Fatalities/clear/sessions/{session id}
现在我们可以将您的目标称为https://covid19tracker.health.ny.gov/views/NYS-COVID19-Tracker/NYSDOHCOVID-19Tracker-Fatalities?%3Aembed=yes&%3Atoolbar=no&%3Atabs=n
。
现在,我注意到对XHR
back-end
的另一个API
请求。但是在进行调用之前,我们将解析HTML
内容以拾取time
对象,该对象负责从freshly
生成数据API
,因此我们将获得即时数据(像实时聊天)。在我们的情况下,它位于lastUpdatedAt
HTML
后面我也注意到,我们将需要提取从先前的X-Session-Id
请求中生成的最近的POST
。
[现在,我们将使用我们接听的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")