909

自动化测试之selenium的初步使用

最近在爬取亚马逊数据时发现,我们爬虫访问的源码跟浏览器打开的不一样,导致数据抓取的丢失,上网查了下,发现居然有可以模拟浏览器打开浏览器并浏览我们制定的路径,更夸张的是还能模仿人的行为,比如点击操作,滚动操作等等,堪称神器啊,哈哈!

这么强大的工具真是相识恨晚啊,接下来就以我的电脑测试环境做一个简单的总结,基本前提:windows7系统,谷歌浏览器(chrome),python环境搭建,然后就是下载浏览器驱动,本文只以Chrome作为例子讲解,其他的浏览器估计也大同小异。

具体步骤如下:

首先先安装插件:pip install selenium

一、chromedriver的使用(模拟打开浏览器)

我用的是谷歌浏览器,所以需要下载个谷歌的驱动,对应版本如下:

ChromeDriver Version Chrome Version
78.0.3904.11 78
77.0.3865.40 77
77.0.3865.10 77
76.0.3809.126 76
76.0.3809.68 76
76.0.3809.25 76
76.0.3809.12 76
75.0.3770.90 75
75.0.3770.8 75
74.0.3729.6 74
73.0.3683.68 73
72.0.3626.69 72
2.46 71-73
2.46 71-73
2.45 70-72
2.44 69-71
2.43 69-71
2.42 68-70
2.41 67-69
2.40 66-68
2.39 66-68
2.38 65-67
2.37 64-66
2.36 63-65
2.35 62-64

下载对应的webdriver (这里没有可以自己推测每3个版本,对应一个v65-67—v2.38,即v68-70–v2.39)

下载地址:http://chromedriver.storage.googleapis.com/index.html或者http://npm.taobao.org/mirrors/chromedriver/

把下载好的chromedriver.exe,解压后放到python36目录下(或者python36目录下的scripts),即放有python.exe的同目录下,这样就配置完成了。

实例代码如下:

from selenium import webdriver
browser = webdriver.Chrome() #打开浏览器
browser.get(url) #访问url
html = browser.page_source #获取页面源码
browser.find_element_by_xpath("//li[@class='a-last']/a").click() #找到下一页按钮并点击跳转下一页
browser.quit() #关闭浏览器

功能还是很强大,对于网页数据的提起可以有正则匹配,xpath等提取。

接下来介绍一下如何用selenium模拟登陆坚果云,并下载文件:

首先先打开坚果云,找到其对应的登录url

直接上代码

# -*- coding: utf-8 -*-

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


class FollowLogin(object):
    '''
     模拟登陆
    '''
    def __init__(self, url):
        self.url = url

    # 禁用扩展程序
    def BuildDriver(self):
        chrome_options = Options()
        chrome_options.add_argument("--disable-extensions")
        # 设置默认打开是英文
        # chrome_options.add_experimental_option('prefs', {'intl.accept_languages': 'en'})
        # 最大化
        # chrome_options.add_argument('--start-maximized')
        # chrome_options.add_argument("--window-size=0,5")
        browser = webdriver.Chrome(chrome_options=chrome_options)
        return browser

    def open_url(self):
        browser = self.BuildDriver()
        browser.set_page_load_timeout(300)
        return browser

    def get_data(self, browser):
        data = browser.page_source.encode('utf-8', 'ignore')
        order_doc = lxml.html.document_fromstring(data)
        return order_doc

    def main(self):
        '''
         模拟登陆坚果云
        '''
        browser = self.open_url()
        try:
            browser.get(self.url)
        except Exception as e:
            browser.quit()
            time.sleep(1)
            browser.get(self.url)
        # 账号密码定位
        login_email = browser.find_element_by_xpath("//input[@id='login_email']")
        login_email.send_keys("登录邮箱")
        time.sleep(1)
        elem = browser.find_element_by_id("login_password")
        elem.send_keys("登录密码")
        time.sleep(1)
        # 定位登录按钮并模拟点击
        browser.find_element_by_xpath("//button[@id='login-button']").click()
        time.sleep(2)
        browser.find_element_by_xpath("//span[@class='sandboxName'][1]").click()
        time.sleep(1)
        browser.find_element_by_xpath("//li[@class='file-explorer-item'][1]").click()
        time.sleep(1)
        browser.find_element_by_xpath("//button/span[text()='下载']").click()
        time.sleep(1)


