Chrome:性能数据 API

Posted

技术标签:

【中文标题】Chrome:性能数据 API【英文标题】:Chrome: API for performance data 【发布时间】:2018-08-02 22:54:58 【问题描述】:

问题描述

在使用 Selenium 时,如何从浏览器控制台或使用 Chrome 驱动程序方法访问 Chrome 性能工具中的数据?

特别是,我对获得页面加载时间感兴趣。在上面的图表中,我可以看到最后一个元素是在 1700-1800 毫秒 标记附近加载的。底部的事件日志显示,最后一个元素在页面重新加载后的 1720.1 毫秒处开始加载(并在几毫秒内完成)。

到目前为止我尝试了什么

我尝试像这样使用Performance Timing interface:

console.log(performance.timing.loadEventEnd - 
performance.timing.navigationStart)
357

但我想它可以衡量其他一些性能。 loadEventEndnavigationStarttiming的属性中是最极端的,相差只有357(ms)。

我也尝试过像这样使用 Selenium 记录性能信息(从 here 获取一些想法并用 Python 重写):

import time
import json
import copy
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.chrome.options import Options

caps = copy.deepcopy(DesiredCapabilities.CHROME)
caps['loggingPrefs'] = 'performance': 'ALL'
chromedriver_options = Options()
chromedriver_options.add_argument("--headless")
chromedriver_options.add_argument("--window-size=1920,1080")
chromedriver_options.add_argument("--log-level=3") # suppress selenium logging to stdout
driver = webdriver.Chrome(chrome_options=chromedriver_options, executable_path='chromedriver.exe', desired_capabilities=caps)
driver.set_window_position(0, 0)
driver.implicitly_wait(8) # set timeout to 8 seconds
driver.get(my_url)
time.sleep(5) # wait for page to load for the first time
_ = driver.get_log('performance') # discard all previous logs
driver.refresh()
time.sleep(5) # make sure page loaded completely before writing log
with open('logs.txt', 'a') as f:
    for entry in driver.get_log('performance'):
        f.write(str(entry) + '\n')
driver.close()

生成的日志包含调用Page.frameStartedLoadingPage.frameStoppedLoading 方法及其时间戳的条目,我想在刷新日志并调用@ 后测量第一个Page.frameStartedLoading 和最后一个Page.frameStoppedLoading 之间的时间987654334@。

不幸的是,生成的日志文件没有多大意义。性能记录不会停止(我认为它应该停止,因为网页在某个时候加载并且性能方面没有发生任何事情)。如果我在刷新后调用time.sleep(5),我会得到一些日志,其中每个Page.frameStartedLoadingPage.frameStoppedLoading 调用5 次。如果我打电话给time.sleep(7),我将分别接到Page.frameStartedLoadingPage.frameStoppedLoading 的7 个电话。最后一个Page.frameStoppedLoading 和第一个Page.frameStartedLoading 的时间戳之间的差异在最后一种情况下约为7 秒,这显然不是我想要的。

任何人都有捕获此页面加载性能信息的经验?

【问题讨论】:

【参考方案1】:

如果您想使用 ChromeDriverChrome 开发者工具 访问 性能数据,您可以使用以下代码块:

Selenium-Python 片段

from selenium import webdriver

