Selenium学习

selenium安装配置

  1. Python安装

  2. selenium客户端库

    # win
    pip install selenium
    # mac
    sudo pip3 install selenium
    
    
    • 验证是否安装成功
      控制台输入命令pip list 查看列表中是否存在selenium,如果有,则说明安装成功。

      image
  3. 谷歌浏览器驱动chromedriver notes.txt文件可以查看对应的chrome版本

  4. 将浏览器驱动文件(chromedriver.exe)放到环境变量中配置的路径内

    1. 如果不放入环境变量,则每次使用时需填写浏览器驱动文件所在的路径
    2. 必须为系统的环境变量,临时设置的环境变量无效
    3. 快速设置:mac 可以把浏览器驱动文件放到/usr/local/bin
    4. 快速设置:win 可以把浏览器驱动文件放到C:\Windows
    # 在系统环境变量中
    from selenium import webdriver
    # driver = webdriver.Chrome(chromedriver)
    driver = webdriver.Chrome()
    driver.get('https://www.baidu.com/')
    
    # 不在系统环境变量中
    from selenium import webdriver
    test = r'E:/python/chromedriver'
    driver = webdriver.Chrome(test)
    driver.get('https://www.baidu.com/')
    
    
  5. 补充:安装三大浏览器驱动(driver)

    • chromedriver 下载地址:参考第三点
    # 启动谷歌浏览器
    from selenium import webdriver
    browser = webdriver.Chrome()
    browser.get('http://www.baidu.com/') 
    
    
    # 启动火狐浏览器
    from selenium import webdriver
    browser = webdriver.Firefox()
    browser.get('http://www.baidu.com/')
    
    
    # 启动IE浏览器
    from selenium import webdriver
    browser = webdriver.Ie()
    browser.get('http://www.baidu.com/')
    
    
  6. 简单操作方法

    • 导入from selenium import webdriver
    • 打开浏览器driver = webdriver.Chrome()
    • get方法打开指定网址driver.get('https://www.baidu.com/')
    • 通过id获取元素element_keyword = find_element_by_id('kw')
    • 对输入框输入文字内容element_keyword.send_keys('松勤')
    • 对按钮进行点击element_search_button.click()
    • 获取某个元素的内容one_yuansu.text
    • 关闭浏览器driver.quit()
    • 设置浏览器固定宽、高driver.set_window_size(480,800)
    • 控制浏览器前进、后退:前进driver.forward()后退driver.back()
    • 示例如下:
    from selenium import webdriver
    driver = webdriver.Chrome()
    #get方法打开指定网址
    driver.get('https://www.baidu.com/')
    
    # 查找到那个搜索输入栏网页元素,返回一个表示该元素到WebElement对象
    element_keyword = driver.find_element_by_id('kw')
    # 输入字符
    element_keyword.send_keys('测试')
    
    # 找到搜素按钮
    element_search_button = driver.find_element_by_id('su')
    # 点击该按钮
    element_search_button.click()
    import time
    time.sleep(2)# 设置等待时间
    ret = driver.find_element_by_id('1') # 获取第一条信息
    print(ret.text)
    
    # if ret.text.startswith('松勤'):
    #     print('测试通过')
    # else:
    #     print('测试不通过')
    
    # 退出(关闭浏览器)
    driver.quit()
    
    # 控制台输出效果
    测试_百度百科
    测试英文名Test、Measure;中文拼音cè shì;由中文“测”与中文“试”两个字组成的词语。是动词、名词。测试行为,一般发生于为检测特定的目标是否符合标准而采用专用的工具或...
    词语 综合式测试 心理测试
    baike.baidu.com/
    
    

元素选择之常规方法

Selenium 选择、操作web元素01

Selenium 自动化主要就是:

  • 选择界面元素依靠selenium库 难点
  • 操作界面元素依靠selenium库
    • 输入操作:点击、输入文字、拖拽等
    • 输出操作:获取元素的各种属性
  • 根据界面上获取的数据进行分析和处理依靠编程语言,例如Python等 难点