if __name__ == "__main__":
    url = 'https://www.jianguoyun.com/d/login'
    FollowLogin(url).main()

行为链的使用

有时候在也页面中的操作可能要有很多很多,那么这时候可以使用鼠标行为链类ActionChains来完成。比如现在要将鼠标移动到某个元素上并执行点击事件,那么示例代码如下:

import time
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
# 声明定义chromedriver路径
path = r'C:/Users/win7/Anaconda3/Lib/chromedriver.exe'
# 实例化Chrome
# 如果时其他浏览器需要实例化为对应的对象,例如火狐webdriver.firefox()
driver = webdriver.Chrome(path)
# 操作输入框
driver.get('https://www.baidu.com/')
time.sleep(2)
# 根据id获取元素
input_kw = driver.find_element_by_id('kw')
time.sleep(2)
submit_btn = driver.find_element_by_id('su')
# 实例化Action
action = ActionChains(driver)
time.sleep(2)
action.move_to_element(input_kw)
time.sleep(2)
action.send_keys_to_element(input_kw, 'python')
time.sleep(2)
action.move_to_element(submit_btn)
time.sleep(2)
action.click(submit_btn)
# 执行上述操作
action.perform()
time.sleep(25)
driver.close()

常用的行为链操作方法(ActionChains类方法):
click(on_element=None) : 左键单击传入的元素,如果不传入的话,点击鼠标当前位置。
context_click(on_element=None): 右键单击。
double_click(on_element=None) : 双击。
click_and_hold(on_element=None): 点击但不松开鼠标
drag_and_drop(source, target) : 在source元素上点击抓起,移动到target元素上松开放下。
drag_and_drop_by_offset(source,xoffset,yoffset):在source元素上点击抓起,移动到相对于source元素偏移xoffset和yoffset的坐标位置放下。
send_keys(*keys_to_send): 将键发送到当前聚焦的元素。
send_keys_to_element(element, *keys_to_send): 将键发送到指定的元素。
reset_actions(): 清除已经存储的动作。

页面等待

现在的网页越来越多采用了Ajax技术,这样程序便不能确定合适某个元素才完成加载出来。如果实际页面等待事件过长导致某个DOM元素还没出来,但是你的代码直接使用了这个页面元素,那么就会抛出NullPointer的异常。为了解决这个问题,所以Selenium提供了两种等待方式,一种是隐式等待、一种是显示等待。
1. 隐式等待
隐式等待指的是,在webdriver中进行find_element_*这一类查找操作时,如果找不到元素,则会默认的轮询等待一段时间。
调用driver.implicitly_wait(10)。那么在获取不可用的元素之前,会先等待10秒的时间,示例代码如下:

driver = webdriver.Chrome(path)
# 设置隐式等待
driver.implicitly_wait(10)
# 请求网页
driver.get('https://www.baidu.com/')

2. 显示等待
显示等待是表明某个条件成立后才执行获取元素的操作。也可以在等待的时候指定一个最大的时间,如果超过这个时间那么就抛出一个异常。显示等待应该使用selenium.webdriver.support.expected_conditions期望条件和selenium.webdriver.support.ui.WebDriverWait来配合完成。

示例代码如下:

# 引入所需库
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

# 声明定义chromedriver路径
path = r'E:\Python_Code\s1\chromedriver_win32\chromedriver.exe'
# 实例化Chrome
# 如果时其他浏览器需要实例化为对应的对象,例如火狐webdriver.firefox()
driver = webdriver.Chrome(path)

