Selenium Webdriver传递Cookies给requests及持久化

使用Selenium进行登陆

def login(self):

    # 访问登陆页
    self.driver.get(self.LoginPage)

    # 填写邮箱与密码登陆
    self.driver.find_element_by_id("EmailAddress").send_keys(self.username)
    self.driver.find_element_by_id("Password").send_keys(self.password)
    self.driver.find_element_by_id("signin").submit()
    self.driver.implicitly_wait(self.WAIT_TIME)

    # 检测登陆状态
    try:
        length = self.driver.find_element(By.CSS_SELECTOR, '.sign-out').size
        if length != 0:
            self.log.info('Login success')
    except:
        self.log.error("Login failed")

上边是使用Selenium登陆网站的步骤,单考虑登陆没有问题,一旦经常需要登录,品军30s+的登陆时间以及频繁登陆可能导致账号异常的问题就不容忽视

如下代码可以将Cookies保存起来,登陆完成后下一次直接载入使用即可

# 保存 Cookies
pickle.dump(self.driver.get_cookies(), open("cookies.pkl", "wb"))

# 载入 Cookies
self.driver.get(self.HomePage)
cookies = pickle.load(open("cookies.pkl", "rb"))
for cookie in cookies:
    self.driver.add_cookie(cookie)

值得注意的是:Phantomjs保存完Cookies可能存在无法加载的情况,建议使用Firefox,服务器上使用Friefox参考我的上一篇博文

接下来验证Cookies是否有效,使用Webdriver访问网页并判断比较浪费时间,因为加载driver启动浏览器需要些时间,浏览器加载js渲染也比较耗时。如果把验证的工作交给requests就很好,如果Cookies还能用,就导入driver使用,如果Cookies失效了,那么使用driver登陆并保存新的Cookies

import pickle
import requests

cookies = pickle.load(open("cookies.pkl", "rb"))

s = requests.Session()
for cookie in cookies:
    s.cookies.set(cookie['name'], cookie['value'])
response = s.get("https://www.abc.com/account/list.aspx")
bodyStr = response.text

这时,就可以看看返回的内容,是登陆成功后返回的列表还是Cookies失效后返回的重定向信息

<html lang="en">

    <HEAD>
        <meta http-equiv='refresh' content='0; url=https://www.abc.com/account/login.aspx'>

    </HEAD>
    <!--Processed by MotionPoint's TransMotion (r) translation engine v8.3.10.0
    3/22/2016. Copyright© 2003-2016 MotionPoint Corporation. All Rights Reserved.
    This product is protected under one or more of the following US patents:
    7584216, 7580960, 7627479, 7627817, 7996417, 8065294. Other patents pending.-->

</html>

如上就是一个网站返回的Cookies失效的情况。

这样就使得开发时间和运行时间达到了一个比较均衡的状态。使用driver 编写10行的登陆代码,运行需要30s。测试的时候,有个网站跳转多次,如果分析js,模拟From表单登陆,代码有200+行,登陆所用时间10s。这样看起来driver方案还不错

Googling的时候还发现了一个比较有趣的包selenium-requests 它是一个selenium扩展,使得selenium下也可以使用requests的功能,了解更多

from seleniumrequests import Firefox

webdriver = Firefox()
response = webdriver.request('GET', 'https://www.baidu.com/')
print response.status_code

结论:

  • 保存的Cookies能活多久看脸,看网站的策略,一般来讲购物网站的Cookies的有效期都很短,测试过程中,即使在Chrome下真实用户登录,一个小时内,Cookies也会失效。即使在首页一个看到已经登陆,一旦进入用户中心就会跳转登陆页。( •̀ ω •́ )y
  • 在请求详情页列表并且需要对列表内容进一步访问URL请求时,将Cookies导入requests请求是个不错的主意,一是短时间不会失效,二是速度比driver请求快
  • 对于频繁需要登录验证的网站,基本没什么好的办法,只能一次次登陆,然后在短暂的Cookies有效期内多做点事情...
  • 至于将requests导入到driver可以看看使用selenium-requests,看看能不能有什么收获,而且这个需求应该蛮奇怪的。除非是将driver与requests进行有机分离,按需使用,但是这样来看无疑增加程序的复杂性
  • 开发速度与程序效率从某种程度来讲真的如鱼与熊掌一般,不可得兼