我正在尝试从网站上抓取数据。我对某些日期时间感兴趣,但有两个问题:
它们并不以原始 HTML 形式出现在网站上,而是稍后加载。
加载后,它们以相对且不精确的人类可读形式显示。因此 7.3.2023 14:22 变为“七天内”。因此,仅仅等待页面完成加载也是行不通的。
当我在 Chrome 开发工具中打开“网络”面板时,我可以查明以正确形式发送数据的请求。
有没有办法使用无头 Chrome 或其他软件以编程方式访问这些请求的内容?最好的情况是使用 PHP 生态系统中的工具,但我想使用 javascript 或其他东西也是可能的,只是不方便。
不,我无法直接访问请求的 URL。该网页发送了大量我无法合理复制的数据,更不用说肯定会有安全措施阻止来自原始站点以外的其他来源的访问。
好吧,这是一段相当漫长的旅程,但我成功地完成了它。
该解决方案使用了这个优秀的库:https://github.com/jakubkulhan/chrome-devtools-protocol
这是我的代码:
$ctx = Context::withTimeout(Context::background(), 10);
$launcher = new Launcher();
$launcher->setExecutable('chromium');
$instance = $launcher->launch($ctx, '--no-sandbox', '--remote-allow-origins=*');
try {
$session = $instance->createSession($ctx);
try {
$requestIds = [];
$session->page()->enable($ctx);
$session->network()->enable($ctx, EnableRequest::builder()->build());
$session->network()->addResponseReceivedListener(function (ResponseReceivedEvent $ev) use (&$requestIds) {
$requestIds[] = $ev->requestId;
});
$session->page()->navigate(
$ctx,
NavigateRequest::builder()
->setUrl($url)
->build()
);
$session->page()->awaitLoadEventFired($ctx);
foreach ($requestIds as $id) {
$responseBody = $session->network()->getResponseBody($ctx, GetResponseBodyRequest::builder()->setRequestId($id)->build());
$responseText = $responseBody->body;
}
} finally {
$session->close();
}
} finally {
$instance->close();
}