# 请求网页
driver.get('https://www.baidu.com/')

# 设置显示等待
try:
    element = WebDriverWait(driver, 10).until(
        # 只能传一个参数,需要放到元组中
        EC.presence_of_element_located((By.ID,'kw'))
    )
    print(element)
finally:
    driver.close()

在上面例子中,我们在查找一个元素的时候,不再使用find_element_by_*这样的方式来查找元素,而是使用了WebDriverWait。

try代码块中的代码的意思是:在抛出元素不存在异常之前,最多等待10秒。在这10秒中,WebDriverWait会默认每500ms运行一次until之中的内容,而until中的EC.presence_of_element_located则是检查元素是否已经被加载,检查的元素则通过By.ID这样的方式来进行查找。

也就是说,在10秒内,默认每0.5秒检查一次元素是否存在,存在则将元素赋值给element这个变量。如果超过10秒这个元素仍不存在,则抛出超时异常。

expected_conditions类中其他方法

title_is:判断title,返回布尔值
WebDriverWait(driver,10).until(EC.title_is(u”百度一下,你就知道”))
title_contains:判断title,返回布尔值
WebDriverWait(driver,10).until(EC.title_contains(u”百度一下”))
presence_of_element_located:判断元素对象是否被加载到dom树里; 并不代表该元素一定可见, 如果定位到就返回Webelement
WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,’some’)))
visibility_of_element_located:判断元素对象是否被加载到dom里并且可见, 一般在对象可能会被其他元素对象遮挡的情况下使用
WebDriverWait(driver,10).until(EC.visibility_of_element_located((By.ID,’some’)))
visibility_of:判断元素是否可见,如果可见就返回这个元素.
WebDriverWait(driver,10).until(EC.visibility_of(driver.find_element(by=By.ID,value=’some’)))
presence_of_all_elements_located:判断是否至少有1个元素存在dom树中,如果定位(找)到就返回列表.
WebDriverWait(driver,10).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR,’some’)))
visibility_of_any_elements_located:判断是否至少有一个元素在页面中可见,如果定位到就返回列表.
WebDriverWait(driver,10).until(EC.visibility_of_any_elements_located((By.CSS_SELECTOR,’some’)))
text_to_be_present_in_element:判断指定的元素中是否包含了预期的字符串,返回布尔值.
WebDriverWait(driver,10).until(EC.text_to_be_present_in_element((By.XPATH,”some”),u’设置’))
text_to_be_present_in_element_value:判断指定元素的属性值中是否包含了预期的字符串,返回布尔值.
WebDriverWait(driver,10).until(EC.text_to_be_present_in_element_value((By.CSS_SELECTOR,’some’),u’百度一下’))
invisibility_of_element_located:判断某个元素在是否存在于dom或不可见,如果可见返回False,不可见返回这个元素.
WebDriverWait(driver,10).until(EC.invisibility_of_element_located((By.CSS_SELECTOR,’some’)))
element_to_be_clickable:判断某个元素中是否有可见并且是enable(可点击)的.
WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH,”some”))).click()
element_to_be_selected: 判断某个元素是否被选中了,一般用在下拉列表.
WebDriverWait(driver,10).until(EC.element_to_be_selected(driver.find_element(By.XPATH,”some”)))
更多方法请参考:http://sekenium-python.readthedocs.io/waits.html

切换页面

有时候窗口中有很多子tab,这时候肯定是需要进行切换的,selenuim提供了一个叫做switch_to_window来进行切换,具体切换到那个页面,可以从driver.window_handles中找到。示例代码如下:

# 引入所需库
from selenium import webdriver

# 声明定义chromedriver路径
path = r'E:\Python_Code\s1\chromedriver_win32\chromedriver.exe'
# 实例化Chrome
# 如果时其他浏览器需要实例化为对应的对象,例如火狐webdriver.firefox()
driver = webdriver.Chrome(path)
# 操作输入框
driver.get('https://www.baidu.com/')

