Python 如何判断页面已完成加载?

Python 如何判断页面已完成加载?,python,google-chrome,google-chrome-devtools,headless,headless-browser,Python,Google Chrome,Google Chrome Devtools,Headless,Headless Browser,我正在玩Chromium的无头web浏览器API。基于chrome_remote_shell源代码,我提出了以下代码: #!/usr/bin/env python import json import requests import pprint import websocket tablist = json.loads(requests.get("http://%s:%s/json" % ("localhost", 9222)).text) print(tablist) wsurl = t

我正在玩Chromium的无头web浏览器API。基于chrome_remote_shell源代码,我提出了以下代码:

#!/usr/bin/env python

import json
import requests
import pprint
import websocket

tablist = json.loads(requests.get("http://%s:%s/json" % ("localhost", 9222)).text)
print(tablist)
wsurl = tablist[0]['webSocketDebuggerUrl']
conn = websocket.create_connection(wsurl)
navcom = json.dumps({"id":0, "method":"Network.enable"})
conn.send(navcom)
navcom = json.dumps({"id":1, "method":"Page.navigate", "params":{"url":"https://news.ycombinator.com/"}})
conn.send(navcom)

while True:
    packet = json.loads(conn.recv())
    if 'method' in packet:
        print(packet['method'])
    else:
        print(packet)
以下是示例输出:

[{u'description': u'', u'title': u'Hacker News', u'url': u'https://news.ycombinator.com/', u'webSocketDebuggerUrl': u'ws://localhost:9222/devtools/page/7d03a57d-77a9-4ceb-b645-3b85461de5be', u'type': u'page', u'id': u'7d03a57d-77a9-4ceb-b645-3b85461de5be', u'devtoolsFrontendUrl': u'/devtools/inspector.html?ws=localhost:9222/devtools/page/7d03a57d-77a9-4ceb-b645-3b85461de5be'}]
{u'id': 0, u'result': {}}
Network.requestWillBeSent
{u'id': 1, u'result': {u'frameId': u'21045.1'}}
Network.responseReceived
Network.dataReceived
Network.dataReceived
Network.loadingFinished
Network.requestWillBeSent
Network.requestWillBeSent
Network.requestServedFromCache
Network.responseReceived
Network.dataReceived
Network.loadingFinished
Network.requestWillBeSent
Network.requestServedFromCache
Network.responseReceived
Network.dataReceived
Network.loadingFinished
Network.requestWillBeSent
Network.requestServedFromCache
Network.responseReceived
Network.dataReceived
Network.loadingFinished
Network.responseReceived
Network.dataReceived
Network.loadingFinished
Network.requestWillBeSent
Network.requestServedFromCache
Network.responseReceived
Network.dataReceived
Network.loadingFinished

我注意到我收到了一个很长的消息流,最后一个消息流是Network.loadingFinished,但是我得到了一个用于多个requestid的消息流。如何修改我的脚本,使其在页面完全加载时终止,我可以跳出循环?

我不确定WebSocket如何工作,但在连接到远程服务器时,您会收到成片的数据。所以要接收整个响应,你应该在一个循环中这样做,直到得到一个小于块长度的块,我的意思是当你的块是4096字节时,最后一个块将是0或
x,在任何一般意义上,你不能。。。不是真的

现在,对于动态网页,您需要了解页面实际在做什么,并查找DOM元素的特定事件/存在或其他线索

如您所见,您正在加载许多已完成的事件,但您如何知道这是“最后”一个?你需要理解这一页。例如,您可以通过观察页面将对每个特定DOM元素类发出一个请求,或者基于javascript变量或XHR响应来确定将发送多少个请求吗?如果是这样,那么一旦得到n个响应,就可以停止。或者,最后一个请求(目标或负载)或最后一个响应(例如,长度为零,包含文本“last”、^D或^Z)是否有特殊之处

此外,如果页面正在轮询服务器(通常带有套接字),“完成加载”是什么意思

为在线加载更新

如果您要查找的是
onload
事件,则无需执行任何特殊操作<代码>驱动程序.get()
在此之前阻止

WebDriver将等待页面完全加载(即触发
onload
事件),然后再将控件返回到测试或脚本。值得注意的是,如果您的页面在加载时使用了大量AJAX,那么WebDriver可能不知道它何时已完全加载。如果需要确保这些页面已完全加载,则可以使用等待


事实证明,我还应该通过page.enable订阅页面事件:

#!/usr/bin/env python

import json
import requests
import pprint
import websocket
import sys

tablist = json.loads(requests.get("http://%s:%s/json" % ("localhost", 9222)).text)
print(tablist)
wsurl = tablist[0]['webSocketDebuggerUrl']
conn = websocket.create_connection(wsurl)
navcom = json.dumps({"id":0, "method":"Network.enable"})
conn.send(navcom)
navcom = json.dumps({"id":1, "method":"Page.enable"})
conn.send(navcom)
navcom = json.dumps({"id":2, "method":"Page.navigate", "params":{"url":sys.argv[1]}})
conn.send(navcom)

while True:
    s = conn.recv()
    packet = json.loads(s)
    if packet.get('method') == 'Page.loadEventFired':
        break
    print(s)

对不起,但事实并非如此。我说的是一个无头浏览器的API,它给了我一个信号,告诉我它是如何发出大量请求的。我的问题是如何确定所有请求都已收到。然后我不确定你想要什么。如果可以的话,我的第一个想法是设置一个超时。你能指出你在说代码中的哪一行吗?问题是关于DevTools接口的。我告诉远程浏览器启用网络调试并导航到某个URL。我还需要告诉它,让我知道它何时会触发“已加载”事件,这样我就可以捕获该事件并逃离循环。抱歉,我无法帮助你,因为我缺乏知识:/pbuck,我也在考虑同样的问题。我基本上想抓住普通浏览器隐藏旋转的“加载”符号的时刻,表示页面加载结束。Chrome是否以某种方式公开了它?除了标准的
onload
事件?规范中说:“当文档加载完成时在窗口触发”,Mozilla说,“在文档加载过程结束时触发。此时,文档中的所有对象都在DOM中,所有图像、脚本、链接和子帧都已加载完毕。”是的,问题是如何从headless chrome获取此事件。
onload
本质上是内置在
驱动程序中的。get()
(我已经用此信息更新了答案)。但这可能还不足以满足您的需要。请记住,我指的是webtools API,而不是更高级别的selenium的WebDriver。不管怎样,我找到了一个答案:你能解释一下这里发生了什么吗?网袋?为什么?@Fandango68这是——或者至少是因为我没有检查当前状态——在无头模式下与Chrome通信的标准方式。