赞
踩
1.检查python环境
2.在cmd命令窗口,输入pip3 install selenium
3.浏览器驱动安装:由于执行的脚本需要浏览器驱动来驱动浏览器,所以需要安装形影的浏览器驱动
http://chromedriver.storage.googleapis.com/index.html
4.编写第一个selenium脚本,能吊起Chrome浏览器并运行通过即可
#导包 from selenium import webdriver #创建浏览器对象 driver = webdriver.Chrome() #打开百度首页 driver.get("https://www.baidu.com") #在百度的文本框中输入selenium # Target:对谁进行操作?可以使用他们的属性进行定位 # command:找到之后,你要对她干嘛?输入、键入 # value:键入啥?abc driver.find_element_by_id("kw").send_keys("selenium") #点击百度按钮 driver.find_element_by_id("su").click() #关闭浏览器 driver.quit()
在浏览器上能显示的所有要素,如图片、文本框、按钮、下拉列表、视频等。
Selenium Webdriver中提供的了8种页面元素定位方式。
1. id属性定位 --> find_element_by_id(“id属性值”)
最常用的一种元素定位方式,一般情况下ID属性不会重复,
#导包、创建浏览器对象、获取一下url地址 from selenium import webdriver import time #driver:就是一个普通的变量,dr也行 driver = webdriver.Chrome() driver.get("https://www.baidu.com") #通过ID来定位文本框和百度一下 driver.find_element_by_id("kw").send_keys("selenium") time.sleep(2) driver.find_element_by_id("su").click() time.sleep(2) #退出浏览器对象 driver.quit()
2. name属性 —> find_element_by_name(“name属性值”)
#导包、创建浏览器对象、获取一下url地址
from selenium import webdriver
import time
#driver:就是一个普通的变量,dr也行
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
#通过name属性定位元素
driver.find_element_by_name("wd").send_keys("selenium")
time.sleep(2)
driver.find_element_by_id("su").click()
time.sleep(2)
#退出浏览器对象
driver.quit()
3. class 属性定位->find_element_by_class_name(“class属性值”)
对某些具有相同类的元素一网打尽的好方法
4. tag name:->find_element_by_tag_name(“标签名”)
重复率高,定位效率低,基本不用
5. link text:->find_element_by_link_text(“链接的显示文本”)
超链接的显示文本信息,较为常用,参数是全部文本信息。
#导包、创建浏览器对象、获取一下url地址 from selenium import webdriver import time #driver:就是一个普通的变量,dr也行 driver = webdriver.Chrome() driver.get("https://www.baidu.com") #使用link text属性定位(元素显示的文本信息,要求是全部信息) driver.find_element_by_link_text("新闻").click() #等待3s time.sleep(3) #退出浏览器对象 driver.quit()
6. partial link text:->find_element_by_partial_link_text(“部分链接的显示文本”)
超链接的显示文本信息,较为常用,参数是部分文本信息即可
#导包、创建浏览器对象、获取一下url地址 from selenium import webdriver import time #driver:就是一个普通的变量,dr也行 driver = webdriver.Chrome() driver.get("https://www.baidu.com") #使用link text属性定位(元素显示的文本信息,要求是全部信息) driver.find_element_by_link_text("新闻").click() time.sleep(5) #使用partial link text属性定位(元素显示的文本信息,可以是部分信息) driver.find_element_by_partial_link_text("全国首家在线“报销”互联网慢病诊室开通").click() #等待3s time.sleep(3) #退出浏览器对象 driver.quit()
7. xpath:->find_element_by_xpath(“xpath”)
Xpath不是selenium专用,只是作为一种定位手段,为selenium所用。Xpath是一门在xml文档中查找信息的语言。Xpath可用来在xml文档中对元素和属性进行遍历。由于html的层次结构与xml的层次结构天然一致,所以使用Xpath也能够进行html元素的定位。
7.1 绝对路径
以/开头,从HTML标签开始,依次遍历HTML结构数的节点,直到找到要定位的页面元素,
> 如百度首页的百度文本框的绝对路径,一般万不得已不使用。
> 为:/html/body/div/div/div[3]/div/div/form/span/input
> 父子节点是使用/连接,从上往下依次遍历
> 兄弟节点是[]表示兄弟的排行,比如同一级别上有2个以上的input标签,input[2]就是排在第二位的,排行老大可以写为:input或者是input[1]
#导包、创建浏览器对象、获取一下url地址
from selenium import webdriver
import time
#driver:就是一个普通的变量,dr也行
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
#使用绝对路径定位
# driver.find_element_by_xpath("/html/body/div/div/div[3]/div/div/form/span/input").send_keys("selenium")
# time.sleep(2)
# driver.find_element_by_xpath("/html/body/div/div/div[3]/div/div/form/span[2]/input").click()
# time.sleep(2)
driver.quit()
7.2、通过属性定位(相对路径)
一般以//开头,使用属性id、name、class结合xpath进行定位,如百度文本框的定位:
> //input[@id='kw']
//input[@name='wd']
//input[@class='bg s_btn']
在一个属性不能定位到元素的时候,可以逻辑运算符的使用。
#导包、创建浏览器对象、获取一下url地址 from selenium import webdriver import time #driver:就是一个普通的变量,dr也行 driver = webdriver.Chrome() driver.get("https://www.baidu.com") #利用元素属性定位 # driver.find_element_by_xpath("//input[@id='kw']").send_keys("selenium") # time.sleep(2) # driver.find_element_by_xpath("//input[@id='su']").click() # time.sleep(2) #使用逻辑运算符 driver.find_element_by_xpath("//input[@id='kw' or @name = 'wd']").send_keys("selenium") time.sleep(2) driver.find_element_by_xpath("//input[@id='su']").click() time.sleep(2) driver.quit()
7.3 通过父子关系和属性定位
假设某个标签就一个标签名,其他属性一概没有(或者有一个class name,而且是重复的)
使用绝对路径没问题,就是复杂点
使用属性定位,就不靠谱了,定位不到
#导包、创建浏览器对象、获取一下url地址
from selenium import webdriver
import time
#driver:就是一个普通的变量,dr也行
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
# 利用父子关系以及属性定位:
# driver.find_element_by_xpath("//form[@id='form']/span/input").send_keys("selenium")
# time.sleep(2)
# driver.find_element_by_xpath("//form[@id='form']/span[2]/input").click()
# time.sleep(2)
driver.quit()
7.4 直接Chrome浏览器复制
8. css:---->find_element_by_css_selector(“css”)(掌握)
#导包、创建浏览器对象、获取一下url地址 from selenium import webdriver import time #driver:就是一个普通的变量,dr也行 driver = webdriver.Chrome() driver.get("https://www.baidu.com") #css的类选择器定位百度文本框,使用css的id选择器定位百度一下按钮 # driver.find_element_by_css_selector(".s_ipt").send_keys("selenium") # driver.find_element_by_css_selector("#su").click() driver.find_element_by_css_selector("form#form > span > input#kw").send_keys("selenium") driver.find_element_by_css_selector("#su").click() time.sleep(3) driver.quit()
WebDriver提供了以下三种API用于调整窗口大小:
17. Set_window_size():方法来设置浏览器的大小
18. minimize_window():最大化显示
19. minimize_window():最小化显示,在最小化情况下,也可以进行元素定位及操作
#导包、创建浏览器对象、获取一下url地址 from selenium import webdriver import time #driver:就是一个普通的变量,dr也行 driver = webdriver.Chrome() driver.get("https://www.baidu.com") #比较喜欢宽屏显示,我也要设置打开的窗口为:1920 * 600 #driver是浏览器对象 # windowHandle:一个页面的标识 # driver.set_window_size(1920,600) #最大化显示窗口 # driver.maximize_window() # 最小化 # time.sleep(2) # driver.minimize_window() # time.sleep(2) # driver.find_element_by_id("kw").send_keys("selenium") # driver.maximize_window() #退出浏览器对象 # driver.quit()
在使用浏览器浏览网页时,浏览器提供了后退和前进按钮,可以方便的在浏览过的页面之间来回切换、刷新等,WebDriver也提供了对应的:
20. back():后退
21. forward():前进
22. refresh():刷新
#导包、创建浏览器对象、获取一下url地址 from selenium import webdriver import time #driver:就是一个普通的变量,dr也行 driver = webdriver.Chrome() driver.get("https://www.baidu.com") #页面的前进后退操作 # driver.find_element_by_link_text("新闻").click() # time.sleep(2) # #后退到百度首页 # driver.back() # time.sleep(2) # #再前进到新闻页面 # driver.forward() # time.sleep(2) # #再执行一次刷新操作 # driver.refresh() #退出浏览器对象 # driver.quit()
将运行的页面截图保存在本地,推荐使用png格式:
23. driver.save_screenshot(r"e:\abc.png")
24. driver.get_screenshot_as_file(“{}.{}”.format(“e:/aaa”,“png”))
25. driver.get_screenshot_as_file(r"e:\abc.png")
#导包、创建浏览器对象、获取一下url地址
from selenium import webdriver
import time
#driver:就是一个普通的变量,dr也行
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
# driver.save_screenshot(r"e:\sss.png")
# driver.get_screenshot_as_file("{}.{}".format("e:/aaa","png"))
# driver.get_screenshot_as_file(r"e:\sss.png")
#退出浏览器对象
# driver.quit()
webdriver提供两种关闭的方法:
26. quit():关闭浏览器,不管页面有几个窗口,一概关掉
27. close():只关掉了一个当前的窗口,而且关掉的是前面的一个
每一个页面都一个句柄(handle)值,对一个页面来说是唯一,是页面的一个标识webdriver进行自动化测试,需要将driver绑定到页面句柄,你的driver只能控制你绑定句柄的这个页面,因此对不不同的窗口页面的元素,driver就不能操作了,下面就看如何解决这种多窗口问题。
获取句柄的方式:
1.driver.current_window_handle: 获取当前页面的句柄
28. driver.window_handles:获取所有打开窗口的句柄
实现需求:淘宝首页->聚划算->女装
29. 拿到聚划算的句柄,返回的是一个列表
handles = driver.window_handles
30. 将句柄绑定给driver,参数是列表中聚划算页面的句柄,x为0表示浏览器中的第一个窗口,1表示第二个窗口,-1表示最后一个窗口。
driver.switch_to_window(handles[x]) #导包、创建浏览器对象、获取淘宝的首页 from selenium import webdriver import time driver = webdriver.Chrome() driver.get("https://www.taobao.com") #等待两秒钟 time.sleep(2) #获取当前页面的句柄 # CDwindow-AA8085746F56C04363172064996E1A52 handler1 = driver.current_window_handle print(handler1) # 2、点击聚划算,进入聚划算页面。 driver.find_element_by_link_text("聚划算").click() #等待两秒钟 time.sleep(2) #第一步:获取所有打开窗口的句柄 handlers = driver.window_handles # ['CDwindow-AA8085746F56C04363172064996E1A52', 'CDwindow-FD84D68BEFF3DBFFB64A5AC48E4F1703'] print(handlers) #第二步:将聚划算的句柄绑定给driver driver.switch_to_window(handlers[1]) # 3、选择“女装”,进入女装页面。 driver.find_element_by_link_text("女装").click() #等待两秒钟 time.sleep(2) # 4、返回到聚划算页面。 driver.back() #等待两秒钟 time.sleep(2) #关闭当前窗口(driver所绑定的哪个窗口) driver.close()
使用 Selenium WebDriver 做web自动化测试的时候,会经常模拟鼠标和键盘的一些行为:
比如使用鼠标单击、双击、右击、拖拽、悬浮等动作
或者键盘输入、快捷键使用、组合键使用等模拟键盘的操作
在 WebDeriver 中,有专门的类来负责实现这些测试场景,那就是 ActionChains和Keys类。
ActionChains类中封装了对鼠标事件操作的方法,常见方法有:
context_click() 右击 --> 此方法模拟鼠标右键效果
double_click() 双击 --> 此方法模拟鼠标双击效果
drag_and_drop() 拖动 --> 此方法模拟鼠标拖动效果
move_to_element() 悬停 --> 此方法模拟鼠标悬停效果
perform() 执行 --> 此方法用来执行封装在ActionChains的行为
在ActionChains类中所有提供的鼠标事件方法,在调用的时候所有的行为都存储在ActionChains类中,需要调用perform()方法才能真正执行。
导包:rom selenium.webdriver.common.action_chains import ActionChains
封装鼠标事件到ActionChains中
执行ActionChains中封装的的行为
1、鼠标悬浮和点击
#导包、创建浏览器对象、获取百度的首页 from selenium import webdriver #导入鼠标事件的ActionChains类 from selenium.webdriver.common.action_chains import ActionChains import time driver = webdriver.Chrome() driver.get("https://www.baidu.com") driver.maximize_window() # 案例1:控制鼠标悬浮到百度首页“设置”按钮上 # setButton = driver.find_element_by_xpath('//*[@id="s-usersetting-top"]') # 将对“设置”按钮的操作行为封装到ActionChains # element = ActionChains(driver).move_to_element(setButton) # 并调用perform方法执行悬浮操作 # element.perform() # 案例2:在百度文本框中鼠标右键 webEdit = driver.find_element_by_id("kw") element = ActionChains(driver).context_click(webEdit) element.perform() time.sleep(5) driver.quit()
2、鼠标拖拽动作
方法的格式:drag_and_drop(source,target)
from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains from time import sleep driver = webdriver.Firefox() url = "http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable" driver.get(url) #切换到目标元素所在的frame driver.switch_to.frame("iframeResult") #确定拖拽目标的起点 source = driver.find_element_by_id("draggable") #确定拖拽目标的终点 target = driver.find_element_by_id("droppable") #执行动作 actions = ActionChains(driver) actions.drag_and_drop(source,target) #执行 actions.perform() sleep(5)
Keys中封装了键盘上的按键或者组合键的字段,sendkeys()方法可以用来模拟键盘输入,除此之外还可以使用sendkeys方法发送文件到服务器(上传功能以input标签实现),常见的键盘事件操作有:
键盘事件使用步骤:
##导包、创建浏览器对象、获取一下url地址 from selenium import webdriver from selenium.webdriver.common.keys import Keys import time #driver:就是一个普通的变量,dr也行 driver = webdriver.Chrome() driver.get("https://www.baidu.com") # 1、百度“seleniumm” driver.find_element_by_id("kw").send_keys("seleniumm") time.sleep(1) # 2、删除多输入的m driver.find_element_by_id("kw").send_keys(Keys.BACK_SPACE) time.sleep(1) # 3、再输入“空格 教程”,再次发送字符串,是和前面的进行拼接 driver.find_element_by_id("kw").send_keys(" 教程") time.sleep(1) # 4、ctrl+a,全选文本框内容 driver.find_element_by_id("kw").send_keys(Keys.CONTROL,"a") time.sleep(1) # 5、ctrl+x,剪切选择的内容 driver.find_element_by_id("kw").send_keys(Keys.CONTROL,"x") time.sleep(1) # 6、ctrl+v,粘贴复制的内容 driver.find_element_by_id("kw").send_keys(Keys.CONTROL,"v") time.sleep(1) # 7、回车代替单击,完成搜索 driver.find_element_by_id("kw").send_keys(Keys.ENTER) time.sleep(1) # 8、退出浏览器 driver.quit()
在一个页面中可以嵌套另外一个页面,如frame/iframe技术,这是现在很多web应用中使用的一种方式,webdriver对象只能在一个页面(外层是默认的)中定位元素,需要一种方式将driver对象从外层切换给内层使用才能对内层的对象进行处理。
下图是qq邮箱登录页面,其中的登录框就是一个内嵌的frame页面,下面我们就以他为案例。
webdriver中提供的对iframe/frame操作API常用到有:
从外部页面切入frame框架中,参数可以为id/name/index及页面元素对象。
第一种方式:默认是可以给ID、name的
#导包、创建浏览器对象、打开qq首页 from selenium import webdriver import time driver = webdriver.Chrome() # 1.打开腾讯首页;http://www.qq.com driver.get("https://www.qq.com") # 2.点击邮箱图标; driver.find_element_by_link_text("Qmail").click() # 跳转到邮箱登录界面(窗口),涉及到多窗口的处理 handles = driver.window_handles driver.switch_to.window(handles[1]) #现在先验证窗口跳转是否成功 # driver.find_element_by_link_text("基本版").click() # 3.输入用户名 #webdriver中提供API:driver.switch_to.frame()实现frame的切换 #第一种方式,默认是可以给ID或者name的 # driver.switch_to.frame("login_frame") #第二种方式,可以传参iframe的元素对象 # iframeObj = driver.find_element_by_xpath('//*[@id="login_frame"]') # driver.switch_to.frame(iframeObj) #第三种方式,可以给索引号 driver.switch_to.frame(1) driver.find_element_by_link_text('帐号密码登录').click() driver.find_element_by_xpath('//*[@id="u"]').send_keys("2572612580") time.sleep(2) # 4.输入密码; driver.find_element_by_xpath('//*[@id="p"]').send_keys("123456789") time.sleep(2) # 5.点击登录; driver.find_element_by_xpath('//*[@id="login_button"]').click() time.sleep(2) # 6.关闭浏览器。 driver.quit()
切到frame中之后,我们便不能继续操作主文档的元素,这时如果想操作主文档内容,则需切回主文档。
如果frame/iframe有多层,我们可以通过driver.switch_to.frame()一层层切入到内层,并可以通过driver.switch_to.parent_frame()一层层再退出来,相当于前进、后退。
相对driver.switch_to.default_content()方法,是一层层退回,而不是直接退回主页面
driver.switch_to.frame(“frame1”) #从主页面切入到frame1,相当于前进
driver.switch_to.frame(“frame2”) #从frame1再切入到frame2,相当于前进
driver.switch_to.parent_frame() #返回到上级frame1,相当于后退
driver.switch_to.parent_frame() #返回到主页面
webdriver处理javascript生成的alert、confirm、prompt消息框的方式十分简单,都是统一使用switch_to.alert将driver的控制权限交给消息框,然后再调用相应方法进行操作:
alert 方法生成的警告消息框提供了一个“确定”按钮让用户关闭该消息框,并且该消息框是模式对话框,也就是说,用户必须先关闭该消息框然后才能继续进行操作。
案例:百度搜索设置中,保存后弹出警告框,确认接收该提示信息。
#导包、创建浏览器对象、获取百度的首页 from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains import time driver = webdriver.Chrome() driver.get("https://www.baidu.com") #控制鼠标悬浮到“设置”按钮上 setButton = driver.find_element_by_xpath('//*[@id="s-usersetting-top"]') ActionChains(driver).move_to_element(setButton).perform() driver.find_element_by_link_text("搜索设置").click() time.sleep(3) #时间等待的作用,如果不加的话可能会元素定位失败 # driver.find_element_by_xpath('//*[@id="SL_0"]').click() # time.sleep(2) # driver.find_element_by_xpath('//*[@id="nr"]/option[2]').click() # time.sleep(2) #点击保存设置按钮,弹出一个警告框 driver.find_element_by_link_text("保存设置").click() time.sleep(2) #就可以对他做操作啦,由于版本问题,switch_to.alert dd = driver.switch_to.alert #获取alert里面的文本信息 tt = dd.text #已经记录下您的使用偏好 print(tt) time.sleep(2) #接受窗口信息(确定这个文本框) # dd.accept() dd.dismiss() #退出浏览器对象 driver.quit()
使用确认消息框可向用户问一个“是-或-否”问题,并且用户可以选择单击“确定”按钮或者单击“取消”按钮。confirm 方法的返回值为 true 或 false。该消息框也是模式对话框:用户必须在响应该对话框(单击一个按钮)将其关闭后,才能进行下一步操作。
案例:复制下面html代码,保存在本地的文本文件中,并将文件重命名为:confirm.html,文件保存在:e:\confirm.html
<html> <head> <script type="text/javascript"> function show_confirm() { var r=confirm("Press a button!"); if (r==true) { alert("You pressed OK!"); } else { alert("You pressed Cancel!"); } } </script> </head> <body> <input type="button" onclick="show_confirm()" value="Show a confirm box" /> </body> </html>
编写自动化测试脚本,处理该确认消息框:
from selenium import webdriver import time driver = webdriver.Chrome() driver.get("file:///E:/confirm.html") #点击页面的:show a confirm box driver.find_element_by_xpath('/html/body/input').click() #driver对象切换到confirm提示框 aaa = driver.switch_to.alert #点击确认消息框的确定按钮或者取消按钮 # aaa.accept() aaa.dismiss() time.sleep(5) #点击后续弹出的alert窗口的确定按钮 aaa.accept() time.sleep(5) #退出浏览器对象 driver.quit()
提示消息框提供了一个文本字段,用户可以在此字段输入一个答案来响应您的提示。该消息框有一个“确定”按钮和一个“取消”按钮。
案例:复制下面html代码,保存在本地的文本文件中,并将文件重命名为:prompt.html,文件保存在:e:\prompt.html
<html> <head> <script type="text/javascript"> function disp_prompt() { var name=prompt("请输入您的名字","Bill Gates") if (name!=null && name!="") { document.write("你好," + name + "!今天过得好吗?") } } </script> </head> <body> <input type="button" onclick="disp_prompt()" value="显示一个提示框" /> </body> </html>
编写自动化测试脚本,处理该提示消息框prompt:
from selenium import webdriver import time driver = webdriver.Chrome() driver.get("file:///E:/prompt.html") #点击页面的按钮:先是一个提示框 driver.find_element_by_xpath('/html/body/input').click() #driver对象切换到prompt提示框 aaa = driver.switch_to.alert #使用提示消息框的send_keys()方法 aaa.send_keys("捉虫布道人") time.sleep(5) #使用提示消息框的确认accept()方法及取消dismiss()方法 aaa.accept() # aaa.dismiss() time.sleep(3) driver.quit()
元素等待:如今很多web都在使用AJAX技术,运用这种技术的软件当浏览器加载页面时,页面上的元素可能不会被同步加载完成,如此一来,定位元素时就会出现困难,我们可以通过设置元素等待来改善这类问题导致的测试脚本不稳定。
WebDriver脚本开发中可以使用三种种元素等待方式:
time.sleep(5),单位是s,就是直接让线程休眠,这几秒啥事也不用干
import time #导入时间模块
time.sleep(5) #休眠5s钟
在脚本创建driver对象之后,给driver设置一个全局的等待时间,对driver的整个生命周期(创建到关闭)都起效。如果在设置等待时间(超时时间)内,定位到了页面元素,则不再等待,继续执行下面的代码如果超出了等待时间,则抛出异常TimeoutException。
driver.implicity_wait(10):默认是0s等待,设置之后的值是最大超时时间
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('http://www.baidu.com')
# 隐式等待,设置10s的超时时间
driver.implicitly_wait(10)
注意:在使用隐式等待的时候,实际上浏览器会在你自己设定的时间内部不断的刷新页面去寻找我们需要的元素,在使用AJAX技术的页面自动化测试中,建议使用。
就是明确的要等到某个元素的出现或者是某个元素的可点击等条件,等到就可以返回元素对象;在超时时间到达之后仍未等到,那么就抛出TimeoutException。(简而言之,就是直到元素出现才去操作,如果超时则报异常)。
先来看一下显式等待的语法,然后我们在分别解析:
element = WebDriverWait(driver,10,0.5,ignored_exceptions=None).until(EC.presence_of_element_located((By.ID,“kw”)),“找不到”)
该WebDriverWait类中提供两个方法用于处理等待的条件:
隐式等待的案例
需求,等待百度首页百度一下是否被加载(加载到DOM),成功则返回元素对象并执行点击操作,否则抛出异常。
from selenium import webdriver #ui--模块,WebDriverWait是个类 from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By import time driver = webdriver.Chrome() # driver.implicitly_wait(10) driver.get("http://www.baidu.com") try: driver.find_element_by_id("kw").send_keys("selenium") element = WebDriverWait(driver,10,0.5,ignored_exceptions=None).until(EC.presence_of_element_located((By.ID,"su")),"找不到") element.click() time.sleep(3) except Exception as e: print(e) driver.quit()
若同时设置了隐式等待和显示等待,则以隐式等待为第一优先级,也就是说,若隐式等待时间大于显示等待,显示等待时间设置无效,因为driver若找不到元素,会先等待隐式等待的时间
time.sleep()是强制休眠,只要执行到这句代码,就会等待
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。