driver.execute_script('window.open("http://www.douban.com/")')
print(driver.window_handles)
driver.switch_to.window(driver.window_handles[1])
print(driver.current_url)

# 虽然在窗口中切换到了新页面,但是driver中还没有切换.
# 如果想要在代码中切换到新的页面,并且做一些爬虫,
# 那么应该使用driver.switch_to.window()来切换到指定窗口
# 从driver.window_handlers中取出jurisdiction第几个窗口
# driver.window_handlers是一个列表,里面装的都是窗口句柄.
# 它会按照打开页面的顺序来存储窗口的句柄.

以上的行为链、页面等待、页面切换转载于CSDN博主「ZhiHuaWei」的原创文章
原文链接:https://blog.csdn.net/Zhihua_W/article/details/102890725
版权声明:内容为CSDN博主「ZhiHuaWei」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
————————————————

目前只针对不需要验证码的模拟登陆,需要验证的较为复杂,暂时还未研究,后期会慢慢更新,哈哈

二、PhantomJS的使用(代理设置)

上面介绍的是基于chrome(谷歌浏览器)模拟打开网页采集数据,最近在服务器上采集AMZ好像一打开selenium的chrome就被识别到,打开的页面是显示sorry something went wrong,然后点击回到home页,其实就是回到Robet Check页面,可想而知该方式采集可能已经被对方侦测到了。接下来介绍一种叫PhantomJS的方式进行采集。并且可以很好的利用代理IP进行数据采集。
PhantomJS是一个基于webkit的javaScript API。它使用QtWebKit作为它核心浏览器的功能,使用webkit来编译解释执行javaScript代码。任何你可以基于在webkit浏览器做的事情,它都能做到。它不仅是个隐性的浏览器,提供了诸如css选择器、支持wen标准、DOM操作、json、HTML5等,同时也提供了处理文件I/O的操作,从而使你可以向操作系统读写文件等。phantomJS的用处可谓非常广泛诸如网络监测、网页截屏、无需浏览器的wen测试、页面访问自动化等。

phantomjs的下载安装地址 : http://phantomjs.org/download.html

根据自己电脑不同的操作系统下载对应的版本,我现在的电脑的Windows,我就以Windows为例演示一下如何采集数据:

phantom

如上图,点击下载Windows版本phantomjs-2.1.1-windows.zip,下载后随便解压到你想要的放的地方。

phantomjs的简单使用案例:

from selenium import webdriver
#使用webkit无界面浏览器
driver = webdriver.PhantomJS(r'phantomjs-2.1.1-windows/bin/phantomjs.exe')#如果路径为exe启动程序的路径 那么该路径需要加一个r
#获取网页数据
driver.get('http://test.html')
data = browser.page_source.encode('utf-8', 'ignore')

以上是不使用代理IP的情况下采集数据,接下来介绍一下利用代理采集数据:

from selenium import webdriver

# 代理服务器
proxyHost = "222.186.26.253"
proxyPort = "888"
proxyType='http' #socks5

# 代理隧道验证信息
service_args = [
"--proxy-type=%s" % proxyType,
"--proxy=%(host)s:%(port)s" % {
    "host" : proxyHost,
    "port" : proxyPort,
}
]
# 要访问的目标页面
targetUrl = "http://test.com"
#使用webkit无界面浏览器
driver = webdriver.PhantomJS(r'phantomjs-2.1.1-windows/bin/phantomjs.exe', service_args=service_args) #如果路径为exe启动程序的路径 那么该路径需要加一个r
#获取网页数据
driver.get(targetUrl)
data = browser.page_source.encode('utf-8', 'ignore')

以上就是对selenium、python、PhantomJS、chrome结合使用采集数据,后期也会根据实际开发中遇到的问题不断更新、总结。好记性不如烂笔头!

发表评论

邮箱地址不会被公开。 必填项已用*标注