一.selenium简介
Selenium是一个用于测试网站的自动化测试工具,支持各种浏览器包括Chrome、Firefox、Safari等主流界面浏览器,同时也支持phantomJS无界面浏览器。
二.selenuum的使用
1.安装
pip install selenium
2.下载浏览器驱动程序
chrome浏览器驱动程序Firefox浏览器
找到自己的浏览器版本下载驱动程序
3.浏览器自动播放咪咕音乐周杰伦歌曲列表第二首歌曲
from selenium import webdriver
import time
bro = webdriver.Chrome(executable_path="./chromedriver") # 实例化浏览器对象,executable_path是刚下载的浏览器驱动
bro.maximize_window()#窗口最大化
bro.get(url="https://music.migu.cn/v3") # 浏览器访问咪咕音乐
bro.find_element_by_id("search_ipt").send_keys("周杰伦") # 在搜索框输入周杰伦
bro.find_element_by_xpath('//*[@id="header"]/div[1]/div/div[2]/div[1]/div/span').click() # 点击搜索按钮
bro.switch_to.window(bro.window_handles[1]) # 切换到第二个tab栏
bro.execute_script("window.scrollTo(0,400)")#定位到周杰伦第二个音乐,为了效果明显,可省略
time.sleep(1)
bro.find_element_by_xpath('//*[@id="J_PageSonglist"]/div[2]/div[2]/div[3]/a').click() # 点击第二个歌曲
bro.switch_to.window(bro.window_handles[2]) # 切换到第三个tab栏
time.sleep(1)
bro.find_element_by_xpath('/html/body/div[2]/div[2]/div[2]/div[3]/div[1]').click() # 播放歌曲
while True:#页面跳转太慢,无法获得最新的标签,用个死循环夯住
if len(bro.window_handles) == 4:
bro.switch_to.window(bro.window_handles[3])
break
bro.find_element_by_xpath('//*[@id="header"]/div/div[2]/div[1]/div').click()#点击沉浸模式按钮
time.sleep(240) # 播放4m
bro.quit() # 退出浏览器
4.控制浏览器操作的一些方法
方法 | 说明 |
set_window_size() | 设置浏览器的大小 |
back() | 控制浏览器后退 |
forward() | 控制浏览器前进 |
refresh() | 刷新当前页面 |
clear() | 清除文本 |
send_keys (value) | 模拟按键输入 |
click() | 单击元素 |
submit() | 用于提交表单 |
get_attribute(name) | 获取元素属性值 |
is_displayed() | 设置该元素是否用户可见 |
size | 返回元素的尺寸 |
text | 获取元素的文本 |
5.鼠标事件
方法 | 说明 |
ActionChains(driver) | 构造ActionChains对象 |
context_click() | 执行鼠标悬停操作 |
move_to_element(above) | 右击 |
double_click() | 双击 |
drag_and_drop() | 拖动 |
move_to_element(above) | 执行鼠标悬停操作 |
context_click() | 用于模拟鼠标右键操作, 在调用时需要指定元素定位 |
perform() | 执行所有 ActionChains 中存储的行为,可以理解成是对整个操作的提交动作 |
6.动作链和iframe处理
i.动作链
模拟鼠标复杂动作,比如长按鼠标并拖动
ii.iframe处理
当前页面有iframe,则在iframe里的标签是爬不到的,只有先定位到此iframe,再获取标签
iii.代码
from selenium import webdriver
from time import sleep
#导入动作链对应的类
from selenium.webdriver import ActionChains
bro = webdriver.Chrome(executable_path='./chromedriver')
bro.get('https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
#如果定位的标签是存在于iframe标签之中的则必须通过如下操作在进行标签定位
bro.switch_to.frame('iframeResult')#切换浏览器标签定位的作用域
div = bro.find_element_by_id('draggable')
#动作链
action = ActionChains(bro)
#点击长按指定的标签
action.click_and_hold(div)
for i in range(5):
#perform()立即执行动作链操作
#move_by_offset(x,y):x水平方向 y竖直方向
action.move_by_offset(17,0).perform()
sleep(0.5)
#释放动作链
action.release()
bro.quit()
7. 无头浏览器和反检测手段
i.无头浏览器
我们发现,当我们做爬虫爬取页面的时候,使用selenium总是弹出浏览器,然后自动运行,当我们更不想看到浏览器运行,只想看到数据时可以隐藏浏览器
ii.反检测手段
有的服务器检测到浏览器是selenium发送的,会屏蔽该请求的访问,就需要伪装selenuim
iii.代码
from selenium import webdriver
from time import sleep
#实现无可视化界面
from selenium.webdriver.chrome.options import Options
#实现规避检测
from selenium.webdriver import ChromeOptions
#实现无可视化界面的操作
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
#实现规避检测
option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
#如何实现让selenium规避被检测到的风险
bro = webdriver.Chrome(executable_path='./chromedriver',chrome_options=chrome_options,options=option)
#无可视化界面(无头浏览器) phantomJs
bro.get('https://www.baidu.com')
print(bro.page_source)
sleep(2)
bro.quit()
7.selenium实现自动登录12306
#下述代码为超级鹰提供的示例代码
import requests
from hashlib import md5
class Chaojiying_Client(object):
def __init__(self, username, password, soft_id):
self.username = username
password = password.encode('utf8')
self.password = md5(password).hexdigest()
self.soft_id = soft_id
self.base_params = {
'user': self.username,
'pass2': self.password,
'softid': self.soft_id,
}
self.headers = {
'Connection': 'Keep-Alive',
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
}
def PostPic(self, im, codetype):
"""
im: 图片字节
codetype: 题目类型 参考 http://www.chaojiying.com/price.html
"""
params = {
'codetype': codetype,
}
params.update(self.base_params)
files = {'userfile': ('ccc.jpg', im)}
r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers)
return r.json()
def ReportError(self, im_id):
"""
im_id:报错题目的图片ID
"""
params = {
'id': im_id,
}
params.update(self.base_params)
r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
return r.json()
# chaojiying = Chaojiying_Client('bobo328410948', 'bobo328410948', '899370') #用户中心>>软件ID 生成一个替换 96001
# im = open('12306.jpg', 'rb').read() #本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
# print(chaojiying.PostPic(im, 9004)['pic_str'])
#上述代码为超级鹰提供的示例代码
#使用selenium打开登录页面
from selenium import webdriver
import time
from PIL import Image
from selenium.webdriver import ActionChains
bro = webdriver.Chrome(executable_path='./chromedriver')
bro.get('https://kyfw.12306.cn/otn/login/init')
time.sleep(1)
#save_screenshot就是将当前页面进行截图且保存
bro.save_screenshot('aa.png')
#确定验证码图片对应的左上角和右下角的坐标(裁剪的区域就确定)
code_img_ele = bro.find_element_by_xpath('//*[@id="loginForm"]/div/ul[2]/li[4]/div/div/div[3]/img')
location = code_img_ele.location # 验证码图片左上角的坐标 x,y
print('location:',location)
size = code_img_ele.size #验证码标签对应的长和宽
print('size:',size)
#左上角和右下角坐标
rangle = (
int(location['x']), int(location['y']), int(location['x'] + size['width']), int(location['y'] + size['height']))
#至此验证码图片区域就确定下来了
i = Image.open('./aa.png')
code_img_name = './code.png'
#crop根据指定区域进行图片裁剪
frame = i.crop(rangle)
frame.save(code_img_name)
#将验证码图片提交给超级鹰进行识别
chaojiying = Chaojiying_Client('bobo328410948', 'bobo328410948', '899370') #用户中心>>软件ID 生成一个替换 96001
im = open('code.png', 'rb').read() #本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
print(chaojiying.PostPic(im, 9004)['pic_str'])
result = chaojiying.PostPic(im, 9004)['pic_str']
all_list = [] #要存储即将被点击的点的坐标 [[x1,y1],[x2,y2]]
if '|' in result:
list_1 = result.split('|')
count_1 = len(list_1)
for i in range(count_1):
xy_list = []
x = int(list_1[i].split(',')[0])
y = int(list_1[i].split(',')[1])
xy_list.append(x)
xy_list.append(y)
all_list.append(xy_list)
else:
x = int(result.split(',')[0])
y = int(result.split(',')[1])
xy_list = []
xy_list.append(x)
xy_list.append(y)
all_list.append(xy_list)
print(all_list)
#遍历列表,使用动作链对每一个列表元素对应的x,y指定的位置进行点击操作
for l in all_list:
x = l[0]
y = l[1]
ActionChains(bro).move_to_element_with_offset(code_img_ele, x, y).click().perform()
time.sleep(0.5)
bro.find_element_by_id('username').send_keys('www.zhangbowudi@qq.com')
time.sleep(2)
bro.find_element_by_id('password').send_keys('bobo_15027900535')
time.sleep(2)
bro.find_element_by_id('loginSub').click()
time.sleep(30)
bro.quit()