选择元素

  • WebDriver:操作整个浏览器和当前整个页面
    • 当前页面上的选择符合查找条件的对象
    • 打开网址,回退,前进,刷新网页
    • 获取、改变浏览器窗口大小,关闭浏览器,截屏
    • 获取、设置cookies
  • WebElement:操作和对应web元素
    • 当前web元素的所有子元素里面符合查找条件的对象
    • 操作该web元素,比如
      • 点击元素
      • 输入字符
      • 获取元素坐标、尺寸、文本内容、其他的属性信息
通过id选择元素
  • id是DOM中唯一标志这个元素的属性

    • 查找效率高
    • 写法一:element = driver.find_element_by_id("kw")
    • 写法二:
    from selenium.webdriver.common.by import By
    element = driver.find_element(by=By.ID,value="kw")
    
    
  • 没有找到id时将报错selenium.common.exceptions.NoSuchElementException

  • 没有id时,可以通过根据上层的id,然后获取内部的源代码,然后找到相关信息(str)

    当开发做一定的变动时,此方法就失效了

  • 没有id时,使用BeautifulSoup4详见后续内容

获取元素信息
  • text属性显示该元素在web页面显示出来的文本内容

  • get_attribute方法非界面值

    • 某个属性的值ele.get_attribute('href')
    • 该元素对应的html源代码ele.get_attribute('outerHTML')

    出现问题时,将相关源代码打印到日志里,以便快速定位问题

    • 该元素的内部部分的html源代码ele.get_attribute('innerHTML')

Selenium 选择、操作web元素02

选择元素的方法

通过name选择元素 id是唯一的,name不一定是唯一的

<input name='cheese' type='text'/>

  • 返回第一个找到的元素如果找不到,抛出异常
# 方法一:
cheese = driver.find_element_by_name('cheese')
# 方法二:
from selenium.webdriver.common.by import By
cheeses = driver.find_emement(By.NAME,'cheese')

# 示例
from selenium import webdriver
driver = webdriver.Chrome()
driver.get(r'file:///E:/Python/tmp/own/test.html')
button = driver.find_element_by_name('button')
print(button.text)
# 执行结果
按钮01

#找不到时
from selenium import webdriver
driver = webdriver.Chrome()
driver.get(r'file:///E:/Python/tmp/own/test.html')
try:
    button = driver.find_element_by_name('button4')
    print(button.text)
except:
    print('未找到')
# 执行结果
未找到

  • 返回所有的元素(list)如果找不到,返回空列表,不抛出异常
# 方法一:
cheese = driver.find_elements_by_name('cheese')
# 方法二:
from selenium.webdriver.common.by import By
cheeses = driver.find_emements(By.NAME,'cheese')

# 示例
from selenium import webdriver
driver = webdriver.Chrome()
driver.get(r'file:///E:/Python/tmp/own/test.html')
button = driver.find_elements_by_name('button')
for a in button:
    print(a.text)
# 执行结果
按钮01
按钮02
按钮03

通过class选择元素非唯一值,通常用来选择多个元素

  • 返回所有的元素(list)
cheeses = driver.find_elements_by_class_name('cheese')

通过tag名选择元素

  • 如果tag名是唯一的,可以根据tag名定位
  • 如果tag名不是唯一的,返回到是第一个
frame = driver.find_element_by_tag_name('iframe')

通过链接文本选择元素

  • 对于链接,可以通过其链接文本的内容<a href="http://www.baidu.com">转到百度</a>
ele = driver.find.element_by_link_text("转到百度")

  • 只通过部分文本去找到该链接元素适用于文本内容过长时
ele = driver.find.element_by_partial_link_text(u"百度") # 此处可以不写u,python2中此处的“u”必写

页面操作(补充)

学习地址

查找时间

  • 每半秒查找一次,直到10秒后 driver.implicitly_wait((10))
  • 强制睡眠10秒
import time
time.sleep(10)

模拟回车键enter的操作

  • 使用\n方法
from selenium.webdriver.common.keys import Keys
driver.find_element_by_id('toStationText').send_keys('杭州东\n')

  • 使用enter方法
from selenium.webdriver.common.keys import Keys
driver.find_element_by_id('toStationText').send_keys('杭州东')
driver.find_element_by_id('toStationText').send_keys(Keys.ENTER)  # 模拟键盘enter

