该内容面向网络爬虫selenium所需要了解的模拟登陆相关业务技巧
模拟登陆宝象金融
import ssl
from functools import wraps
import requests
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
def sslwrap(func):
@wraps(func)
def bar(*args, **kw):
kw['ssl_version'] = ssl._create_unverified_context(protocol='PROTOCOL_SSLv23')
return func(*args, **kw)
return bar
ssl.wrap_socket = sslwrap(ssl.wrap_socket)
——————————————————————————————————————————————
关键地方:
driver = webdriver.Firefox()打开firefox
driver.get("https://www.bxjr.com/")访问网址
driver.find_element_by_xpath('//a[@class="js-login-btn"]').click()
找到该元素,点击该元素
注意direver定位的是渲染出来的元素,而不是源代码中的元素。
driver.switch_to.frame('layui-layer-iframe1')切换到frame
重头戏:网上的教程都告诉我们要切换到frame标签,但是并没有说明为什么要求换到frame标签,
这里我就好好解释一下:
一般来说xpath只能识别一个html。【功能缺陷】
同理webdriver也是如此
· 通过id定位元素:find_element_by_id("id_vaule")
· 通过name定位元素:find_element_by_name("name_vaule")
· 通过tag_name定位元素:find_element_by_tag_name("tag_name_vaule")
· 通过class_name定位元素:find_element_by_class_name("class_name")
· 通过css定位元素:find_element_by_css_selector();用css定位是比较灵活的
· 通过xpath定位元素:find_element_by_xpath("xpath")
· 通过link定位:find_element_by_link_text("text_vaule")或者find_element_by_partial_link_text()
· 这些方法只识别一个html。在一个html中定位元素。它们不会去定位内套的html中的元素。
但是倘若是要模拟登陆的话,你会发现它渲染出来的页面是有两个html的,即内嵌了一个html。而这个html一定是在iframe或者frame标签底下的。
此时webdriver为了解决这个问题创造了driver.switch_to.frame这个方法,这个方法就是为了能够去定位内嵌的html标签里面的元素。
所以一般来说如果是模拟登陆的话,都会执行driver.switch_to.frame这一步。
注意:
图一是百度查看元素中获得的iframe标签内容
图二是firefox查看元素中获得的iframe标签内容
你会发现图一和图二的iframe标签是不一样的。这说明每个浏览器都有自己的一套机制去渲染页面,所以很有可能出现百度中存在的标签,火狐中不存在的情况。这时在dirvier中用百度的标签定位的话,就有定位不到的嫌疑了。
所以当我们在做selenium的模拟登陆时,最好使用一个浏览器。
WebDriverWait(driver, 10,poll_frequency=0.5
).until(lambda driver: driver.find_element_by_xpath('//input[@id="username"]')).send_keys(
'13564118478') 这里显性等待的惯用方法,直到定位到这个标签为止,等待时长10秒,每0.5秒询问一次,一旦定位成功,输入账号。------该方法当作一个黑盒子就好
WebDriverWait(driver, 10,poll_frequency=0.5
).until(lambda driver: driver.find_element_by_xpath('//input[@id="password"]')).send_keys(
't55111134') 这里显性等待的惯用方法,直到定位到这个标签为止,等待时长10秒,每0.5秒询问一次,一旦定位成功,输入密码。------该方法当作一个黑盒子就好
————————————————————————————————————————
注意常用等待的作用
显示等待
WebDriverWait(driver, 10,poll_frequency=0.5
).until(lambda driver: driver.find_element_by_xpath('//input[@id="username"]'))
自定义哪些标签要等待,超过10秒,报错
类似与自定义在requests中添加timeout=10
隐示等待
driver.implicitly_wait(10)
隐式等待会在WebDriver对象实例的整个生命周期起作用。
也就是说每次定位标签的时候,如果没有就会等待,等待时间为10秒,10秒超过,报错
等到了,执行下去。
类似于在每个requests中添加timeout=10
强制等待
time.sleep(10)
————————————————————————————————————————
driver.find_element_by_xpath('//input[@class="login-btn borderRadius3"]').click()
找到该元素,点击
模拟登陆成功
——————————————————————————————————————————————
获取cookies
我们模拟登陆的目的无非就是获取cookies,然后将cookies加入get请求中实现登陆的需求。
cookie = {}
——————————————————————————————————————————————
for i in driver.get_cookies():
cookie[i['name']] = i['value'] 如果你要获取cookies就必须用这样的方法
因为webdriver返回的cookies,是不能直接给requests
使用的,需要重新处理一下。
——————————————————————————————————————————————
respponse = requests.get(url='https://www.bxjr.com/secure/get-login-info.html?&_=1515293849522', cookies=cookie,
verify=False, headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 BIDUBrowser/8.7 Safari/537.36'})
注意一般用cookies来登陆的时候,加上user-agent比较好。
print(respponse.text)
{"isLogin":true,"username":"大保健一发","avatar":null,"mobile":"135 **** 8478","authType":"personal","isPersonal":true,"isBorrow":false,"isCustodyBorrow":false,"idCardOn":false,"bindCardOn":false,"lastLoginTime":"2018-01-07","callName":"大*****发","nCount":0,"uid":1225829}
成功!!!