在准备好必要步骤之后,开始使用selenium放飞自我。selenium 的准备工作请查看上篇。子琂:Python selenium 使用前的准备工作zhuanlan.zhihu.com
此次的需求来自于老爹。
需求说明:
出于某种原因,老爹需要在某网站上下载相关服务协议。服务协议位于该网站用户中心的协议中心。需要账号登陆,方可查看。协议较多,共计190项,19页。每次下载需要点击三次链接,关闭一次窗口。
这么算下来,如果不借助程序,人力硬刚,想想都头皮发麻,繁琐且效率不高,容易失误,重复下载。于是乎,我便着手解决这一问题。
1、问题拆解需要解决登陆问题
个人中心页面是js加载渲染的,需要解决js问题
需要流程中会出现信息弹框,页面窗口跳转问题
这些,用selenium来解决就再合适不过了。
2、流程拆解
驱动浏览器 -> 访问页面 -> 关闭首页推荐弹窗 -> 登陆 -> 进入个人中心 -> 获取信息列表 -> 点击下载查看(会重新打开一个窗口)->在第二个窗口点击下载按钮 (会弹出一个确认提示框)->点击确认,开始下载。
3、代码实现
引用及常量
url = 'https://www.xxx.xxx/'
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
from selenium.webdriver.common.keys import Keys
驱动浏览器访问网页并获取当前窗口的hadle name
driver = webdriver.Chrome()#有界面的驱动chrome浏览器。
driver.maximize_window()#窗口最大化
wait = WebDriverWait(driver, 10)
driver.get(url)#访问制定网页
current_window = driver.current_window_handle # 获取当前窗口handle name
等推荐弹窗加载完成后,模拟触发点击关闭按钮,因为可能会存在超时的问题,需要加上try catch
print('取消弹框')#操作日志
cancel = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#j-homepage > div.g-wrap > div.m-guide-block.animated.bounceInDown > span"))
)
cancel.click()
print('进入登陆页面')
输入账号、密码进行网页登陆
login = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, "body > div.g-hd.f-cb > div.m-toolbar > div > ul > li:nth-child(6) > div > a.u-sign-btn.u-sign-in"))
)
login.click()
print('输入账号、密码')
name = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#j-cpn2"))
)
psw = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#j-password"))
)
name.send_keys('*******')
psw.send_keys('*******')
submit = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#j-login-submit"))
)
print('确定登陆')
submit.click()
time.sleep(3)#休息一会,怕被对方屏蔽
进入个人中心
print('进入个人中心')
geren = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, "body > div.g-hd.f-cb > div.m-navbar.f-pos-r > div > ul > li.m-user-nav > a > img"))
)
geren.click()
print('点击我的')
chujie = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, "body > div.g-bd.f-mh500.f-cf > div > div > div.m-page-sidebar > ul > li:nth-child(2) > a > span.title"))
)
chujie.click()
获取信息列表
因为已经获知每页10条,且共计190条,此处就省去自动获取分页列表长度的步骤。
for j in range(1,20):
for i in range(1,11):
print('遍历:第%d页'%j+'第%d条记录'%i)
xiangqing = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#j-invest-table > tbody > tr:nth-child(%d) > td:nth-child(6) > a.u-eSignatue.u-op-link.z-current.j-eSignatue-finish"%i))
)
xiangqing.click()
all_window=driver.window_handles
#print(all_window)
for window in all_window:
if window != current_window:
driver.switch_to.window(window)
current_window = driver.current_window_handle # 获取当前窗口handle name
#print(current_window)
time.sleep(3)
!关键性操作!
这一步是实现窗口切换,句柄切换的关键步骤。
all_window=driver.window_handles#先获取打开的所有窗口的句柄
#print(all_window)
#遍历句柄,如果存在有句柄不是当前句柄(也就是有新打开的窗口),就把句柄切换到新的窗口。
for window in all_window:
if window != current_window:
driver.switch_to.window(window)
current_window = driver.current_window_handle # 获取当前窗口handle name
#print(current_window)
time.sleep(3)
进行新开窗口的操作,点击下载按钮
down = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#j-contract-download"))
)
down.click()
reldown = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#j-download-box > span"))
)
reldown.click()
time.sleep(3)
driver.close()
#切换回窗口A
driver.switch_to_window(all_window[0])
time.sleep(3)
翻页操作,翻页操作用的是selenium驱动js。
print('翻页')
if j ==1:
js = "document.getElementsByClassName('u-pnav-prev')[1].click()"
else:
js = "document.getElementsByClassName('u-pnav-prev')[2].click()"
driver.execute_script(js)
time.sleep(3)
4、篇后语
整个实现过程中,用的最多的是waits等操作,更多的selenium操作,可以查看一下网页。希望对你有所帮助。欢迎交流。WeChat:wf342502Selenium Python Bindings 2 documentationselenium-python.readthedocs.io