页面交互

WebDriver提供了各种方法来寻找元素。例如下面有一个表单输入框。

<input type="text" name="passwd" id="passwd-id" />

element = driver.find_element_by_id("passwd-id")
element = driver.find_element_by_name("passwd")
element = driver.find_elements_by_tag_name("input")
element = driver.find_element_by_xpath("//input[@id='passwd-id']")

获取了元素之后,下一步当然就是向文本输入内容了,可以利用下面的方法

element.send_keys("some text")

同样你还可以利用 Keys 这个类来模拟点击某个按键

element.send_keys("and some", Keys.ARROW_DOWN)

可以用下面的方法来清除输入文本的内容。

element.clear()

填充表单

元素选择之BeautifulSoup4

BeautifulSoup4

  • BS是可以从HTML或XML文件中提取数据的库

  • Selenium可以用来远程获取数据

  • 有的时候,感觉用Selenium获取某些元素数据不太方便

  • 可以将其父节点的html获取回来,利用BS在本地做分析

  • 我们可以将它和selenium两种技术融合使用,达到我们的目的

  • 安装BeautifulSoup4

    pip install beautifulsoup4
    # pip install beautifulsoup4 -i https://pypi.douban.com/simple/
    pip install html5lib
    
    
  • 常见用法(详见示例内的代码及注释)

    • 示例及具体方法
    # 本例采用的是本地的html
    with open ('test.html',encoding = 'utf8') as f :
        html_doc = f.read()
    # 导入beautifulsoup
    from bs4 import BeautifulSoup
    
    # 指定html5lib来解析html文档
    soup = BeautifulSoup(html_doc,'html5lib')
    
    print(soup.title) # 获取标签整体内容
    print(soup.p)# 有多个时,获取的是第一个
    print(soup.title.name) # 获取标签名称
    print(soup.title.string) # 获取点前节点标签的内容
    print(soup.title.get_text()) # 获取当前节点及子节点的所有内容
    print(soup.body.get_text("|")) # 获取当前节点及子节点的所有内容,以|分隔每个节点的内容
    print(soup.title.parent)# 获取当前节点及父节点的内容
    
    print(soup.body['style']) # 获取属性值
    print(soup.body.get('style')) # 获取属性值
    
    # 有多个标签想获取非第一个
    # 方法一;先返回所有的,在根据下标查找
    print(soup.find_all('p')) #返回的是一个列表所以可以使用列表获取元素的方法
    print(soup.find_all('p')[1]) # 根据下标获取第二个
    # 方法二:根据属性找
    print(soup.find_all('p',id='b')) # 根据id获取第二个
    
    # 执行结果
    
    <title>测试</title>
    <p id="a">第一个p</p>
    title
    测试
    测试
    
    |
    标题1
    |
    |
    标题2
    |
    |第一个p|
    |第二个p|
    |第三个p|
    
    <head>
    <title>测试</title>
    </head>
    background-color: yellow
    background-color: yellow
    [<p id="a">第一个p</p>, <p id="b">第二个p</p>, <p id="c">第三个p</p>]
    <p id="b">第二个p</p>
    [<p id="b">第二个p</p>]
    
    
    • 演示文件
    # html文件(本地)
    <html>
    <head>
    <title>测试</title>
    </head>
    <body style='background-color: yellow'>
    <h1 >
    标题1
    </h1>
    <h2 style = 'background-color:green;text-align:center'>
    标题2
    </h2>
    <p id ='a'>第一个p</p>
    <p id = 'b'>第二个p</p>
    <p id = 'c'>第三个p</p>
    </body>
    </html>
    
    

元素选择之css

语法

  • # 选择单个元素
    driver.find_element_by_css_selector('...')
    # 选择多个元素
    driver.find_elements_by_css_selector('...')
    
    

