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

时间:2017-04-21 17:44:00

标签: python google-chrome google-chrome-devtools headless headless-browser

我正在使用Chromium的无头网络浏览器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,但我得到了一个用于多个requestIds的消息。如何修改我的脚本,以便在页面完全加载时终止,我可以逃避循环?

3 个答案:

答案 0 :(得分:4)

事实证明我本应该通过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)

答案 1 :(得分:0)

当您连接到远程服务器时,我不确定websockets是如何工作的,但是在套接字上接收数据时。所以要接收整个响应,你应该在一个循环中执行它,直到你得到一个小于块长度的块,我的意思是当你的块是4096bytes然后最后一个块将是0或x<4096 x是接收块的长度。因此,根据该信息,您知道所有数据都是从远程服务器接收的。请阅读插座。

答案 2 :(得分:0)

在任何一般意义上,你都不能......不是真的。

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

如你所见,你得到了很多loadingFinished事件,但是你怎么知道它是“最后一个”呢?您需要了解该页面。例如,您是否可以通过观察页面将针对每个特定DOM元素类发出一个请求,还是基于javascript变量或XHR响应来确定将发送多少请求?如果是这样,那么一旦获得 n 响应,就可以停止。或者,最后一个请求(目标或有效负载)或最后一个响应(例如,零长度,包含文本“last”,^ D或^ Z)是否有特殊之处。

此外,如果页面正在轮询服务器(通常使用套接字),那么“完成加载”甚至意味着什么?

onload更新

如果您正在寻找onload事件,那么您不需要做任何特别的事情。 driver.get(<url>)阻止直到那时。

  

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