文章目录
前言
2021.08.08弄完第七章。
第七章
一、selenium模块的基本使用
- 问题:selenium模块和爬虫之间具有怎样的关联?
- 1.便捷的获取网站中动态加载的数据
- 2.便捷的实现模拟登录
- 什么是selenium模块?
- 基于浏览器自动化的一个模块。
1.selenium使用流程
知识点部分
- selenium使用流程:
-
环境的安装:
pip install selenium
-
下载一个浏览器的驱动程序
-
实例化一个浏览器的对象
-
编写基于浏览器自动化的操作代码
- 发起请求:
get(url)
- 标签定位:
find系列方法
- 标签交互:
send_keys('***')
- 执行js程序:
excute_script('jsCode')
- 前进:
forward()
- 后退:
back()
- 关闭浏览器:
quit()
- 发起请求:
-
selenium处理iframe
- 如果定位的标签存在于iframe标签之中,则必须使用
switch_to.frame(id)
- 动作链(拖动):
from selenium.webdriver import ActionChains
- 实例化一个动作链对象:
action = ActionChains(bro)
- 点击且长按操作:
click_and_hold(div)
- 移动操作:
move_by_offset(x, y)
x-水平方向 y-竖直方向 - 让动作链立即执行:
perform()
- 释放动作链对象:
action.release()
- 实例化一个动作链对象:
- 如果定位的标签存在于iframe标签之中,则必须使用
-
代码部分
①展示代码
演示文档中要用到chromedriver.exe,下载教程:
Selenium Chrome驱动安装(windows系统)
备注:
1.咱在运行的时候Chromedriver需要使用绝对路径,相对路径会报错;
2.使用的Chromedriver版本要与电脑上浏览器版本一致;
3.可能是因为版本更新了,教程中的代码无法正常运行(只能进行到打开浏览器和百度页面),因为找不到“设置”选项。
样例代码:
from selenium import webdriver
from time import sleep
# 后面是你的浏览器驱动位置,记得前面加r'','r'是防止转义字符的
driver = webdriver.Chrome(r'D:\pycharm\PyCharm Community Edition 2020.1.2\CrawlerCourse\07DynamicLoad_dataProcessing\chromedriver.exe')
# 用get打开百度页面
driver.get("http://www.baidu.com")
# 查找页面的“设置”选项,并进行点击
driver.find_elements_by_link_text('设置')[0].click()
sleep(2)
# 打开设置后找到“搜索设置”选项,设置为每页显示50条
driver.find_elements_by_link_text('搜索设置')[0].click()
sleep(2)
# 选中每页显示50条
m = driver.find_element_by_id('nr')
sleep(2)
m.find_element_by_xpath('//*[@id="nr"]/option[3]').click()
m.find_element_by_xpath('.//option[3]').click()
sleep(2)
# 点击保存设置
driver.find_element_by_class_name("prefpanelgo").click()
sleep(2)
# 处理弹出的警告页面
# 确定accept()
# 取消dismiss()
driver.switch_to_alert().accept()
sleep(2)
# 找到百度的输入框,并输入“鲁智深”
driver.find_element_by_id('kw').send_keys('鲁智深')
sleep(2)
# 点击搜索按钮
driver.find_element_by_id('su').click()
sleep(2)
# 在打开的页面中找到“鲁智深 - 百度图片”,并打开这个页面
driver.find_elements_by_link_text('鲁智深 - 百度图片')[0].click()
# 关闭浏览器
driver.quit()
②selenium模块使用样例
selenium模块代码使用样例:
from selenium import webdriver
from lxml import html
etree = html.etree
from time import sleep
# 实例化一个浏览器对象(传入浏览器的驱动程序)
bro = webdriver.Chrome(executable_path=r'D:\pycharm\PyCharm Community Edition 2020.1.2\CrawlerCourse\07DynamicLoad_dataProcessing\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')
# print(li_list)
for li in li_list:
name = li.xpath('./dl/@title')[0]
print(name)
sleep(5)
bro.quit()
③selenium其它动态操作
代码如下:
from selenium import webdriver
from time import sleep
bro = webdriver.Chrome(executable_path=r'D:\pycharm\PyCharm Community Edition 2020.1.2\CrawlerCourse\07DynamicLoad_dataProcessing\chromedriver.exe')
bro.get('https://www.taobao.com/')
# 实现标签定位
search_input = bro.find_element_by_id('q')
# 标签交互
search_input.send_keys('Iphone')
# 执行一组js程序
# ghrome中可以手动在console界面执行以下括号中的代码
bro.execute_script('window.scrollTo(0, document.body.scrollHeight)')
sleep(2)
# class="btn-search tb-bg"
# 空格表示分隔,使用时选择一个,不可两个同时使用
# 点击搜索按钮
btn = bro.find_element_by_css_selector('.btn-search')
btn.click()
bro.get('https://www.baidu.com')
sleep(2)
# 回退
bro.back()
sleep(2)
# 前进
bro.forward()
sleep(5)
bro.quit()c.
④动作链和iframe操作
代码如下:
from selenium import webdriver
from time import sleep
# 导入动作链对应的类
from selenium.webdriver import ActionChains
bro = webdriver.Chrome(executable_path=r'D:\pycharm\PyCharm Community Edition 2020.1.2\CrawlerCourse\07DynamicLoad_dataProcessing\chromedriver.exe')
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.3)
# 释放动作链
action.release()
print(div)
bro.quit()
⑤模拟QQ空间登录
代码如下:
from selenium import webdriver
from time import sleep
bro = webdriver.Chrome(executable_path=r'D:\pycharm\PyCharm Community Edition 2020.1.2\CrawlerCourse\07DynamicLoad_dataProcessing\chromedriver.exe')
bro.get('https://qzone.qq.com/')
bro.switch_to.frame('login_frame')
a_tag = bro.find_element_by_id('switcher_plogin')
a_tag.click()
uesrName_tag = bro.find_element_by_id('u')
password_tag = bro.find_element_by_id('p')
uesrName_tag.send_keys('qq账号')
sleep(1)
password_tag.send_keys('******')
sleep(1)
btn = bro.find_element_by_id('login_button')
btn.click()
sleep(5)
bro.quit()
⑥谷歌无头浏览器&反检测
- chrome_options方法已经被弃用了(如果继续用代码也可以运行,但是会有警告让你用options作为参数),被options替代了,但是无头化和规避检测同时使用时options参数又不能重复,所以现在这里的代码应该怎么写还是个谜。
代码如下:
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=r'D:\pycharm\PyCharm Community Edition 2020.1.2\CrawlerCourse\07DynamicLoad_dataProcessing\chromedriver.exe',
chrome_options=chrome_options, options=option)
# 无可视化界面(无头浏览器) phantomJs
# webdriver.phantomjs
# 不建议用phantomJs,因为它已经停止更新与维护
bro.get('https://www.baidu.com/')
print(bro.page_source)
sleep(2)
bro.quit()
2.12306模拟登录
- 12306模拟登录
- 超级鹰:http://www.chaojiying.com/
- 使用流程:
- 注册:普通用户
- 登录:普通用户
- 题分查询:充值(1元1000题分)
- 创建软件(id)
- 下载示例代码
- 类型9004:坐标多选,返回1~4个坐标,如:x1,y1|x2,y2|x3,y3
- 使用流程:
- 12306模拟登录编码流程:
- 使用selenium打开登录页面
- 对当前selenium打开的这张页面进行截图
- 对当前图片局部区域(验证码图片)进行裁剪
- 好处:将验证码图片和模拟登陆进行一一对应
- 使用超级鹰识别验证码图片(坐标)
- 超级鹰:http://www.chaojiying.com/
代码如下(点击超级鹰识别出来的的图片时位置总是对不上[之前裁剪的时候参数已经调整好了没问题],而且识别很多次也不对):
from selenium import webdriver
import time
import requests
from hashlib import md5
from PIL import Image
from selenium.webdriver import ActionChains
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()
if __name__ == '__main__':
# 使用selenium打开登录页面
bro = webdriver.Chrome(executable_path=r'D:\pycharm\PyCharm Community Edition 2020.1.2\CrawlerCourse\07DynamicLoad_dataProcessing\chromedriver.exe')
bro.get('https://kyfw.12306.cn/otn/resources/login.html')
time.sleep(1)
btn = bro.find_element_by_xpath('/html/body/div[2]/div[2]/ul/li[2]/a')
btn.click()
time.sleep(3)
# save_screenshot 将当前页面进行截图
bro.save_screenshot('./aa.png')
# 确定验证码图片对应的左上角和右下角的坐标(裁剪的区域就确定)
code_img_ele = bro.find_element_by_xpath('//*[@id="J-loginImg"]')
location = code_img_ele.location # 验证码图片左上角的坐标 x y
print('location:', location)
size = code_img_ele.size # 验证码标签对应的长和宽
print('size:', size)
# 左上角和右下角坐标
# 截图时有默认缩放,裁剪时坐标乘1.25,点击对应图片时坐标乘0.8
rangle = (int(location['x'])*1.25, int(location['y'])*1.25,
int(location['x'] + size['width'])*1.25, int(location['y'] + size['height'])*1.25)
# 至此验证码图片区域就确定下来了
i = Image.open('./aa.png')
code_img_name = './code.png'
# crop根据指定区域进行图片裁剪
frame = i.crop(rangle)
frame.save(code_img_name)
# 将验证码图片提交给超级鹰进行识别
chaojiying = Chaojiying_Client('zhangyi132', 'zhangjinpeng101', '920271')
im = open('code.png', 'rb').read()
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]) / 1.25
y = int(list_1[i].split(',')[1]) / 1.25
xy_list.append(x)
xy_list.append(y)
all_list.append(xy_list)
else:
xy_list = []
x = int(result[i].split(',')[0]) / 1.25
y = int(result[i].split(',')[1]) / 1.25
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[0]
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('******')
time.sleep(2)
bro.find_element_by_id('password').send_keys('******')
time.sleep(2)
bro.find_element_by_id('loginSub').click()
time.sleep(5)
bro.quit()