子元素(child)选择器

  • 选择元素的子元素(直接子节点)

    • 对比:后代选择器(非直接子节点)
    #choose_car option
    
    
    • 语法举例
    #choose_car > option
    footer > p
    
    
    • 可以是很多级
    ul > ol > li > em
    
    
  • 组选择:同时选择多个元素,逗号隔开,

    • 语法:<s1>,<s2>
    • 举例:
    p,button
    #food,.cheese
    
    
    • 组合使用

      • 选择id为food的所有span子元素和所有的p(包括非food的子元素)
      #food >span, p
      
      
      • 选择id为food的:所有span子元素和所有的p子元素
      #food > span,#food > p
      
      
      • 选择id为food的所有子元素
      #food > *
      
      

兄弟节点选择

  • 选择紧跟在另一个元素后的元素,二者有相同的父元素 +

    • 举例
    #food + div
    #many > div > p.special + p
    
    
  • 选择在另一个元素后的元素,二者有相同的父元素~

    • 举例
    #food ~ div
    
    

属性选择器

  • 可以根据元素的属性及属性值来选择元素

    • 举例
    *[style] # 选择所有的元素中属性中含style的元素
    p[spec = len2] # 选择元素p的属性spec=len2的元素(spec ='len2 len3'时,不会选中)
    p[spec = 'len2 len3'] 
    p[spec* = 'len2'] # 选择元素p的属性spec包含len2的元素(spec ='len2 len3'时,也会选中)
    p[spec^ = 'len2'] # 选择元素p的属性spec以len2开头的元素(spec ='len2 len3'时,也会选中)
    p[spec$ = 'len2'] # 选择元素p的属性spec以len2结尾的元素(spec ='len2 len3'时,不会选中)
    p[class = special][name = p1] #  选择元素p的属性class = special,同时name = p1的元素
    
    

编辑框的一些操作

    • 用clear方法清楚该元素里面的字符串
    input1.clear()
    
    
    • 输入内容
    input1.sed_keys('xxxx')
    
    
    • 获取input元素里面输入的文本内容
    input1.get_attribute('value')
    
    

单选框-选择单个

    • 对应的html
    <input type='radio' name='gender' value='male'>男<br>
    <input type='radio' name='gender' value='female'>女<br>
    
    
    • click方法选择
    • 不管原来该元素是否选中,直接去点击该元素没有问题,都可以确保该单选框选中
    • 示例
    input1 = driver.find_element_by_css_selector('input[value=male]')
    input1.click()
    
    

勾选框-可选择多个

    • 对应的html
    <input type='checkbox' name='vehicle' value='bike'>自行车<br>
    <input type='checkbox' name='vehicle' value='car'>汽车<br>
    
    
    • click方法选择
    • is_selected方法来获取选择的状态
    • 示例
    input1 = driver.find_element_by_css_selector('input[value=car]')
    # 判断是否已经被选中
    selected = input1.isselected()
    if selected:
        print('car already selected')
    else:
        print('car not selected,click on it')
        input1.click()
    
    

复选框

    • 对应的html
    # 按住ctrl可多选
    <select id='multi' multiple>
        <option value='benz'>奔驰S300</option>
        <option value='accord'>雅阁</option>
        <option value='aa'>测试aa</option>
        <option value='bb'>测试bb</option>
    </select>
    # 单选
    <select id='single'>
        <option value='male'>男</option>
        <option value='female' selected='selected'>女</option>
    </select>
    
    
    • Select类
    • 方法deselect_all
    • 方法select_by_visible_text
    • 示例
    # 导入Select
    from selenium.webdriver.support.ui import Select
    # 获得相应的WebElement
    select = Select(driver.find_element_by_id('multi'))
    # 先去选择所有的选项
    select.deselect_all()
    select.select_by_visible_text('雅阁')
    select.select_by_visible_text('奔驰S300')
    
    # 获得相应的WebElement
    select = Select(driver.find_element_by_id('single'))
    select.select_by_visible_text('男')
    
    

补充01:点击查看selenium之下拉选择框Select 相关补充内容

  • Select提供了三种选择方法:

    • select_by_index(index) ——通过选项的顺序,第一个为 0
    • select_by_value(value) ——通过value属性
    • select_by_visible_text(text) ——通过选项可见文本
  • Select提供了四种方法取消选择:

    • deselect_by_index(index)
    • deselect_by_value(value)
    • deselect_by_visible_text(text)
    • deselect_all()
  • Select提供了三个属性方法给我们必要的信息:

    • options ——提供所有的选项的列表,其中都是选项的WebElement元素
    • all_selected_options ——提供所有被选中的选项的列表,其中也均为选项的WebElement元素
    • first_selected_option ——提供第一个被选中的选项,也是下拉框的默认值

