selenium模块
发布日期:2021-05-07 10:48:27 浏览次数:20 分类:原创文章

本文共 12448 字,大约阅读时间需要 41 分钟。

文章目录

selenium模块的定义

基于浏览器自动化的一个模块

使用selenium模块的优点

  • 便捷的获取网站加载的动态数据
  • 便捷实现模拟登陆

selenium模块使用流程

环境安装:

pip install selenium

下载chrome浏览器的驱动程序(网站不太稳定,可能需要多进几次):

步骤

  1. 实例化一个浏览器对象
  2. 编写基于浏览器自动化的操作代码

先看一个自动加载药监局网站并获取上面企业名称的例子

from selenium import webdriverfrom lxml import etreefrom time import sleepif __name__ == '__main__':    # 实例化一个浏览器对象(一定要传入浏览器驱动程序)    bro = webdriver.Chrome(executable_path='./chromedriver.exe')    # 让浏览器对指定url发起请求    bro.get('http://scxk.nmpa.gov.cn:81/xk/')    # 获取浏览器当前页面源码数据    page_text = bro.page_source    # 解析企业名称    tree = etree.HTML(page_text)    li_list = tree.xpath('//ul[@id="gzlist"]/li') # 定位到企业名称的li标签    for li in li_list:        title_name = li.xpath('./dl/@title')[0]        print(title_name)    sleep(5) # 在网站停留五秒    bro.quit() # 自动退出网站

再看一个在淘宝上自动搜索商品的操作

from selenium import webdriverimport timeif __name__ == '__main__':    bro = webdriver.Chrome(executable_path='./chromedriver.exe')    bro.get('https://www.taobao.com/')    # 标签定位,这里是根据id来定位    search_input = bro.find_element_by_id('q')    # 标签交互    search_input.send_keys('macbook')    time.sleep(2)    # 执行js代码    bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')    time.sleep(5)    # 点击搜索按钮    btn = bro.find_element_by_class_name('btn-search')    btn.click()    time.sleep(5)    bro.quit()

代码中,bro.find_element_by_id()函数用于定位网页源码中id标签,函数的参数就是id标签的值;

send_keys()用于向输入框中输入字符;

如果想要模拟鼠标的滑轮向下滑的操作,可以用js代码实现,而执行js代码的函数是execute_script(),相应的js代码window.scrollTo(0,document.body.scrollHeight)0代表的是x轴即横向移动的像素,另一个参数如果是数字的话,就是y轴即竖着移动的像素,这里的document.body.scrollHeight是向下滑动显示屏的大小;

在输入想要搜索的内容后,还有一个点击搜索按钮的操作,可以用click()函数来实现。

bro.get('https://www.baidu.com/')time.sleep(2)# 回退bro.back()time.sleep(2)# 前进bro.forward()

这里还有两个常用操作,back()用于返回浏览器上一页,forward()用于返回上一页后再回去。

selenium处理iframe

先来了解下什么是iframe

iframe 用于在网页内显示网页。
<iframe src=“URL”></iframe>
URL 指向隔离页面的位置。

在程序中,如果定位的标签是存在于iframe中,则必须通过switch_to.frame('iframe标签id')再进行标签定位。

实现拖动的操作,在我们实际操作时,需要点击+长按鼠标来拖动,在selenium模块中就要使用到动作链。

动作链

导入动作链对应的类:

from selenium.webdriver import ActionChains

实例化一个动作链对象:

action = ActionChains(bro)

执行长按且点击的操作:

action.click_and_hold(div)

执行拖动操作(x是水平移动的像素,y是竖直移动的像素):

action.move_by_offset(x, y)

让动作链立即执行:perform()

释放动作链对象:release()

下面是代码实现runoob上拖动的操作

from selenium import webdriverfrom time import sleep# 导入动作链对应的类from selenium.webdriver import ActionChainsif __name__ == '__main__':    bro = webdriver.Chrome('./chromedriver.exe')    bro.get('https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')    bro.switch_to.frame('iframeResult')    div = bro.find_element_by_id('draggable')    # print(div)    # 动作链    action = ActionChains(bro)    # 点击长按指定标签    action.click_and_hold(div)    for i in range(5):        # move_by_offset()有x、y两个参数        # perform()表示立即执行动作链操作        action.move_by_offset(17, 0).perform()    # 释放动作链    action.release()    bro.quit()