driver=webdriver.Chrome(executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe')
driver.get("http://www.google.com")
performance_data = driver.execute_script("return window.performance.getEntries();")
print (performance_data)

提取的参数如下:

connectEnd                 Time when server connection is finished.
connectStart               Time just before server connection begins.
domComplete                Time just before document readiness completes.
domContentLoadedEventEnd   Time after DOMContentLoaded event completes.
domContentLoadedEventStart Time just before DOMContentLoaded starts.
domInteractive             Time just before readiness set to interactive.
domLoading                 Time just before readiness set to loading.
domainLookupEnd            Time after domain name lookup.
domainLookupStart          Time just before domain name lookup.
fetchStart                 Time when the resource starts being fetched.
loadEventEnd               Time when the load event is complete.
loadEventStart             Time just before the load event is fired.
navigationStart            Time after the previous document begins unload.
redirectCount              Number of redirects since the last non-redirect.
redirectEnd                Time after last redirect response ends.
redirectStart              Time of fetch that initiated a redirect.
requestStart               Time just before a server request.
responseEnd                Time after the end of a response or connection.
responseStart              Time just before the start of a response.
timing                     Reference to a performance timing object.
navigation                 Reference to performance navigation object.
performance                Reference to performance object for a window.
type                       Type of the last non-redirect navigation event.
unloadEventEnd             Time after the previous document is unloaded.
unloadEventStart           Time just before the unload event is fired.

控制台输出:

Page Title is : Google
['connectEnd': 2725.146514015987, 'connectStart': 1503.1734234800108, 'decodedBodySize': 204837, 'domComplete': 7603.4821342458235, 'domContentLoadedEventEnd': 4588.4400826362535, 'domContentLoadedEventStart': 4576.987229310746, 'domInteractive': 4559.208601432438, 'domainLookupEnd': 1503.1734234800108, 'domainLookupStart': 1503.1734234800108, 'duration': 7623.300733238722, 'encodedBodySize': 61075, 'entryType': 'navigation', 'fetchStart': 1503.1734234800108, 'initiatorType': 'navigation', 'loadEventEnd': 7623.300733238722, 'loadEventStart': 7603.516579526861, 'name': 'document', 'nextHopProtocol': 'h2', 'redirectCount': 0, 'redirectEnd': 1501.686197816412, 'redirectStart': 22.057947498907886, 'requestStart': 2725.729247123413, 'responseEnd': 3624.7713441197043, 'responseStart': 3349.3679493549, 'secureConnectionStart': 2049.7916668355165, 'startTime': 0, 'transferSize': 61926, 'type': 'navigate', 'unloadEventEnd': 0, 'unloadEventStart': 0, 'workerStart': 0, 'connectEnd': 3388.3040845619494, 'connectStart': 3388.3040845619494, 'decodedBodySize': 1730, 'domainLookupEnd': 3388.3040845619494, 'domainLookupStart': 3388.3040845619494, 'duration': 237.3373068328902, 'encodedBodySize': 1730, 'entryType': 'resource', 'fetchStart': 3388.3040845619494, 'initiatorType': 'img', 'name': 'https://www.google.co.in/logos/doodles/2018/doodle-snow-games-day-15-5907794870927360.4-s.png', 'nextHopProtocol': 'h2', 'redirectEnd': 0, 'redirectStart': 0, 'requestStart': 3439.3892730100556, 'responseEnd': 3625.6413913948395, 'responseStart': 3625.271003314041, 'secureConnectionStart': 0, 'startTime': 3388.3040845619494, 'transferSize': 2242, 'workerStart': 0, 'connectEnd': 0, 'connectStart': 0, 'decodedBodySize': 0, 'domainLookupEnd': 0, 'domainLookupStart': 0, 'duration': 230.20794413542762, 'encodedBodySize': 0, 'entryType': 'resource', 'fetchStart': 3425.689371645131, 'initiatorType': 'css', 'name': 'https://ssl.gstatic.com/gb/images/i1_1967ca6a.png', 'nextHopProtocol': 'h2', 'redirectEnd': 0, 'redirectStart': 0, 'requestStart': 0, 'responseEnd': 3655.8973157805594, 'responseStart': 0, 'secureConnectionStart': 0, 'startTime': 3425.689371645131, 'transferSize': 0, 'workerStart': 0, 'connectEnd': 0, 'connectStart': 0, 'decodedBodySize': 0, 'domainLookupEnd': 0, 'domainLookupStart': 0, 'duration': 969.9734406621285, 'encodedBodySize': 0, 'entryType': 'resource', 'fetchStart': 3502.3913129811713, 'initiatorType': 'script', 'name': 'https://www.gstatic.com/external_hosted/createjs/createjs-2015.11.26.min.js', 'nextHopProtocol': 'h2', 'redirectEnd': 0, 'redirectStart': 0, 'requestStart': 0, 'responseEnd': 4472.364753643298, 'responseStart': 0, 'secureConnectionStart': 0, 'startTime': 3502.3913129811713, 'transferSize': 0, 'workerStart': 0, 'connectEnd': 3520.930168473896, 'connectStart': 3520.930168473896, 'decodedBodySize': 12232, 'domainLookupEnd': 3520.930168473896, 'domainLookupStart': 3520.930168473896, 'duration': 134.0411771046674, 'encodedBodySize': 12232, 'entryType': 'resource', 'fetchStart': 3520.930168473896, 'initiatorType': 'css', 'name': 'https://www.google.co.in/logos/2018/snowgames_bobsled/cta.png', 'nextHopProtocol': 'h2', 'redirectEnd': 0, 'redirectStart': 0, 'requestStart': 3525.3821197382813, 'responseEnd': 3654.971345578564, 'responseStart': 3625.955856548778, 'secureConnectionStart': 0, 'startTime': 3520.930168473896, 'transferSize': 12745, 'workerStart': 0, 'connectEnd': 4527.024551785848, 'connectStart': 4527.024551785848, 'decodedBodySize': 842405, 'domainLookupEnd': 4527.024551785848, 'domainLookupStart': 4527.024551785848, 'duration': 2632.3253968704244, 'encodedBodySize': 265174, 'entryType': 'resource', 'fetchStart': 4527.024551785848, 'initiatorType': 'script', 'name': 'https://www.google.co.in/logos/2018/snowgames_bobsled/snowgames_bobsled18.2.js', 'nextHopProtocol': 'h2', 'redirectEnd': 0, 'redirectStart': 0, 'requestStart': 4528.843667863202, 'responseEnd': 7159.3499486562705, 'responseStart': 4946.163646693538, 'secureConnectionStart': 0, 'startTime': 4527.024551785848, 'transferSize': 265741, 'workerStart': 0, 'connectEnd': 4558.896162471504, 'connectStart': 4558.896162471504, 'decodedBodySize': 0, 'domainLookupEnd': 4558.896162471504, 'domainLookupStart': 4558.896162471504, 'duration': 1005.3106518587082, 'encodedBodySize': 0, 'entryType': 'resource', 'fetchStart': 4558.896162471504, 'initiatorType': 'other', 'name': 'https://www.google.co.in/gen_204?s=webaft&atyp=csi&ei=N6mPWp6mC8H00ASJtoL4Ag&rt=wsrt.3384,aft.1175,prt.1175', 'nextHopProtocol': 'h2', 'redirectEnd': 0, 'redirectStart': 0, 'requestStart': 4560.575876470308, 'responseEnd': 5564.206814330209, 'responseStart': 5564.1444075857435, 'secureConnectionStart': 0, 'startTime': 4558.896162471504, 'transferSize': 358, 'workerStart': 0, 'connectEnd': 4576.353841378264, 'connectStart': 4576.353841378264, 'decodedBodySize': 417606, 'domainLookupEnd': 4576.353841378264, 'domainLookupStart': 4576.353841378264, 'duration': 1903.6302084304214, 'encodedBodySize': 144417, 'entryType': 'resource', 'fetchStart': 4576.353841378264, 'initiatorType': 'script', 'name': 'https://www.google.co.in/xjs/_/js/k=xjs.s.en.smQ6-n1iGHA.O/m=sx,sb,cdos,cr,elog,hsm,jsa,r,d,csi/am=wCLkeMEAyP8JgogEKwgsQIpgGBA/rt=j/d=1/t=zcms/rs=ACT90oH8FZej9QmzW2qBqlOOQ7DASmnKAA', 'nextHopProtocol': 'h2', 'redirectEnd': 0, 'redirectStart': 0, 'requestStart': 4578.110550711152, 'responseEnd': 6479.984049808687, 'responseStart': 5564.372556917789, 'secureConnectionStart': 0, 'startTime': 4576.353841378264, 'transferSize': 144999, 'workerStart': 0, 'connectEnd': 0, 'connectStart': 0, 'decodedBodySize': 0, 'domainLookupEnd': 0, 'domainLookupStart': 0, 'duration': 574.9679253647753, 'encodedBodySize': 0, 'entryType': 'resource', 'fetchStart': 4791.30009458269, 'initiatorType': 'script', 'name': 'https://www.gstatic.com/og/_/js/k=og.og2.en_US.SpCLDXmWlPM.O/rt=j/m=def/exm=in,fot/d=1/ed=1/rs=AA2YrTtMoJJMGQfOfYZyZ7reaiaiva99OQ', 'nextHopProtocol': 'h2', 'redirectEnd': 0, 'redirectStart': 0, 'requestStart': 0, 'responseEnd': 5366.2680199474635, 'responseStart': 0, 'secureConnectionStart': 0, 'startTime': 4791.30009458269, 'transferSize': 0, 'workerStart': 0, 'connectEnd': 0, 'connectStart': 0, 'decodedBodySize': 0, 'domainLookupEnd': 0, 'domainLookupStart': 0, 'duration': 1586.0147296126488, 'encodedBodySize': 0, 'entryType': 'resource', 'fetchStart': 5417.5655534222005, 'initiatorType': 'script', 'name': 'https://apis.google.com/_/scs/abc-static/_/js/k=gapi.gapi.en.29tAKSAI8cc.O/m=gapi_iframes,googleapis_client,plusone/rt=j/sv=1/d=1/ed=1/am=IA/rs=AHpOoo82FxkTgGRAoVn-fgFU3zdQ5QIqEw/cb=gapi.loaded_0', 'nextHopProtocol': 'h2', 'redirectEnd': 0, 'redirectStart': 0, 'requestStart': 0, 'responseEnd': 7003.580283034848, 'responseStart': 0, 'secureConnectionStart': 0, 'startTime': 5417.5655534222005, 'transferSize': 0, 'workerStart': 0, 'connectEnd': 6646.626267079796, 'connectStart': 6646.626267079796, 'decodedBodySize': 83168, 'domainLookupEnd': 6646.626267079796, 'domainLookupStart': 6646.626267079796, 'duration': 783.8056119062338, 'encodedBodySize': 27299, 'entryType': 'resource', 'fetchStart': 6646.626267079796, 'initiatorType': 'script', 'name': 'https://www.google.co.in/xjs/_/js/k=xjs.s.en.smQ6-n1iGHA.O/m=aa,abd,async,dvl,foot,fpe,ipv6,lu,m,mu,sf,sonic,d3l/am=wCLkeMEAyP8JgogEKwgsQIpgGBA/exm=sx,sb,cdos,cr,elog,hsm,jsa,r,d,csi/rt=j/d=1/ed=1/t=zcms/rs=ACT90oH8FZej9QmzW2qBqlOOQ7DASmnKAA?xjs=s1', 'nextHopProtocol': 'h2', 'redirectEnd': 0, 'redirectStart': 0, 'requestStart': 6648.111871788991, 'responseEnd': 7430.431878986027, 'responseStart': 7159.731278179281, 'secureConnectionStart': 0, 'startTime': 6646.626267079796, 'transferSize': 27880, 'workerStart': 0, 'connectEnd': 0, 'connectStart': 0, 'decodedBodySize': 0, 'domainLookupEnd': 0, 'domainLookupStart': 0, 'duration': 930.0310980101976, 'encodedBodySize': 0, 'entryType': 'resource', 'fetchStart': 6668.677730761095, 'initiatorType': 'img', 'name': 'https://www.google.com/textinputassistant/tia.png', 'nextHopProtocol': 'h2', 'redirectEnd': 0, 'redirectStart': 0, 'requestStart': 0, 'responseEnd': 7598.708828771292, 'responseStart': 0, 'secureConnectionStart': 0, 'startTime': 6668.677730761095, 'transferSize': 0, 'workerStart': 0, 'connectEnd': 7222.302954756732, 'connectStart': 7222.302954756732, 'decodedBodySize': 469, 'domainLookupEnd': 7222.302954756732, 'domainLookupStart': 7222.302954756732, 'duration': 208.68612730489625, 'encodedBodySize': 469, 'entryType': 'resource', 'fetchStart': 7222.302954756732, 'initiatorType': 'img', 'name': 'https://www.google.co.in/logos/2018/snowgames_bobsled/main-sprite.png', 'nextHopProtocol': 'h2', 'redirectEnd': 0, 'redirectStart': 0, 'requestStart': 7223.911346761861, 'responseEnd': 7430.989082061627, 'responseStart': 7430.7698479787905, 'secureConnectionStart': 0, 'startTime': 7222.302954756732, 'transferSize': 980, 'workerStart': 0]

从此输出中,您可以轻松地提取出您感兴趣的性能统计数据

【讨论】:

这行不通;到目前为止,我在浏览器的几个页面上对其进行了测试。在调用console.log(window.performance.getEntries()); 时,最后一个条目中的responseEnd 始终比性能图上最后一帧加载的时间至少低1000 ms(在帖子的屏幕截图中)。此外,将鼠标悬停在图表上时,我可以看到随着时间的推移页面的外观。在时间responseEnd(从最后一个条目)我可以清楚地看到页面没有完全加载。 您问了一个关于如何从 Chrome 性能工具访问数据的问题,我已为您构建了一个答案。如果您发现行为有任何偏差,您应该向 Chromium 项目 提出,以确保对社区有所帮助。 我的问题是关于从 Chrome 性能工具访问数据并从中获取客观加载时间。在我的问题中,我实际上在这里访问了性能工具:console.log(performance.timing.loadEventEnd-performance.timing.navigationStart)。我从性能工具中获得的时间没有意义,因此我问了这个问题。 @DebanjanB 我从未尝试过这样做,它非常有用,谢谢! Max,如果你想要客观的加载时间,你为什么要跳过这么多圈?只需跟踪导航到页面和最后一个元素加载之间的时间。完毕。此外,使用 WebdriverWait 将避免使用 time.sleep() 人为地夸大您的数字。 @Aphid 我尝试测量导航到页面和最后一个元素加载之间的时间。从浏览器控制台执行此操作时,它可以很好地近似实际加载时间。出于某种原因,当从 Selenium(禁用缓存)运行相同的 js 命令时,我的加载时间快得离谱(比我自己访问网站时看到的快 10-20 倍)。【参考方案2】:

右键单击演奏录音并选择保存配置文件。它会为您提供大量数据,但可能应该包含您需要的任何内容(我认为这是绩效记录报告可视化的源数据)。

DevTools 用于从浏览器获取数据的底层协议称为 Chrome DevTools 协议。其他客户端,例如 Selenium,可以启动与浏览器的会话(就像 DevTools 一样),并使用该协议来获取与 DevTools 获取的相同数据。底层协议方法称为Performance.getMetrics。我不熟悉 Selenium,但它应该可以以某种方式连接到 CDP。

您还可以使用 Puppeteer 自动执行此操作。我在Using DevTools Features Without Opening DevTools 中提供了一个使用 Puppeteer 访问 DevTools 功能的示例。

【讨论】:

以上是关于Chrome:性能数据 API的主要内容,如果未能解决你的问题,请参考以下文章

chrome插件开发-教程01(性能数据的获取和分析)

Chrome Developer Tools:Network Panel说明

Web Audio API:当使用媒体流时,Firefox 中的 FFT 数据与 chrome 中的不同?

爬虫工程师应该掌握的技能Chrome Devtools 高级调试指南(新)

了解 chrome 控制台上的网络选项卡

chrome devtools protocol——Web 性能自动化