补充02:点击CSS3 选择器进入原内容界面查看

  • 在 CSS 中,选择器是一种模式,用于选择需要添加样式的元素。
  • "CSS" 列指示该属性是在哪个 CSS 版本中定义的。(CSS1、CSS2 还是 CSS3。)
  • 选择属于其父元素的第二个子元素的每个 <p> 元素。p:nth-child(2)

数字跟元素类型无关,仅表示父元素下的第几个元素

选择器 例子 例子描述 CSS
.class .intro 选择 class="intro" 的所有元素。 1
#id #firstname 选择 id="firstname" 的所有元素。 1
* * 选择所有元素。 2
element p 选择所有 <p> 元素。 1
element,element div,p 选择所有 <div> 元素和所有 <p> 元素。 1
element element div p 选择 <div> 元素内部的所有 <p> 元素。 1
element>element div>p 选择父元素为 <div> 元素的所有 <p> 元素。 2
element+element div+p 选择紧接在 <div> 元素之后的所有 <p> 元素。 2
[attribute] [target] 选择带有 target 属性所有元素。 2
[attribute=value] [target=_blank] 选择 target="_blank" 的所有元素。 2
[attribute~=value] [title~=flower] 选择 title 属性包含单词 "flower" 的所有元素。 2
:link a:link 选择所有未被访问的链接。 1
:visited a:visited 选择所有已被访问的链接。 1
:active a:active 选择活动链接。 1
:hover a:hover 选择鼠标指针位于其上的链接。 1
:focus input:focus 选择获得焦点的 input 元素。 2
:first-letter p:first-letter 选择每个 <p> 元素的首字母。 1
:first-line p:first-line 选择每个 <p> 元素的首行。 1
:first-child p:first-child 选择属于父元素的第一个子元素的每个 <p> 元素。 2
:before p:before 在每个 <p> 元素的内容之前插入内容。 2
:after p:after 在每个 <p> 元素的内容之后插入内容。 2
:lang(language) p:lang(it) 选择带有以 "it" 开头的 lang 属性值的每个 <p> 元素。 2
element1~element2 p~ul 选择前面有 <p> 元素的每个 <ul> 元素。 3
[attribute^=value] a[src^="https"] 选择其 src 属性值以 "https" 开头的每个 <a> 元素。 3
[attribute$=value] a[src$=".pdf"] 选择其 src 属性以 ".pdf" 结尾的所有 <a> 元素。 3
[attribute*=value] a[src*="abc"] 选择其 src 属性中包含 "abc" 子串的每个 <a> 元素。 3
:first-of-type p:first-of-type 选择属于其父元素的首个 <p> 元素的每个 <p> 元素。 3
:last-of-type p:last-of-type 选择属于其父元素的最后 <p> 元素的每个 <p> 元素。 3
:only-of-type p:only-of-type 选择属于其父元素唯一的 <p> 元素的每个 <p> 元素。 3
:only-child p:only-child 选择属于其父元素的唯一子元素的每个 <p> 元素。 3
:nth-child(n) p:nth-child(2) 选择属于其父元素的第二个子元素的每个 <p> 元素。 3
:nth-last-child(n) p:nth-last-child(2) 同上,从最后一个子元素开始计数。 3
:nth-of-type(n) p:nth-of-type(2) 选择属于其父元素第二个 <p> 元素的每个 <p> 元素。 3
:nth-last-of-type(n) p:nth-last-of-type(2) 同上,但是从最后一个子元素开始计数。 3
:last-child p:last-child 选择属于其父元素最后一个子元素每个 <p> 元素。 3
:root :root 选择文档的根元素。 3
:empty p:empty 选择没有子元素的每个 <p> 元素(包括文本节点)。 3
:target #news:target 选择当前活动的 #news 元素。 3
:enabled input:enabled 选择每个启用的 <input> 元素。 3
:disabled input:disabled 选择每个禁用的 <input> 元素 3
:checked input:checked 选择每个被选中的 <input> 元素。 3
:not(selector) :not(p) 选择非 <p> 元素的每个元素。 3
::selection ::selection 选择被用户选取的元素部分。 3