自动登录QQ空间

网站url:

先进行信息搜集,打开qq空间url后,出现的是扫码登录页面,需要点击账号密码登录才能输入账号密码,然后点击登录,最后成功。

from selenium import webdriverfrom time import sleepif __name__ == '__main__':    bro = webdriver.Chrome('./chromedriver.exe')    bro.get('https://qzone.qq.com/')    # 登录页面在一个iframe中    bro.switch_to.frame('login_frame')    btn = bro.find_element_by_id('switcher_plogin')    btn.click()    username_search = bro.find_element_by_id('u')    username_search.send_keys('xxxxxxx') # 用户账号    password_search = bro.find_element_by_id('p')    password_search.send_keys('xxxxxx') # 用户密码    login_btn = bro.find_element_by_id('login_button')    login_btn.click()    sleep(5)    bro.quit()

一开始,我不知道登录框在一个iframe中,一直不成功,后来才发现登录框在一个名为login_frameiframe中,需要先切换才能进行后面的操作。

无头谷歌浏览器

在前面,程序执行时会弹出一个浏览器的窗口,当我们不想它弹出窗口时,就要用到无头浏览器的知识。

导入相关类:

from selenium.webdriver.chrome.options import Options

调用类中方法进行参数设定:

chrome_options = Options()chrome_options.add_argument('--headless')chrome_options.add_argument('--disable-gpu')

例如请求百度

from selenium import webdriverfrom time import sleepfrom selenium.webdriver.chrome.options import Optionsif __name__ == '__main__':    chrome_options = Options()    chrome_options.add_argument('--headless')    chrome_options.add_argument('--disable-gpu')        bro = webdriver.Chrome(executable_path='./chromedriver.exe', chrome_options=chrome_options)    bro.get('https://www.baidu.com')    print(bro.page_source)    sleep(2)    bro.quit()

程序运行后一直未弹出浏览器加载的界面,并且最后也输出了网站的源码。

selenium检测的规避

导入相关类:

from selenium.webdriver import ChromeOptions

调用类中方法进行参数设置:

option = ChromeOptions()option.add_experimental_option('excludeSwitches', ['enable-automation'])

还是上面那个例子

from selenium import webdriverfrom time import sleep# 实现无可视化界面from selenium.webdriver.chrome.options import Options# 规避检测from selenium.webdriver import ChromeOptionsif __name__ == '__main__':    # 实现无可视化操作    chrome_options = Options()    chrome_options.add_argument('--headless')    chrome_options.add_argument('--disable-gpu')    # 规避被检测到的风险    option = ChromeOptions()    option.add_experimental_option('excludeSwitches', ['enable-automation'])    bro = webdriver.Chrome(executable_path='./chromedriver.exe', chrome_options=chrome_options, options=option)    bro.get('https://www.baidu.com')    print(bro.page_source)    sleep(2)    bro.quit()

12306模拟登陆

在这里插入图片描述
12306的登录界面主要是这个选图片的验证码,可以使用进行识别。在验证码类型中,选择的是坐标多选,返回1~4个坐标,如:x1,y1|x2,y2|x3,y3
在这里插入图片描述

import requestsfrom hashlib import md5class 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()if __name__ == '__main__':    chaojiying = Chaojiying_Client('用户名', '登录密码', '软件id')  # 用户中心>>软件ID 生成一个替换 96001    im = open('a.jpg', 'rb').read()  # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//    print(chaojiying.PostPic(im, 9004)['pic_str'])  # 9004 验证码类型  官方网站>>价格体系 3.4+版 print 后要加()

模拟登录编码流程:

  1. 使用selenium打开登录页面
  2. 对当前selenium打开的这张页面进行截图
  3. 对当前截取的图片局部区域(验证码)进行裁剪
  4. 使用超级鹰识别验证码图片(返回坐标数据)

网站打开后是扫码登录的页面,首先要切换到账号密码登录

