钮(button)可能是网页中最常见的组件之一了,大部分都平淡无奇,如果你碰到的是一个这样的按钮,会不会忍不住多点几次呢?
转载链接: https://github.com/XboxYan/notes/issues/16
通常这类效果第一反应可能就是借助canvas了,比如下面这个案例点击预览(建议去codepen原链接点击预览访问,segmentfault内置的预览js会加载失败)
效果就更加震撼了,当然canvas实现也有一定的门槛,而且实际使用起来也略微麻烦(所有js实现的通病),这里尝试一下CSS的实现方式。
抛开js方案,还有HTML和CSS实现方式。HTML就不用说了,直接写上大量的标签
<button>
button
<i></i>
<i></i>
<i></i>
<i></i>
<i></i>
...
</button>
一般情况下我不是很喜欢这种方式,标签太多,结构不美观,而且有可能对现有的页面造成其他影响(很多情况下并不方便修改原始HTML结构)
那么来看看CSS实现方式,主要也是两种方式,其实就是想一下有哪些属性可以无限叠加,一个是box-shadow,还有一个是background-image(CSS3支持无限叠加)。
我们先看看box-shadow方式,为了避免使用额外标签,这里采用伪元素生成。
.button::before{
position: absolute;
content: '';
width: 5px;
height: 5px;
border-radius: 50%;
background-color: #ff0081;
box-shadow: 10px 10px #ff0081,15px 0px 0 2px #ff0081,20px 15px 0 3px #ff0081,...;/*无限叠加*/
}
效果还是有的,主要就是多花点时间来调试,这里主要根据偏移量和扩展来决定粒子的位置和大小。
不过这里的偏移量只能是px单位,无法很好的自适应按钮的大小,所以这里采用第二种方式来实现
CSS3中background-image是可以无限叠加的,类似于
.myclass {
background: background1, background2, /*...*/ backgroundN;
}
这里我们可以采用径向渐变radial-gradient来实现多个小圆点。
.button::before{
position: absolute;
content: '';
left: -2em;
right: -2em;
top: -2em;
bottom: -2em;
pointer-events: none;
background-repeat: no-repeat;
background-image: radial-gradient(circle, #ff0081 20%, transparent 0),
radial-gradient(circle, #ff0081 20%, transparent 0),
radial-gradient(circle, #ff0081 20%, transparent 0),
radial-gradient(circle, #ff0081 20%, transparent 0),
...;
background-size: 10% 10%, 20% 20%, 15% 15%,...;
background-position: 18% 40%, 20% 31%, 30% 30%,...;
}
这里主要通过background-size和background-position来控制原点的尺寸与位置,看着好像挺复杂,其实只要background-size和background-position与background-image位置一一对应就行了。实际开发中可能有点难调试,可以直接在控制台中通过键盘上下左右键微调实时预览效果(可以考虑做一个可视化工具)。
这样就做出了一个简单的粒子效果。
虽然background-image不支持CSS动画,但是另外两个background-size和background-position支持呀,所以,CSS transition和CSS animation都可以用起来。
动画效果很简单,就是粒子从中心往外扩散,并且逐渐消失的过程。
我们先看看:hover交互
.button::before{
transition:.75s background-position ease-in-out,75s background-size ease-in-out;
}
.button:hover::before{
background-position: 5% 44%, -5% 20%, 7% 5%...;
background-size: 0% 0%;
}
当然直接这样设置肯定是不理想,鼠标离开时会收缩回去,效果如下
我们需要是鼠标离开时不收缩回去,如何实现呢?
很简单,把transition设置在:hover下就可以了,表示只有当鼠标经过时才有过渡,离开时没有
.button:hover::before{
background-position: 5% 44%, -5% 20%, 7% 5%...;
background-size: 0% 0%;
transition:.75s background-position ease-in-out,75s background-size ease-in-out;
}
这样是不是感觉稍微好些了呢?点击这里点击预览查看。
如果我们想做成点击的时候出现粒子动画该怎么做呢?这里就需要借助:active伪类了。
如果我们按照:hover逻辑,那么
.button:active::before{
background-position: 5% 44%, -5% 20%, 7% 5%...;
background-size: 0% 0%;
transition:.75s background-position ease-in-out,75s background-size ease-in-out;
}
很遗憾,只有当只有按住不动的时候才能触发,一旦鼠标抬起就没有了,这个时候我们就需要换个角度了。可以这么想象一下,默认就是发散的,然后点击的时候聚拢,抬起的时候就会有还原成之前的发散状态,同时,在点击的时候需要取消掉过渡效果,如下
.button::before {
/*...*/
background-position: 5% 44%...;/*扩散的状态*/
background-size: 0% 0%;
transition: background-position .5s ease-in-out, background-size .75s ease-in-out;
}
.button:active::before {
transition:0s;/**注意取消掉过渡**/
background-size: 10% 10%, 20% 20%...;
background-position: 18% 40%, 20% 31%,...;
}
你可以查看这个demo点击预览
为什么在:active需要transition:0s呢,你可以试下不添加的效果就明白了,如下
animation和transition实现原理比较类似,优点是可以做出更加精细的动画,这里就拿:active方式来说吧。
.button::before{
/*...*/
animation: bubbles ease-in-out .75s forwards;
}
.button:active::before {
animation: none; /*这里注意取消动画*/
background-size: 0;
}
@keyframes bubbles {
0% {
background-position: 18% 40%, ...;
}
50% {
background-position: 10% 44%, ...;
}
100% {
background-position: 5% 44%, ...;
background-size: 0% 0%;
}
}
可以在这里点击预览查看源码。
唯一的不足可能是初始化动画会自执行一次。
上面介绍了纯CSS实现一个粒子动效的按钮,优点很明显,复制一下CSS直接扔到项目里就能用,管他什么原生项目还是react项目,也无需绑定什么事件,也无需额外的逻辑处理,增强现有体验。试想一下,如果这是一个‘购买’按钮,会不会触发你多购买几次呢,反正我肯定是会被吸引住了,哈~缺点也还是有的,比如上面的定位,密密麻麻都是工作量啊,建议这些功能在项目整体完成之后再细细打磨,也可以试着做一些可视化工具来减轻工作量,完。
一种:selenium导入浏览器驱动,用get方法打开浏览器,例如:
import time from selenium import webdriver def mac(): # browser = webdriver.Chrome() # browser = webdriver.Firefox() browser = webdriver.Ie() browser.implicitly_wait(5) browser.get('http://www.baidu.com/')
第二种:通过导入python的标准库webbrowser打开浏览器,例如:
import webbrowser def mac(): # web.open(‘http://www.baidu.com’,new=0,autoraise=True) # new:0/1/2 0:同一浏览器窗口打开 1:打开浏览器新的窗口,2:打开浏览器窗口新的tab; autoraise=True:窗口自动增长 # web.open_new_tab(‘http://www.baidu.com’) web.open_new(‘http://www.baidu.com’)
第三种:使用Splinter模块模块
一、Splinter 的安装
Splinter 的使用必修依靠 Cython、lxml、selenium 这三个软件。所以,安装前请提前安装 Cython、lxml、selenium。
二、Splinter 的使用
这里,我给出自动登录 126 邮箱的案例。难点是要找到页面的账户、密码、登录的页面元素,这里需要查看 126 邮箱登录页面的源码,才能找到相关控件的 id.
例如: 输入密码,密码的文本控件 id 是 pwdInput. 可以使用browser.find_by_id() 方法定位到密码的文本框,接着使用fill() 方法,填写密码。至于模拟点击按钮,也是要先找到按钮控件的 id, 然后使用 click() 方法。
# coding=utf-8 import time from splinter import Browser def splinter(url): browser = Browser() # login 126 email websize browser.visit(url) # wait web element loading time.sleep(5) # fill in account and password browser.find_by_id('idInput').fill('xxxxxx') browser.find_by_id('pwdInput').fill('xxxxx') # click the button of login browser.find_by_id('loginBtn').click() time.sleep(8) # close the window of brower browser.quit() if __name__ == '__main__': websize3 ='http://www.126.com' splinter(websize3)
WebDriver简介
selenium 从 2.0 开始集成了 webdriver 的 API,提供了更简单,更简洁的编程接口。selenium webdriver 的目标是提供一个设计良好的面向对象的 API,提供了更好的支持进行 web-app 测试。
打开浏览器
在 selenium+python 自动化测试(一)–环境搭建中,运行了一个测试脚本,脚本内容如下:
from selenium import webdriver import time browser = webdriver.Chrome() browser.get("http://www.baidu.com") print(browser.title) browser.find_element_by_id("kw").send_keys("selenium") browser.find_element_by_id("su").click() time.sleep(3) browser.close()
webdriver 是一个 Web 应用程序测试自动化工具,用来验证程序是否如预期的那样执行。
webdriver.Chrome():创建一个 Chrome 浏览器的 webdriver 实例
browser.get(“http://www.baidu.com“):打开”http://www.baidu.com”页面
browser.find_element_by_id(“kw”).send_keys(“selenium”):
找到 id 为“kw”的元素,在这个页面上为百度首页的搜索框,在其中输入“selenium”
browser.find_element_by_id(“su”).click():找到 id 为“su”的元素并点击,在这个页面上为百度首页的“百度一下”按钮
browser.close():退出浏览器
运行脚本的第一步是打开浏览器,使用 webdriver.Chrome() 打开谷歌浏览器,如果要指定其他浏览器,比如要使用 Firefox 或者 IE 浏览器,更换浏览器名称就可以了
browser = webdriver.Chrome() // 打开 Chrome 浏览器
browser = webdriver.Firefox() // 打开 Firefox 浏览器
browser = webdriver.Ie() // 打开 IE 浏览器
第二步操作是打开页面,使用browser.get(url)方法来打开网页链接,例如脚本中打开百度首页
browser.get("http://www.baidu.com")
接下来是 **print(browser.title)**,使用browser.title获取当前页面的title,title就是在浏览器 tab 上显示的内容,例如百度首页的标题是“百度一下,你就知道”
浏览器前进后退
在当前页面打开一个新的链接后,如果想回退到前一个页面,使用如下browser.back(),相当于点击了浏览器的后退按钮
和 back 操作对应的是浏览器前进操作browser.forward(),相当于点击了浏览器的前进按钮
browser.back() // 回到上一个页面
browser.forward() // 切换到下一个页面
浏览器运行后,如果页面没有最大化,可以调用browser.maximize_window()将浏览器最大化,相当于点击了页面右上角的最大化按钮
browser.maximize_window() // 浏览器窗口最大化
browser.set_window_size(800, 720) // 设置窗口大小为 800*720
浏览器截屏操作,参数是截屏的图片保存路径:
browser.get_screenshot_as_file("D:/data/test.png") 屏幕截图保存为***
browser.refresh() // 重新加载页面, 页面刷新
在测试脚本运行完后,一般会在最后关闭浏览器,有两种方法关闭浏览器,close()方法用于关闭当前页面,quit()方法关闭所有和当前测试有关的浏览器窗口
browser.close() // 关闭当前页面
browser.quit() // 关闭所有由当前测试脚本打开的页面
<h1 class="csdn_top" line-height:38px;color:#2c3033;padding:0px="" 29px;white-space:normal;"="" style="word-wrap: break-word; color: rgb(0, 0, 0); font-family: "sans serif", tahoma, verdana, helvetica; margin-top: 0px; margin-bottom: 0px; font-size: 24px;"> 页面元素定位
要定位页面元素,需要找到页面的源码。
IE 浏览器中,打开页面后,在页面上点击鼠标右键,会有“查看源代码”的选项,点击后就会进入页面源码页面,在这里就可以找到页面的所有元素
使用 Chrome 浏览器打开页面后,在浏览器的地址栏右侧有一个图标,点击这个图标后,会出现许多菜单项,选择更多工具里的开发者工具,就会出现页面的源码,不同版本的浏览器菜单选项可能不同,但是都会在开发者工具里找到页面的源码
Firefox 浏览器打开页面后,在右键菜单里也可以找到“查看页面源代码”的选项。在 Firefox 中,可以使用浏览器自带的插件查看定位元素,在 Firefox 的附加组件里搜索 firebug 进行下载,安装 firebug 组件后会在浏览器的工具栏中多出一个小虫子的图标,点击这个图标就可以打开组件查看页面源码,打开后如下图所示
以百度首页搜索页面为例,看一下 webdriver 定位元素的八种方式
使用id定位
在页面源码中找到搜索输入框的元素定义
可以看到输入框有一个有一个 id 的属性,调用find_element_by_id()根据 id 属性来找到元素,参数为属性的值
input_search = browser.find_element_by_id("kw")
使用name定位
使用find_element_by_name()根据 name 属性找到元素,参数为 name 属性的值
搜索框有一个 name=”wd”的属性,使用 name 查找搜索输入框元素
input_search = browser.find_element_by_name("wd")
使用className定位
使用find_element_by_class_name()根据 className 属性找到元素,参数为 className 属性的值
搜索框有一个 class=”s_ipt”的属性,使用 className 查找元素
input_search = browser.find_element_by_class_name("s_ipt")
使用tagName定位
使用find_element_by_tag_name()根据 tagName 属性找到元素,参数为元素标签的名称
每个页面的元素都有一个 tag,搜索框的标签为 input,有时候一个页面里有许多相同的标签,所以用这种方法找到的元素一般都不准确,除非这个元素使用的标签在这个页面里是唯一的。一般不会使用这种方式来定位元素
input_search = browser.find_element_by_class_name("input")
使用link_text定位
页面上都会有一些文本链接,点击链接后会打开一个新的页面,这些可以点击的链接可以使用find_element_by_link_text来定位,百度首页上方有如下几个元素
例如要定位“新闻”,找到元素的代码,有一个 href 的属性,这是点击后打开的页面
新闻
使用 link_text 查找元素,参数为元素的文本信息
news = browser.find_element_by_link_text("新闻")
使用partial_link_text定位
这种方式类似于 link_text 的定位方式,如果一个元素的文本过长,不需要使用文本的所有信息,可以使用其中的部分文本就可以定位
使用 partial_link_text 查找百度首页的“新闻”元素,参数为文本信息,可以使用全部的文本,也可以使用部分文本
news = browser.find_element_by_link_text("新闻") // 使用全部文本
news = browser.find_element_by_link_text("新") // 使用部分文本
使用css selector定位
使用 css 属性定位元素有多种方法,可以使用元素的 id、name、className,也可以使用元素的其他属性,如果一个元素没有上述的几种属性或者定位不到时,可以使用 css 来定位
还是使用百度搜索框的实例来说明 css 定位的用法
css使用元素的id定位
css 属性使用 id 定位时,使用 #号表示元素的 id
input_search = browser.find_element_by_css_selector("#kw") // 使用元素的 id 定位
css使用元素的class定位
css 属性使用 class 定位时,使用. 号表示元素的 class
input_search = browser.find_element_by_css_selector(".s_ipt") // 使用元素的 class 定位
css使用元素的tag定位
css 属性使用 tagName 定位时,直接使用元素的标签
input_search = browser.find_element_by_css_selector("input") // 使用元素的 tagName 定位
css 使用元素的其他属性
除了上述 3 种属性,css 属性可以使用元素的其他属性定位,格式如下
input_search = browser.find_element_by_css_selector("[maxlength='255']")
使用元素的maxlength属性定位
input_search = browser.find_element_by_css_selector("[autocomplete='off']")
使用元素的autocomplete属性定位
可以在参数中加入元素的标签名称
input_search = browser.find_element_by_css_selector("input#kw") // 使用元素的 id 定位
input_search = browser.find_element_by_css_selector("input.s_ipt") // 使用元素的 class 定位
input_search = browser.find_element_by_css_selector("input[maxlength='255']") // 使用元素的 maxlength 属性定位
input_search = browser.find_element_by_css_selector("input[autocomplete='off']") // 使用元素的 autocomplete 属性定位
css 的层级定位
当一个元素使用自身的属性不容易定位时,可以通过它的父元素来找到它,如果父元素也不好定位,可以再通过上元素来定位,以此类推,一直找到容易定位的父元素为止,通过层级定位到需要查找的元素
通过 Firefox 的 firebug 组件查看百度首页的源码
通过层级来定位搜索框
input_search = browser.find_element_by_css_selector("form#form>span:nth-child(1)>input")
input_search = browser.find_element_by_css_selector("form.fm>span:nth-child(1)>input")
搜索框的父元素为 span 标签,span 的父元素为 form,form 有 id 和 class 属性,可以通过这两个属性来定位,找到 form 元素后,form 下有多个 span 标签,所以要使用 span:nth-child(1),表示 form 下的第一个 span 标签,这种用法很容易理解,表示第几个孩子,最后是 span 下的 input 标签,span 下只有一个 input,所以就可以定位到搜索框
css逻辑运算
用一个属性来定位元素时,如果有其他元素的属性和此元素重复,可以组合多个属性来功共同定位
组合多个属性定位元素定位百度搜索框
input_search = browser.find_element_by_css_selector("input[id='kw'][name='wd']")
在元素内定义的属性,都可以使用 css 来定位,使用其他几种方式无法定位到元素时,可以使用 css,够强大!
使用xpath定位
XPath 是一种在 XML 文档中定位元素的语言。因为 HTML 可以看做 XML 的一种实现,所以 selenium 用户可是使用这种强大语言在 web 应用中定位元素。xpath 也可以通过元素的各种属性定位到元素
使用元素属性定位
input_search = browser.find_element_by_xpath("//*[@id='kw']") // 通过元素 id 查找元素
input_search = browser.find_element_by_xpath("//*[@name='wd']") // 通过元素 name 查找元素
input_search = browser.find_element_by_xpath("//*[@class='s_ipt']") // 通过元素 class 查找元素
input_search = browser.find_element_by_xpath("//*[@maxlength='255']") // 通过其他属性查找元素
input_search = browser.find_element_by_xpath("//*[@autocomplete='off']") // 通过其他属性查找元素
前面的 * 号表示查找所有的标签元素,可以替换为标签名称,更准确的定位元素
input_search = browser.find_element_by_xpath("//input[@id='kw']") // 通过元素 id 查找元素
input_search = browser.find_element_by_xpath("//input[@name='wd']") // 通过元素 name 查找元素
input_search = browser.find_element_by_xpath("//input[@class='s_ipt']") // 通过元素 class 查找元素
input_search = browser.find_element_by_xpath("//input[@maxlength='255']") // 通过其他属性查找元素
input_search = browser.find_element_by_xpath("//input[@autocomplete='off']") // 通过其他属性查找元素
xpath也可以通过层级来定位,定位方式
input_search = browser.find_element_by_xpath("//input[@id='form']//span[1]//input")
browser.find_element_by_xpath("//input[@class='fm']//span[1]//input")查找效果和通过 css 的层级定位是相同的,意思是 form 元素下面的第一个 span 元素的 input 标签子元素xpath的逻辑元素通过and运算符来组合元素属性
input_search = browser.find_element_by_xpath("//input[@id='kw' and name='wd']")
属性匹配
xpath 中还有一种更强大的定位方式,通过模糊匹配元素的属性
news = browser.find_element_by_xpath("//a[contains(text(), '新闻')]")
查找text中包含"新闻"的元素
input_search = browser.find_element_by_xpath("//input[contains(@id, 'kw']")
查找id中包含"kw"的元素
input_search = browser.find_element_by_xpath("//input[starts-with(@id, 'k']")
查找id以"k"开头的元素
input_search = browser.find_element_by_xpath("//input[ends-with(@id, 'w']")
查找id以"w"结尾的元素
input_search = browser.find_element_by_xpath("//input[matchs(@id, 'k*']")
利用正则表达式查找元素
上面介绍了查找页面元素的八种方法,通过这些方式找到的都是单个元素,如果需要批量查找元素,还有和上面方式对应的八种复数形式
find_elements_by_id
find_elements_by_name
find_elements_by_class_name
find_elements_by_tag_name
find_elements_by_link_text
find_elements_by_partial_link_text
find_elements_by_css_selector
find_elements_by_xpath
这8种方法查找到的是一组元素,返回的是list,可以通过索引来操作元素
例如页面上的复选框和单选框,或者页面上有多个属相相同的输入框,这些属性相同的一组元素,可以批量获取,然后过滤出需要操作的元素,选择其中的一个或者多个进行操作
通过百度首页搜索“selenium”关键字,会出现许多搜索结果,这些搜索结果具有相同的属性,不同的是属性的值不同,定位这些元素时,可以使用批量定位的方法
看下面的代码
这是搜索 selenium 关键字后的页面结果,每一个搜索结果都是可点击的链接,定位这些元素的方法:
search_results = browser.find_elements_by_css_selector("h.t>a")
search_results[3].click() // 通过索引点击第 4 条搜索结果
第二个例子
checkbox
checkbox1
checkbox2
checkbox3
这个页面上有 3 个复选框,打开后如下图所示:
操作复选框
// 查找所有的复选框并点击
checkboxs = browser.find_element_by_xpath('input[@type="checkbox"]')
返回一个 list
for checkbox in checkboxs:
checkbox.click()
// 点击最后一个复选框
checkboxs[2].click()
from selenium import webdriver
browser=webdriver.Firefox()
browser.get(r’http://www.baidu.com/’)
print(‘browser attributes:’)
print(dir(browser))
elem=browser.find_element_by_id(‘kw’)
print(‘WebElement attributes:’)
print(dir(elem))
浏览器属性:
driver attributes:
[‘NATIVE_EVENTS_ALLOWED’, ‘class’, ‘delattr’, ‘dict’, ‘doc’, ‘format’, ‘getattribute’, ‘hash’, ‘init’, ‘module’, ‘new’, ‘reduce’, ‘reduce_ex’, ‘repr’, ‘setattr’, ‘sizeof’, ‘str’, ‘subclasshook’, ‘weakref’, ‘_file_detector’, ‘_is_remote’, ‘_mobile’, ‘_switch_to’, ‘_unwrap_value’, ‘_wrap_value’, ‘add_cookie’, ‘application_cache’, ‘back’, ‘binary’, ‘capabilities’, ‘close’, ‘command_executor’, ‘create_web_element’, ‘current_url’, ‘current_window_handle’, ‘delete_all_cookies’, ‘delete_cookie’, ‘desired_capabilities’, ‘error_handler’, ‘execute’, ‘execute_async_script’, ‘execute_script’, ‘file_detector’, ‘find_element’, ‘find_element_by_class_name’, ‘find_element_by_css_selector’, ‘find_element_by_id’, ‘find_element_by_link_text’, ‘find_element_by_name’, ‘find_element_by_partial_link_text’, ‘find_element_by_tag_name’, ‘find_element_by_xpath’, ‘find_elements’, ‘find_elements_by_class_name’, ‘find_elements_by_css_selector’, ‘find_elements_by_id’, ‘find_elements_by_link_text’, ‘find_elements_by_name’, ‘find_elements_by_partial_link_text’, ‘find_elements_by_tag_name’, ‘find_elements_by_xpath’, ‘firefox_profile’, ‘forward’, ‘get’, ‘get_cookie’, ‘get_cookies’, ‘get_log’, ‘get_screenshot_as_base64’, ‘get_screenshot_as_file’, ‘get_screenshot_as_png’, ‘get_window_position’, ‘get_window_size’, ‘implicitly_wait’, ‘log_types’, ‘maximize_window’, ‘mobile’, ‘name’, ‘orientation’, ‘page_source’, ‘profile’, ‘quit’, ‘refresh’, ‘save_screenshot’, ‘session_id’, ‘set_page_load_timeout’, ‘set_script_timeout’, ‘set_window_position’, ‘set_window_size’, ‘start_client’, ‘start_session’, ‘stop_client’, ‘switch_to’, ‘switch_to_active_element’, ‘switch_to_alert’, ‘switch_to_default_content’, ‘switch_to_frame’, ‘switch_to_window’, ‘title’, ‘w3c’, ‘window_handles’]
调用说明:
driver. 属性值
变量说明:
1.driver.current_url:用于获得当前页面的 URL
2.driver.title:用于获取当前页面的标题
3.driver.page_source: 用于获取页面 html 源代码
4.driver.current_window_handle: 用于获取当前窗口句柄
5.driver.window_handles: 用于获取所有窗口句柄
函数说明:
1.driver.find_element*(): 定位元素,
2.driver.get(url): 浏览器加载 url。
实例:driver.get(“http//:www.baidu.com”)
3.driver.forward():浏览器向前(点击向前按钮)。
4.driver.back():浏览器向后(点击向后按钮)。
5.driver.refresh():浏览器刷新(点击刷新按钮)。
6.driver.close():关闭当前窗口,或最后打开的窗口。
7.driver.quit(): 关闭所有关联窗口,并且安全关闭 session。
8.driver.maximize_window(): 最大化浏览器窗口。
9.driver.set_window_size(宽,高):设置浏览器窗口大小。
10.driver.get_window_size():获取当前窗口的长和宽。
11.driver.get_window_position():获取当前窗口坐标。
12.driver.get_screenshot_as_file(filename): 截取当前窗口。
实例:driver.get_screenshot_as_file(‘D:/selenium/image/baidu.jpg’)
13.driver.implicitly_wait(秒):隐式等待,通过一定的时长等待页面上某一元素加载完成。
若提前定位到元素,则继续执行。若超过时间未加载出,则抛出 NoSuchElementException 异常。
实例:driver.implicitly_wait(10) #等待 10 秒
14.driver.switch_to_frame(id 或 name 属性值):切换到新表单 (同一窗口)。若无 id 或属性值,可先通过 xpath 定位到 iframe,再将值传给 switch_to_frame()
15.driver.switch_to.parent_content(): 跳出当前一级表单。该方法默认对应于离它最近的 switch_to.frame() 方法。
16.driver.switch_to.default_content(): 跳回最外层的页面。
17.driver.switch_to_window(窗口句柄):切换到新窗口。
18.driver.switch_to.window(窗口句柄): 切换到新窗口。
19.driver.switch_to_alert(): 警告框处理。处理 JavaScript 所生成的 alert,confirm,prompt.
20.driver.switch_to.alert(): 警告框处理。
21.driver.execute_script(js): 调用 js。
22.driver.get_cookies(): 获取当前会话所有 cookie 信息。
23.driver.get_cookie(cookie_name):返回字典的 key 为“cookie_name”的 cookie 信息。
实例:driver.get_cookie(“NET_SessionId”)
24.driver.add_cookie(cookie_dict): 添加 cookie。“cookie_dict”指字典对象,必须有 name 和 value 值。
25.driver.delete_cookie(name,optionsString): 删除 cookie 信息。
26.driver.delete_all_cookies(): 删除所有 cookie 信息。
页面元素属性:
WebElement attributes:
[‘class’, ‘delattr’, ‘dict’, ‘doc’, ‘eq’, ‘format’, ‘getattribute’, ‘hash’, ‘init’, ‘module’, ‘ne’, ‘new’, ‘reduce’, ‘reduce_ex’, ‘repr’, ‘setattr’, ‘sizeof’, ‘str’, ‘subclasshook’, ‘weakref’, ‘_execute’, ‘_id’, ‘_parent’, ‘_upload’, ‘_w3c’, ‘clear’, ‘click’, ‘find_element’, ‘find_element_by_class_name’, ‘find_element_by_css_selector’, ‘find_element_by_id’, ‘find_element_by_link_text’, ‘find_element_by_name’, ‘find_element_by_partial_link_text’, ‘find_element_by_tag_name’, ‘find_element_by_xpath’, ‘find_elements’, ‘find_elements_by_class_name’, ‘find_elements_by_css_selector’, ‘find_elements_by_id’, ‘find_elements_by_link_text’, ‘find_elements_by_name’, ‘find_elements_by_partial_link_text’, ‘find_elements_by_tag_name’, ‘find_elements_by_xpath’, ‘get_attribute’, ‘id’, ‘is_displayed’, ‘is_enabled’, ‘is_selected’, ‘location’, ‘location_once_scrolled_into_view’, ‘parent’, ‘rect’, ‘screenshot’, ‘screenshot_as_base64’, ‘screenshot_as_png’, ‘send_keys’, ‘size’, ‘submit’, ‘tag_name’, ‘text’, ‘value_of_css_property’]
调用说明:
driver.find_element*. 属性值
或
element=driver.find_element*
element. 属性值
变量说明:
1.element.size: 获取元素的尺寸。
2.element.text:获取元素的文本。
3.element.tag_name: 获取标签名称。
函数说明:
1.element.clear(): 清除文本。
2.element.send_keys(value): 输入文字或键盘按键(需导入 Keys 模块)。
3.element.click():单击元素。
4.element.get_attribute(name): 获得属性值
5.element.is_displayed(): 返回元素结果是否可见(True 或 False)
6.element.is_selected(): 返回元素结果是否被选中(True 或 False)
7.element.find_element*(): 定位元素,用于二次定位。
网页自动化最基本的要求就是要定位到各个元素,然后才能对该元素进行各种操作(输入,点击,清除,提交等)。
以百度搜索输入框为例,具体说明各个定位方式的用法:
(通过 chrome 浏览器查看元素或者搜狐浏览器的 firebug 查看,即可看到 html 源码)
注意点:第三行的元素是灰色的,该元素是不可定位到的,下方会说明。
1
2
3
4
5
6
7
8
1. 通过 id 定位元素
如果 id 不是动态的,一个页面的 id 是唯一的。最简单的定位方式。
使用:find_element_by_id(“id_vaule”)
实例:find_element_by_id(“kw”)
注意点:有些 id 值是动态变化的,则不能使用该方法定位。如下:id 就是动态的,每次进入页面,该 id 都会改变
邮箱帐号或手机号
2. 通过 class_name 定位元素
classname 有可能重复哦。
使用:find_element_by_class_name(“class_name_vaule”)
实例:find_element_by_class_name(“s_ipt”)
3. 通过 tag_name 定位元素
标签名字最容易重复,不过,当定位一组数据时,可使用。
使用:find_element_by_tag_name(“tag_name_vaule”)
实例:find_element_by_tag_name(“input”)
注意点:当定位一组元素时:可勾选一组复选框。如下:
find_element_by_tag_name(“input”)
checkbox
checkbox1
checkbox2
checkbox3
4. 通过 name 定位元素
name 有可能会重复哦。
使用:find_element_by_name(“name_vaule”)
实例:find_element_by_name(“wd”)
5. 通过 link 文字精确定位元素
登录
使用:find_element_by_link_text(“text_vaule”)
实例:find_element_by_link_text(“登录”)
6. 通过 link 文字模糊定位元素
使用:find_element_by_partial_link_text(“部分 text_vaule”)
实例:find_element_by_partial_link_text(“登”)
7. 通过 CSS 定位元素
CSS(Cascading Style Sheets)是一种语言,它用来描述 HTML 和 XML 文档的表现。CSS 可以较为灵活的选择控件的任意属性,一般情况下会比 XPath 快。且语法也比较简洁。
使用:find_element_by_css_selector(“CSS”)
实例:
7.1 通过 id 属性定位元素
#号表示通过 id 属性来定位元素
find_element_by_css_selector(“#kw”)
7.2 通过 class 属性定位元素
. 号表示通过 class 属性来定位元素
find_element_by_css_selector(“.s_ipt”)
7.3 通过标签名定位元素
find_element_by_css_selector(“input”)
7.4 通过属性定位元素(挺常用的)
find_element_by_css_selector(“[name=‘wd’]”)
find_element_by_css_selector(“[maxlength=‘255’]”)
属性值包含某个值
属性值包含 wd:适用于由空格分隔的属性值。
find_element_by_css_selector(“[name~=‘wd’]”)
7.5 父子定位元素
查找有父亲元素的标签名为 span,它的所有标签名叫 input 的子元素
**find_element_by_css_selector(“span>input”) **
7.6 组合定位元素
标签名 #id 属性值:指的是该 input 标签下 id 属性为 kw 的元素
find_element_by_css_selector(“input#kw”)
标签名.class 属性值:指的是该 input 标签下 class 属性为 s_ipt 的元素
find_element_by_css_selector(“input.s_ipt”)
标签名 [属性 =’属性值‘]:指的是该 input 标签下 name 属性为 wd 的元素
find_element_by_css_selector(“input[name=‘wd’]”)
父元素标签名 > 标签名.class 属性值:指的是 span 下的 input 标签下 class 属性为 s_ipt 的元素
find_element_by_css_selector(“span>input.s_ipt”)
多个属性组合定位元素(挺常用的)
指的是 input 标签下 id 属性为 kw 且 name 属性为 wd 的元素
find_element_by_css_selector(“input.s_ipt[name=‘wd’]”)
指的是 input 标签下 name 属性为 wd 且 maxlength 为 255 的元素
find_element_by_css_selector(“input[name=‘wd’][maxlength='255']”)
8. 通过 XPath 定位元素
XPath 是一种 XML 文档中定位元素的语言。该定位方式也是比较常用的定位方式。
使用:find_element_by_xpath(“XPath”)
8.1 通过属性定位元素
find_element_by_xpath(“// 标签名 [@属性 =‘属性值’]”)
id 属性:find_element_by_xpath(“//input[@id=‘kw’]”)
class 属性:find_element_by_xpath(“//input[@class=‘s_ipt’]”)
name 属性:find_element_by_xpath(“//input[@name=‘wd’]”)
maxlength 属性:find_element_by_xpath(“//input[@maxlength=‘255’]”)
8.2 通过标签名定位元素
指所有 input 标签元素 find_element_by_xpath(“//input”)
8.3 父子定位元素
查找有父亲元素的标签名为 span,它的所有标签名叫 input 的子元素
find_element_by_xpath(“//span/input”)
8.4 根据元素内容定位元素(非常实用)
find_element_by_xpath(“//p[contains(text(),‘京公网’)]”)
京公网安备 11000002000001 号
注:contains 的另一种用法
//**input[contains(@class,‘s’)] **说明 class 属性包含 s 的元素。
8.5 组合定位元素
// 父元素标签名 / 标签名的属性值:指的是 span 下的 input 标签下 class 属性为 s_ipt 的元素
find_element_by_xpath(“//span/input[@class=‘s_ipt’]”)
多个属性组合定位(挺常用的)
指的是 input 标签下 id 属性为 kw 且 name 属性为 wd 的元素
find_element_by_xpath(“//input[@class=‘s_ipt’ and @name=‘wd’]”)
指的是 p 标签下内容包含“京公网”且 id 属性为 jgwab 的元素
find_element_by_xpath(“//p[contains(text(),‘京公网’)and @id=‘jgwab’]”)
比较懒惰的方法:
使用搜狐浏览器的 firebug 工具,复制 XPath 路径,不过这种方式对层级要求高,到时候自己再修改下。
9. 通过 By 定位元素
使用:find_element(定位的类型,具体定位方式)
定位的类型包括 By.ID,By.NAME,By.CLASS_NAME,By.TAG_NAME,By.LINK_TEXT,By.PARTIAL_LINK_TEXT,By.XPATH,By.CSS_SELECTOR
具体定位方式参考上方 1-8 的说明。
实例:find_element(By.ID,‘kw’)
注意:使用 By 定位方式,需先导入 By 类。
from selenium.webdriver.common.by import By
10. 具体实例说明
下方例子是登陆 126 邮件,然后发送邮件。
1 # coding=utf-8
2 '''
3 Created on 2016-7-27
4 @author: Jennifer
5 Project: 发送邮件
6 '''
7 from selenium import webdriver
8 import time
9
10 from test_5_2_public import Login # 由于公共模块文件命名为 test_5_2_public
11 driver=webdriver.Firefox()
12 driver.implicitly_wait(30)
13 driver.get(r’http://www.126.com/‘) # 字符串加 r,防止转义。
14 time.sleep(3)
15 driver.switch_to.frame(‘x-URS-iframe’)
16 #调用登录模块
17 Login().user_login(driver)
18 time.sleep(10)
19 #发送邮件
20 #点击发件箱
21 #_mail_component_61_61 是动态 id,所以不能用于定位
22 #driver.find_element_by_css_selector(’#_mail_component_61_61>span.oz0’).click()
23 #不能加 u"//span[contains(text(),u’写 信’)]“,否则定位不到。
24 #以下定位是查找 span 标签有个文本(text)包含(contains)‘写 信’ 的元素,该定位方法重要
25 **driver.find_element_by_xpath(”//span[contains(text(),‘写 信’)]“).click()**
26 #填写收件人
27 #driver.find_element_by_class_name(‘nui-editableAddr-ipt’).send_keys(r’xxx@doov.com.cn’)
28 driver.find_element_by_class_name(‘nui-editableAddr-ipt’).send_keys(r’xxx@163.com’)
29 #填写主题
30 #通过 and 连接更多的属性来唯一地标志一个元素
31 **driver.find_element_by_xpath(”//input[@class=‘nui-ipt-input’ and @maxlength=‘256’]“).send_keys(u’自动化测试’)**
32 #填写正文
33 #通过 switch_to_frame() 将当前定位切换到 frame/iframe 表单的内嵌页面中
34 driver.switch_to_frame(driver.find_element_by_class_name(‘APP-editor-iframe’))
35 #在内嵌页面中定位邮件内容位置
36 emailcontext=driver.find_element_by_class_name(‘nui-scroll’)
37 #填写邮件内容
38** emailcontext.send_keys(u’这是第一封自动化测试邮件’)**
39 #通过 switch_to().default_content() 跳回最外层的页面
40 #注:不要写成 switch_to().default_content(), 否则报 AttributeError: SwitchTo instance has no call method
41 driver.switch_to.default_content()
42 #driver.switch_to.parent_frame()
43 #点击发送
44 time.sleep(3)
45 #有可能存在元素不可见(查看元素是灰色的),会报 ElementNotVisibleException 错误
46 #包含发送二字的元素很多,所以还得再加上其他限制
47 #sendemails=driver.find_element_by_xpath(”//span[contains(text(),‘发送’)]“)
48 **sendemails=driver.find_element_by_xpath(”//span[contains(text(),‘发送’)and @class=‘nui-btn-text’]")**
49 time.sleep(3)
50
51 #校验邮件是否发送成功
52 try:
53 assert ‘发送成功’ in driver.page_source
54 except AssertionError:
55 print ‘邮件发送成功’
56 else:
57 print ‘邮件发送失败’
58
59 #调用退出模块
60 Login().user_logout(driver)
元素定位说明:
1. 代码 22 行,定位不到是因为 id 是动态的,所以需采取其他方式定位元素。
2. 代码 25 行,是根据元素内容来定位的,具体用法详看 8.4.
3. 代码 28 行,是根据 class 名来定位元素的,由于该值在该页面上是唯一的,所以可以用它来定位。
4. 代码 31 行,是使用逻辑运算符 and 连接更多的属性从而唯一的标志一个元素,具体用法详看 8.5.
5. 代码 34 行,由于使用内嵌的 iframe 框架,所以需要先使用 switch_to_frame() 移到该表单上,才能定位该表单上的元素,非常重要,否则无论怎么定位都会报“NoSuchElementException”,找不到该元素。
6. 代码 41 行,跳出 iframe 框架,当框架内的动作操作完毕后,需要使用 switch_to.default_content 跳出 iframe 框架, 非常重要。
7. 代码 47 行,由于内容包括“发送”的元素中包含不可见元素(html 查看元素可以看到此行是灰色的),这样有可能定位到不可见元素,会报“ElementNotVisibleException”。
8. 代码 48 行,是使用逻辑运算符 and 连接更多的属性从而唯一的标志一个元素,具体用法详看 8.5. 这样可以排除掉那个不可见元素。
1.Frame/Iframe 原因定位不到元素:
这个是最常见的原因,首先要理解下 frame 的实质,frame 中实际上是嵌入了另一个页面,而 webdriver 每次只能在一个页面识别,因此需要先定位到相应的 frame,对那个页面里的元素进行定位。
解决方案:
如果 iframe 有 name 或 id 的话,直接使用 switch_to_frame(“name 值”) 或 switch_to_frame(“id 值”)。
如下:
driver=webdriver.Firefox()
driver.get(r’http://www.126.com/’)
driver.switch_to_frame(‘x-URS-iframe’) # 需先跳转到 iframe 框架
username=driver.find_element_by_name(‘email’)
username.clear()
如果 iframe 没有 name 或 id 的话,则可以通过下面的方式定位:
#先定位到 iframe
elementi= driver.find_element_by_class_name(‘APP-editor-iframe’)
#再将定位对象传给 switch_to_frame() 方法
driver.switch_to_frame(elementi)
如果完成操作后,
可以通过 switch_to.parent_content()方法跳出当前 iframe,或者还可以通过 switch_to.default_content() 方法跳回最外层的页面。
2.Xpath 描述错误原因:
由于 Xpath 层级太复杂,容易犯错。但是该定位方式能够有效定位绝大部分的元素,建议掌握。
解决方案:
2.1 可以使用 Firefox 的 firePath,复制 xpath 路径。该方式容易因为层级改变而需要重新编写过 xpath 路径,不建议使用,初学者可以先复制路径,然后尝试去修改它。
2.2 提高下写 xpath 的水平。
如何检验编写的 Xpath 是否正确?编写好 Xpath 路径,可以直接复制到搜狐浏览器的 firebug 查看 html 源码,通过 Xpath 搜索:如下红色框,若无报错,则说明编写的 Xpath 路径没错。
**find_element_by_xpath(“//input[@id=‘kw’]”) **
3. 页面还没有加载出来,就对页面上的元素进行的操作:
这种情况一般说来,可以设置等待,等待页面显示之后再操作,这与人手工操作的原理一样:
3.1 设置等待时间;缺点是需要设置较长的等待时间,案例多了测试就很慢;
3.2 设置等待页面的某个元素出现,比如一个文本、一个输入框都可以,一旦指定的元素出现,就可以做操作。
3.3 在调试的过程中可以把页面的 html 代码打印出来,以便分析。
解决方案:
导入时间模块。
import time
time.sleep(3)
4. 动态 id 定位不到元素:
解决方案:
如果发现是动态 id,直接用 xpath 定位或其他方式定位。
5. 二次定位,如弹出框登录
如百度登录弹出框登录百度账号,需先定位到百度弹出框,然后再定位到用户名密码登录。
#coding=utf-8
'''
Created on 2016-7-20
@author: Jennifer
Project: 登录百度账号
'''
from selenium import webdriver
import time
driver = webdriver.Firefox()
driver.get(“http://www.baidu.com/”)
time.sleep(3)
#点击登录:有些 name 为 tj_login 的元素为不可见的,点击可见的那个登录按钮即可。
#否则会报:ElementNotVisibleException
element0=driver.find_elements_by_name(“tj_login”)
for ele0 in element0:
if ele0.is_displayed():
ele0.click()
#在登录弹出框,需先定位到登录弹出框
#否则会报:NoSuchElementException
element1=driver.find_element_by_class_name(“tang-content”)
element11=element1.find_element_by_id(“TANGRAM__PSP_8__userName”)
element11.clear()
element11.send_keys(“登录名”)
element2=element1.find_element_by_id(“TANGRAM__PSP_8__password”)
element2.clear()
element2.send_keys(“密码”)
element3=element1.find_element_by_id(“TANGRAM__PSP_8__submit”)
element3.click()
element3.submit()
try:
assert “登录名” in driver.page_source
except AssertionError:
print “登录失败”
else:
print “登录成功”
time.sleep(3)
finally:
print “测试记录:已测试”
driver.close()
6. 不可见元素定位
如上百度登录代码,通过名称为 tj_login 查找的登录元素,有些是不可见的,所以加一个循环判断,找到可见元素(is_displayed())点击登录即可。
然我们生活在一个宽带无处不在、4/5G 几乎全覆盖的时代,但网站加载缓慢还是常态,就算我们打开一个以文本为中心的新闻网站,都可能需要至少 30 秒才能开始阅读。毕竟在内容膨胀时代,一张照片就能轻易超过 1MB 大小,许多网站为了显示几段文本,还会单独加载至少 10MB 的 JS 和自定义字体。
对此,对优化和极简主义充满热情的资深 Web 开发 Nathaniel 告诉我们,你应该让你的网页尽力控制在 14KB 以内,而且即使对于以富媒体为中心的网站,这条 14KB 的规则可能仍然值得遵循。如果 14KB 不足以用于最终布局,则需要优先考虑“首屏”字节,可以用发送给访问者的前 14KB 数据来渲染一些有用的东西,减少用户还没有开始阅读就流失掉的机会。
网页越小,加载速度就越快——这一点都不奇怪。
但令人感到惊讶的是,14KB 网页的加载速度比 15KB 要快得多——可能快 612 毫秒——而 15KB 和 16KB 网页之间的加载速度差异微乎其微。
这是 TCP 慢启动算法导致的。本文将介绍这个算法、它的原理以及为什么你应该关注它。但首先我们需要快速过一遍一些基础知识。
传输控制协议(Transmission Control Protocol,TCP)是一种使用 IP 协议可靠地发送数据包的方法——有时被称为 TCP/IP。
当浏览器向你的网站(或图像或样式表)发出请求时,它会使用 HTTP 请求。HTTP 建立在 TCP 之上,一个 HTTP 请求通常由许多 TCP 数据包组成。IP 只是一个将数据包从互联网上的一个位置发送到另一个位置的系统。IP 没有检查数据包是否成功到达目的地的方法。
对于网站来说,确保所有的数据到达请求端是非常关键的,否则我们可能会因为丢失数据包无法获得完整的网页。但在网络的其他应用场景中,这一点并不那么重要——比如流媒体直播视频。
TCP 是 IP 的扩展,浏览器和网站服务器通过它告诉对方哪些数据包已经成功到达。
服务器发送一些数据包,然后等待浏览器已经收到数据包的响应(这叫确认或 ACK),然后它继续发送更多的数据包——或者如果它没有收到 ACK,将再次发送相同的数据包。
TCP 慢启动是一种算法,服务器用它来确定一次可以发送多少数据包。
当浏览器第一次连接到服务器时,服务器无法知道它们之间的带宽是多少。带宽是指在单位时间内网络可以传输的数据量。通常以比特/秒(b/s)为单位。我们可以用管道来作类比——把带宽想象成每秒从管道流出多少水。
服务器不知道网络连接可以处理多少数据——所以它先发送少量且安全的数据——通常是 10 个 TCP 数据包。如果这些数据包成功地到达网站访问者,他们的计算机返回确认(ACK),表示数据包已经被收到了。然后,服务器发送更多的数据包,但这一次它将数据包的数量增加了一倍。
这个过程会不断重复,直到数据包丢失,服务器没有收到 ACK。(此时,服务器会继续发送数据包,但速度较慢)。
这就是 TCP 慢启动的要点——在现实当中,虽然算法各不相同,但这是它的基本原理。
大多数 Web 服务器的 TCP 慢启动算法都是从发送 10 个 TCP 数据包开始的。
TCP 数据包最大长度为 1500 字节。这个最大值不是由 TCP 规范设置的,它来自于以太网标准。
每个 TCP 数据包的标头占了 40 个字节,其中 16 个字节用于 IP,另外 24 个字节用于 TCP。
这样每个 TCP 数据包还剩下 1460 个字节。10 x 1460 = 14600 字节,或大约 14KB!
因此,如果你能把网站的网页——或网页的关键部分——压缩到 14KB,就可以为访问者节省大量的时间——他们和网站服务器之间的往返时间。
一个数据往返能有多糟糕?但人们非常没有耐心——一个数据往返可能会出奇地长,具体多长取决于延迟……延迟是指数据包从源传输到目的地所花费的时间。如果带宽是每秒钟可以通过管道的水的数量,那么延迟就是一滴水进入管道后从另一端流出所花费的时间。
下面是一个关于延迟有多糟糕的例子。
卫星网络是由环绕地球轨道的卫星提供的,在人烟稀少的地区、石油钻井平台、游轮以及飞机上,人们可以使用这种网络。
为了说明这种糟糕的延迟,我们想象一群在石油钻井平台工作的兄弟把骰子忘在了家里,他们需要通过 missingdice.com(少于 14KB)来玩《龙与地下城》游戏。
首先,他们中的一个用手机发出一个网页请求……
手机将请求发送到钻井平台的 WiFi 路由器,路由器将数据发送给平台上的卫星天线,我们假设这可能需要 1 毫秒时间。
然后,卫星天线将数据发送到地球轨道上方的卫星。
通常,这是通过在地球表面上方 35786 公里处运行的轨道卫星实现的。光速为 299792458 米/秒,所以信息从地球发送到卫星需要 120 毫秒。然后,卫星将信息传回地面接收站,这又需要 120 毫秒。
然后,地面站必须将请求发送到位于地球任意位置的服务器(当光通过光纤电缆传输时,速度会降至每秒 200000000 米)。如果地面站和服务器之间的距离等于纽约到伦敦之间的距离,那么大约需要 28 毫秒,如果地面站和服务器之间的距离等于纽约到悉尼之间的距离,则需要 80 毫秒——所以我们姑且定一个 60 毫秒的数字(这个数字便于计算)。
然后,服务器需要处理请求,这可能需要 10 毫秒,然后服务器再次将它发送出去。
回到地面站,进入太空,回到卫星天线,然后回到无线路由器,再到手机上。
手机 -> WiFi 路由器 ->卫星天线 ->卫星 -> 地面站 -> 服务器 -> 地面站 -> 卫星 -> 卫星天线 -> WiFi 路由器 -> 手机
如果我们算一下,就是 10 + ( 1 + 120 + 120 + 60 ) x 2 = 612 毫秒。
这是每次往返额外的 612 毫秒——也许这看起来不是很长时间,但你的网站可能只是为了获取第一个资源就需要许多个往返。
另外,HTTPS 在完成第一个往返之前需要额外的两次往返——这使延迟达到了 1836 毫秒!
卫星网络似乎是一个极端的例子——我选择它作为例子是因为它能够充分说明了网络延迟这个问题——但对于生活在陆地上的人来说,延迟可能比这更糟糕,原因有很多。
不稳定的网络连接也会导致数据包丢失——导致需要另一个往返来获取丢失的数据包。
了解了 14KB 法则,接下来可以做些什么
当然,你应该让你的网页尽可能的小——你爱你的访客,你希望他们开心。将每个页面的大小控制在 14KB 以内是一个不错的主意。
这 14KB 可以是压缩数据——所以实际上可以对应大约 50KB 的未压缩数据——这已经非常慷慨了。要知道,阿波罗 11 的制导计算机只有 72KB 内存。
去掉自动播放的视频、弹出窗口、Cookie、Cookie 横幅、社交网络按钮、跟踪脚本、JavaScript 和 CSS 框架,以及所有其他人们不喜欢的垃圾——你可能就能实现 14KB 法则。
假设你已经尽力将所有内容控制在 14KB 以内,但仍然做不到——但 14KB 法则仍然很有用。
你可以用发送给访问者的前 14KB 数据来渲染一些有用的东西——例如一些关键的 CSS、JS 和解释如何使用你的应用程序的前几段文本。
需要注意的是,14KB 法则包含了 HTTP 标头——这些是未压缩的(即使是 HTTP/2 的第一个响应),也包含图片,所以你应该只加载在页面上方的内容,并保持它们最小,或者使用占位符,让访问者知道他们在等待一些更好的内容。
14KB 法则更像是一种经验之谈,而不是计算的基本法则。
有一种观点认为,在使用 HTTP/2 时,14KB 法则不再适用。我已经读了所有我能读到的关于这个问题的东西,但我还没有看到任何证据表明使用 HTTP/2 的服务器已经停止使用 TCP 慢启动(从 10 个数据包开始)。
与 HTTP/2 类似,有一种观点认为 HTTP/3 和 QUIC 将废除 14KB 法则——事实并非如此。实际上,QUIC 仍然建议使用 14KB 法则。
原文链接:
https://endtimes.dev/why-your-website-should-be-under-14kb-in-size/
*请认真填写需求信息,我们会在24小时内与您取得联系。