[attribute|=value] [lang|=en] 选择 lang 属性值以 "en" 开头的所有元素.

元素选择之xpath

xpath:树型结构

1. 基本概念
  • 使用方法:find_element_by_xpath("...")

  • 根节点:/

  • 子节点:/html/body/...

    • 直接子节点 /body
    • 所有子节点(包括直接子节点和非直接子节点)//body
  • 当前节点用“.”表示 ./body/...

  • 当前节点的上一层节点用“..”表示 ../body/...

  • 从根节点开始查找/a/b/c/d

  • 不从根节点开始查找(查找所有节点)//c //b/d

  • 通配符用*表示,*可以是任何一种类型//b//* 查找节点b下的所有元素

    • xpath与css方法对比

      xpath css
      //div/* div > *
  • 根据属性查找

    1. 所有属性,包括id和class
    2. 示例01:查找属性含style的所有元素//*[@style]
    3. 示例02:查找p节点下属性spec=len2的元素//p[@spec='len2']
    • xpath与css方法对比

      xpth属性的值必须加引号,css如果没有空格可以不加引号

      xpath css
      //*[@style] *[style]
      //p[@spec='len2'] p[spec=len2]
2. 举例应用
  • 根据id选择//*[@id='food']

  • 选择属于其父元素的第二个p

    • xpath与css方法对比

      xpath css
      //p[2] nth-of-type(2)
  • 选择属于其父元素的倒数第几个元素

    • 最后一个p类型的子元素//p[last()]
    • 倒数第二个p类型的子元素//p[last(-1)]
    • 所有元素的倒数第二个//*[last()]
  • 根据位置选择

    position表示位置

    • 所有元素中的前两个元素 //*[position()<=2]

    • 除了第一个元素外的其他所有元素 //*[position()>1]

    • 所有元素中的最后三个元素 //*[position()>last()-3]

    • xpath与css方法对比

      • xpath:选择所有的p和所有的button(先选择所有的p再选择button)//p | //button
      • css:选择所有的p和所有的button(按结构顺序选择)p,button
  • 当前节点下的所有直接子节点

    • css:food下面所有的直接子节点中的div#food ~ div
    • xpath://*[@id='food']/following-sibling::div
    • id为food的节点的子节点的第一个节点//*[@id='food']/following-sibling::*[1]
    • id是food的上一个节点的div节点//*[@id='food']/preceding-sibling::div
    • id为food的父节点(上层节点)//*[@id='food']/..
  • 当前目录与子目录

    • 从根目录下开始查找所有的p:'//p'
    • 从当前目录下开始查找所有的p:'.//p'
    • 从当前节点的父节点开始查找所有的p:'..//p'
    • 从当前目录下开始查找直接子节点的p:'./p'
3. 在浏览器中确认查找的元素是否正确
  • 浏览器按F2进入开发者模式,点击console

    • xpath与css方法对比

      方法 路径前的符号 示例
      xpath $x $x("//span")
      css $$ $$('span')
  • 浏览器按F2进入开发者模式,点击elements,按ctrl+F进入搜索模式,输入xpath或css参数路径

4. 浏览器端根据html查看xpath
  • 选中某个路径,点击鼠标右键,依次选择copy-->copy xpath即可复制该元素的xpath
image

查询12306列车