# 切换成账号密码登录account_login_btn = bro.find_element_by_xpath('/html/body/div[2]/div[2]/ul/li[2]/a')account_login_btn.click()

其次,打码平台能解决识别验证码的问题,如何把验证码保存到本地呢?可以使用截图的方法,先截图整个屏幕,然后再将验证码的那一块图片截出来。

# 截图并保存bro.save_screenshot('aa.jpg')# 确定验证码图片的左上角和右下角的坐标code_img_ele = bro.find_element_by_class_name('imgCode')location = code_img_ele.location  # 验证码图片左上角的坐标x,yprint('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']))# 至此验证码图片区域确定下来

接下来是要用到python的PIL模块,我下载时失败了,后来才知道要下Pillow模块

from PIL import Image# 实例化image对象i = Image.open('./aa.jpg')code_img_name = './code.png'# 使用crop根据指定区域进行图片裁剪frame = i.crop(rangle)frame.save(code_img_name)

到这里,验证码的图片就被保存到了本地,接下来是用超级鹰对验证码进行识别。

识别完成后,注意到最后的结果是xxx,xxx|xxx,xxx这一种的,想到可以以|进行分割,将每一个坐标存为一个列表,最后所有的结果再存为一个大列表,类似于[[x1,y1],[x2,y2]],然后使用数组遍历,依次模拟鼠标点击。

from selenium.webdriver import ActionChainsif '|' 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)# 遍历列表,使用动作链进行点击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)

最后是简单的输入12306的用户名和密码,并点击登录

# 录入用户名和密码username_btn = bro.find_element_by_id('J-userName')password_btn = bro.find_element_by_id('J-password')username_btn.send_keys('12306用户名')password_btn.send_keys('12306密码')login_btn = bro.find_element_by_id('J-login')login_btn.click()

完整的模拟登录代码

import requestsfrom hashlib import md5from selenium import webdriverimport timefrom PIL import Imagefrom lxml import etreefrom selenium.webdriver import ActionChainsclass 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()# 使用selenium打开页面bro = webdriver.Chrome(executable_path='chromedriver.exe')bro.get('https://kyfw.12306.cn/otn/resources/login.html')bro.maximize_window()time.sleep(1)# 切换成账号密码登录account_login_btn = bro.find_element_by_xpath('/html/body/div[2]/div[2]/ul/li[2]/a')account_login_btn.click()# 截图并保存bro.save_screenshot('aa.jpg')# 确定验证码图片的左上角和右下角的坐标code_img_ele = bro.find_element_by_class_name('imgCode')location = code_img_ele.location  # 验证码图片左上角的坐标x,yprint('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']))# 至此验证码图片区域确定下来# 实例化image对象i = Image.open('./aa.jpg')code_img_name = './code.png'# 使用crop根据指定区域进行图片裁剪frame = i.crop(rangle)frame.save(code_img_name)# 将验证码提交给超级鹰识别chaojiying = Chaojiying_Client('超级鹰用户名', '超级鹰密码', '软件id')  # 用户中心>>软件ID 生成一个替换 96001im = open(code_img_name, 'rb').read()  # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//result = chaojiying.PostPic(im, 9004)['pic_str']print(result)  # 1902 验证码类型  官方网站>>价格体系 3.4+版 print 后要加()all_list = []  # 存储即将被点击的点的坐标 [[],[]]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)# 遍历列表,使用动作链进行点击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)# 录入用户名和密码username_btn = bro.find_element_by_id('J-userName')password_btn = bro.find_element_by_id('J-password')username_btn.send_keys('12306账号')password_btn.send_keys('12306密码')login_btn = bro.find_element_by_id('J-login')login_btn.click()

如果在第一次运行后想要再多运行几次的,一定要记得删掉当前文件夹下保存的屏幕截图和验证码区域的截图,然后才能开始运行。

最后又弹出来一个滑块验证,如果用脚本登录的话就算拖动完也会报错,不让登录,真不愧是12306,十几年的防黄牛经验啊。

上一篇:python入门——数据类型
下一篇:python入门——基础语法

发表评论

最新留言

感谢大佬
[***.8.128.20]2025年04月12日 23时19分53秒