用selenium结合浏览器驱动实现模拟浏览器小结

       本文基于python编程语言,python第三方库中有一个很有用的selenium包,可以用来结合相应的浏览器驱动实现一个模拟浏览器,进行自动化,用此可以实现很多功能,比如爬虫、刷视频脚本,总之用户自己可以通过浏览器实现的操作,对于一些重复性的繁琐的任务,都可以通过selenium和相应的浏览器驱动开发脚本,自动完成相应的任务。那么用selenium实现相应功能的步骤以及从中可能遇到的问题有哪些呢?下面以笔者的简单经验做一个小结。

大体步骤:

1、首先安装selenium包,这个可以直接用pip命令或者conda命令;

2、下载相应的浏览器驱动,比如如果想要模拟chrome浏览器,就下载chrome浏览器驱动,同样的还有ie以及firefox等浏览器驱动,下载好后,要特别注意的是,要把相应的驱动程序的路径放在环境变量的path目录下,这样程序构造浏览器对象时才可以找到相应的驱动程序;

3、以上基本工作准备完毕之后,接下来就是脚本的编写:导入selenium包-->创建浏览器对象-->获取对应url地址的网页-->获取网页中的各种元素进行操作。

       下面是一个简单的代码示例,实现的功能是获取一个网页,并找到登录框各个元素的xpath路径,并填入相应的账号和密码,最后点击登录按钮,实现登录。

from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time

driver=webdriver.Chrome()
elem=driver.get(r'url')
#这里需要休眠5秒,等待浏览器打开
time.sleep(5)

#获取登录框
elem = driver.find_element_by_xpath(r'/html/body/div[2]/div[1]/div[1]/div/div[2]/a[1]')
elem.click()
time.sleep(2)

#获取用户名框对象,并清空后输入用户名
elem = driver.find_element_by_xpath(r'//*[@id="username"]')
elem.clear()
elem.send_keys('account')
time.sleep(2)

#获取密码框对象,清空后输入密码
elem = driver.find_element_by_xpath(r'//*[@id="password"]')
elem.clear()
elem.send_keys('password')
time.sleep(2)

#获取登录键对象,并点击登录
elem = driver.find_element_by_xpath(r'//*[@id="login-form"]/p[5]/input')
elem.click()
time.sleep(5)

#等待alert弹窗出现,并进行同意操作
WebDriverWait(driver,timeout=100*60,poll_frequency=10).until(EC.alert_is_present())
driver.switch_to_alert().accept()

#获取所有句柄,并转换driver的控制页面
handles = driver.window_handles  #返回句柄列表,不同的句柄这里代表不同的页面
driver.close()  #关闭原来的页面
driver.switch_to.window(handles[1])  #把driver的控制对象换成新的页面

       以上只是一个最基本的步骤和操作,最关键的还是在于编写脚本时的要注意的一些细节。笔者之前编写了一个自动刷视频的脚本,仅以此经验总结一下需要注意的几点。

几点注意:

1、最简单也是最基本的,养成click之后要记得休眠几秒的好习惯,防止网页还没加载出来就去获取新的元素了,这样很可能是获取不到的;

2、学会利用不同的方式定位并获取元素,selenium提供了以下方法获取元素,当然也可以一下子获取多个符合条件的元素,只要在下面实现了相应接口的方法的element后面加上s即可,便会返回一个元素列表,具体用法可以查看相关非官方文档

  • find_element_by_id
  • find_element_by_name
  • find_element_by_xpath
  • find_element_by_link_text
  • find_element_by_partial_link_text
  • find_element_by_tag_name
  • find_element_by_class_name
  • find_element_by_css_selector

3、利用driver.window_handles获取句柄列表,实现不同页面之间的交换,在需要不断打开新页面的程序中,如果之前的页面已经不再使用,则为了减轻浏览器负担,记得使用driver.close()关闭页面,而driver.quit()则是关闭整个浏览器,当然,对此也可以使用无头浏览器驱动,这样就不用打开可视化的页面了;

4、对alert弹框的处理,由于在进行网页交互时,经常会有一个alert弹框跳出来,这时候浏览器会强制的先处理弹框,由于弹框无法之间在网页源码中定位获取,这是则可以利用driver.switch_to_alert()方法获取alert弹框,然后可以通过accept()或者dismiss()等方法做相应的处理,如果直接这样获取弹框程序没有反应,则可以尝试利用WebDriverWait和switch_to_alert的组合,如本文的示例代码中那样,更详细的处理可以看这里

5、善于使用条件等待,或者说是显性等待,即脚本处于停滞状态,等待直到满足一定条件后再继续运行,比如本示例代码中的WebDriverWait语句,其中until后面就是条件,一个例子就是笔者在写刷视频的脚本时,需要等一个视频播放完后再进行操作播放下一个视频,这时就需要等待视频播放完毕,而因为一个视频播放完毕就会出现一个alert弹窗让用户选择,所以这时是否出现alert弹窗就成为了一个判断条件,对于这种条件等待更详细的说明,可以参考这里

6、学会利用WebDriverWait进行多条件等待,这时需要自己定义多条件判断的callable的类或者函数,具体可看这里

7、如果是关于视频的任务,则要注意新版的chrome浏览器是默认不允许flash插件加载的,所以当播放视频时,会跳出一个非alert弹窗,对于这种非alert弹窗,笔者还不知道怎么在脚本中获取,而是手动处理的,但幸好只需要处理最开始的一次即可,所以对此种视频任务,可以选择其他的浏览器驱动。当然,笔者的chrome的版本是最新的71版,对于69或者之前的版本,读者可以尝试以下方法,直接设置chrome的flash配置:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
prefs = {
    "profile.default_content_setting_values.plugins": 1,
    "profile.content_settings.plugin_whitelist.adobe-flash-player": 1,
    "profile.content_settings.exceptions.plugins.*,*.per_resource.adobe-flash-player": 1,
    "PluginsAllowedForUrls": "ENTER THE URL HERE"
}

options.add_experimental_option("prefs",prefs)
browser = webdriver.Chrome(options=options)

Bug隐患:

1、由于很多的提示框本来是已经在源码中的,只是暂时不可见而已,所以在判断本元素出现与否,避免用driver.find_element_by_方法,而是利用其目前是否可见的属性精确判断,比如expected_conditions.invisibility_of_element_located(locator)(driver),避免出错错误判断引发异常;

2、当打开新页面时,driver的控制权不会自动转换,还是留在元页面的,所以要注意driver的控制对象是哪一个页面,不要想当然的以为driver的控制对象已经发生改变,这样也会触发异常。

猜你喜欢

转载自blog.csdn.net/S_o_l_o_n/article/details/86572672
今日推荐