查询有票的列车,并输出列车车次

    1. 要求
    • 南京南-杭州东
    • 当前时间的第二天
    • 0600-1200
    • 二等座
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
try:
    driver = webdriver.Chrome()
    driver.get('https://kyfw.12306.cn/otn/leftTicket/init')
    driver.implicitly_wait((10))

    # 出发地
    driver.find_element_by_id('fromStationText').click() # 点击操作用于清空默认置灰的文字
    driver.find_element_by_id('fromStationText').send_keys('南京南')
    driver.find_element_by_id('fromStationText').send_keys(Keys.ENTER)  # 模拟键盘enter

    # 目的地
    driver.find_element_by_id('toStationText').click()
    driver.find_element_by_id('toStationText').send_keys('杭州东')
    driver.find_element_by_id('toStationText').send_keys(Keys.ENTER)  # 模拟键盘enter

    # 选择时间段
    driver.find_element_by_id('cc_start_time').click()
    driver.find_element_by_xpath("//*[@id='cc_start_time']/option[@value='06001200']").click()

    # 选择日期-->自动查询出结果
    driver.find_element_by_xpath(("//*[@id='date_range']/ul/li[2]")).click()

    # # 收集数据--方法一(本人首次做出来时使用的方法)
    # with_ticket_trains = [] # 有票的车次
    # without_ticket_trains =[] # 无票的车次
    # all_trains_info = driver.find_elements_by_xpath("//*[@id='queryLeftTable']/tr/td[4]")
    # for one_train_info in all_trains_info:
    #     train_number = one_train_info.find_element_by_xpath("../td[1]//*[@class='number']").text.strip()  # 查找车次
    #     if one_train_info.text in ('--', '无'): # 判断是否有票
    #         without_ticket_trains.append(train_number)
    #     else:
    #         with_ticket_trains.append(train_number)
    # # 打印出有票的列车车次
    # if len(with_ticket_trains) == 0:
    #     print('您所选的区间及时间范围内所有列车均已无票')
    # else:
    #     print('以下列车还有票:')
    #     for i in with_ticket_trains:
    #         print(f'{i:>6}')

    # 收集数据--方法二(后期发现只有有票的才含有class属性,代码如下)
    all_trains_info = driver.find_elements_by_xpath("//*[@id='queryLeftTable']/tr/td[4][@class]/../td[1]//a")
    for one in all_trains_info:
        print(one.text)

finally:
    driver.quit()

    1. 结果
image
    1. 点击查看补充知识本文采用其他方法实现功能,暂未涉及链接中介绍的方法,但此方法很实用
image

使用技巧

<meta charset="utf-8">

webdriver对象的一些方法

  • 获取某个元素的属性值
# 获取选定元素对应的链接
ele.get_attribute("href")

  • 获取当前窗口的title
driver.get('https://www.baidu.com/')
print(driver.title)
driver.find_element_by_id('kw')
print(driver.title)

  • 获取当前窗口的地址栏url地址
    driver.current_url

  • 随着用户的操作,title和current_url会变化

  • 截屏-全部屏幕

driver.get_screenshot_as_file('ssl.png')

  • 截屏-某个元素
ele = driver.find_element_by_id('search')
ele.screenshot_as_png('serch.png')

切换窗口

  • 切换到新的窗口里面操作

    • 循环遍历所有的窗口 driver.window_handles
    • driver.switch_to.window(handle)方法切入新窗口
    • 检查该窗口特点,是否为要切入的那个
  • 切换到最初的窗口

    • 保存主窗口的handle
  • 关闭窗口

    • close方法
    • quit()关闭整个浏览器
  • 示例

    # 点击某个元素,打开了一个新的窗口
    # 保存主窗口handle
    mainWindow = driver.current_window_handle
    print(driver.window_handles)
    for handle in driver.window_handle:
        # 切换到新窗口
        driver.switch_to.window(handle)
        # 检查是否是我们要进入到window
        if '百度' in driver.title:
            break
    # 进行操作
    pass
    # 切换到主窗口
    driver.switch_to.window(mainWindow)
    # 进行操作
    pass
    
    

弹出对话框

  • 对话框一般来说有三种:
    • alert 简单通知(一个按钮)
    • confirm (确定,取消)
    • prompt (输入内容,确定,取消)
  • 操作方法
driver.switch_to.alert.accept() # 点击ok
driver.switch_to.alert.text # 得到对话框内容
driver.switch_to.alert.getText() # 得到对话框的内容
driver.switch_to.alert.dismiss() # 点击Cancel
driver.switch_to.alert.send_keys() # 输入内容
# alert = driver.switch_to.alert() # 获取弹框

  • alert弹窗和html元素弹框

    • alert弹窗,用上述方法
    • html弹框,查找定位相关元素进行操作
  • 如何判断alert弹窗和html弹框

    • 点击F12,查看是否可以获得该元素
  • 页面含有input元素,通过插入文件到方式input元素win32com.client

  1. 直接发送键盘消息給 当前应用程序。
  2. 前提是浏览器必须是当前应用(放在最上层,浏览器运行后不要操作
import win32com.client
shell = win32com.client.Dispath('WScript.Shell')
shell.Senkey(r'd:\p1.jpg' + '\n')

刷新页面,前进,后退

  • 页面刷新 refresh
  • 前进 forward
  • 后退 back
driver.refresh()
driver.forward()
driver.back()

使用技巧

  • 易消失元素的查看技巧
    • 鼠标移到该元素上面才会出现

    • 鼠标移开就会消失

    • 5秒后冻结页面setTimeout(function(){debugger;},5000)

      image

浏览器定位元素 copy selector

  • 获取元素的方法 css xpath

  • 取巧:选中元素,右键点击copy,选择copy selector,或者选择copy xpath

    上层节点有id时,此方法比较方便,否则可能会生成比较长的路径;
    路径太长时,后期html中被修改的可能性比较大,不好维护
    此方法并不适用于所有情况,慎用

  • 动态的id不可使用

异常捕获,确保chrome进程退出

  • 切换到新的窗口里面操作

  • 使用try...finally...

    try:
        # 可执行代码
    except:
        print()
    finally:
        driver.quit()
    
    

特殊动作

  • ActionChains 类按下,移动,拖动等

    • acInstance.action1().action2().actionN().perform()
  • 移动到某个元素上面

    • ActionChains(driver).move_to_element(ele).perform()
    from selenium.webdriver.common.action_chains import ActionChains
    ac = ActionChains(driver)
    ac.move_to_element(driver.find_element_by_id('zxnav_1')).perform()
    
    
  • 一次性输入多个input内容

    t1 = driver.find_element_by_id('t1')
    t2 = driver.find_element_by_id('t2')
    t3 = driver.find_element_by_id('t3')
    from selenium.webdriver.common.action_chains import ActionChains
    ac = ActionChains(driver)
    ac.click(t1).send_key('1').click(t2).send_key('2').click(t3).send_key('3').perform()
    
    

页面元素不可见

  • 通常不可见元素都是可以操作的

  • 如果确实需要改变窗口大小

    # 获取窗口大小,返回的size是字典(宽度和高度)
    size = driver.get_window_size()  
    # 改变大小,()里对应的分别是宽度和高度,数字对应的是像素,size['height']表示保持原高度不变
    driver.set_window_size(1100,size['height']) 
    
    
  • driver.max... 窗口最大化

  • 滚动页面

    # X坐标的值,Y坐标的值
    # 正数往下往右移动,负数往上往左移动
    driver.execute_script('window.scrollBy(250,0)')
    # 可在浏览器的console中输入window.scrollBy(250,0),以查看是否能滚动到自己想要的位置
    
    

渲染

- 后端渲染
- 前端渲染
- 前端渲染问题引起的报错:statle element reference
- 解决方法:获取内容前,sleep一下

合理使用半自动化

  • 图形界面自动化的难度是比较大的

    • 模拟难(12306输入验证码...)
    • 检查难(检查logo、布局等...)
  • 用半自动化的方法
    -难自动化的操作,都提示(beep)让人去做

    import winsound
    winsound.Beep(1500,3000) # 发出提示音
    
    
    • 其余部分:自动化 去做
  • 自动化的目的:提高测试效率

自动化面对的问题

  • 如何组织我们的自动化脚本?都放在一个大目录里面?
  • 一次测试开始了,如何选择测试脚本去执行?难道是手动的一个个运行这些脚本?
  • 每个测试脚本中,各个检查点是否通过,如何在测试结果里面清晰的反馈
  • 一些通用功能的实现如何以库的形式组织起来,供各个脚本使用
  • 执行结果如何以容易查看的报告的形式提交给别人查阅
  • 以上这些都可以由自动化测试框架解决
selenium.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350