-
python爬虫之爬虫之selenium
本站最新发布 Python从入门到精通|Python基础教程
试听地址 https://www.xin3721.com/eschool/pythonxin3721/
试听地址 https://www.xin3721.com/eschool/pythonxin3721/
selenium基本操作
-
概念:基于浏览器自动化的模块
-
appnium
:基于手机自动化的模块的应用
-
-
环境的安装
-
pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple
-
-
跟爬虫之间的关联?
- 可以实现模拟登陆
- 便捷的捕获动态加载数据(可见即可得)
-
基本操作
-
导包:
from selenium import webdriver
(web浏览器,driver驱动) -
必须提供对应浏览器的驱动程序(谷歌,火狐...)
- 谷歌浏览器驱动下载地址
-
实例化一个浏览器对象
bro = webdriver.Chrome(executable_path='./chromedriver.exe') # Chrome 谷歌浏览器 executable_path 浏览器驱动路径
-
标签定位
- find系列的函数
-
标签对象.send_keys()
:向指定标签中录入数据 -
提交标签.click()
-
js
注入:浏览器对象.execute_script("js代码")
-
浏览器对象.page_source
:返回当前页面的页面源码数据,包含动态加载数据 -
关闭浏览器:
浏览器对象.quit()
-
-
缺点
- 爬取的效率比较低下
-
什么时候用selenium
- 动态加载的数据requests模块实在爬取不到,使用selenium
示例代码
- 登陆京东,搜索商品
from selenium import webdriver
from time import sleep
# 实例化浏览器对象
bro = webdriver.Chrome(executable_path='./chromedriver.exe') # Chrome 谷歌浏览器 executable_path 浏览器驱动地址
# 制定一些自动化的操作
# 发起请求
bro.get('https://www.jd.com')
# 如何进行标签定位
search_tag = bro.find_element_by_id('key')
# 向文本框中录入数据
search_tag.send_keys('mac pro')
sleep(2)
btn = bro.find_element_by_xpath('//*[@id="search"]/div/div[2]/button')
btn.click()
sleep(2)
# 注入JS代码
bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')
sleep(2)
# page_source :返回当前页面的页面源码数据,包含动态加载数据
print(bro.page_source)
# 关闭浏览器
bro.quit()
案例:使用selenium捕获要药监总局的动态加载数据
- 该网站的数据是动态加载的,来测试selenium如何便捷的捕获动态加载数据
- 网址:http://125.35.6.84:81/xk/
from selenium import webdriver
from time import sleep
from lxml import etree
# 实例化浏览器对象
bro = webdriver.Chrome(executable_path='./chromedriver.exe')
# 发起请求
bro.get('http://125.35.6.84:81/xk/')
sleep(1)
# 第一页的页面源码数据
page_text = bro.page_source
all_page_text = [page_text]
for i in range(1,5):
# 找到下一页对应的标签
a_tag = bro.find_element_by_xpath('//*[@id="pageIto_next"]')
# 对下一页的标签发起点击
a_tag.click()
sleep(1)
# page_source 获取当前页面的源码数据(涵动态加载)
page_text = bro.page_source
all_page_text.append(page_text)
for page_text in all_page_text:
tree = etree.HTML(page_text)
# xpath解析到name对应的标签
li_lst = tree.xpath('//*[@id="gzlist"]/li')
for li in li_lst:
name = li.xpath('./dl/@title')[0]
print(name)
sleep(2)
bro.quit()
动作链
动作链:一系列连续的动作
-
导包:
from selenium.webdriver import ActionChains
-
NoSuchElementException
报错:没有定位到指定的标签-
定位的标签是存在于一张嵌套的子页面中,如果想定位之页面中的指定标签的话需要:
-
浏览器对象.switch_to.frame('iframe标签id的属性值')
:将当前浏览器页面切换到指定的子页面范围中
-
-
定位的标签是存在于一张嵌套的子页面中,如果想定位之页面中的指定标签的话需要:
-
针对指定的浏览器实例化一个动作链对象
-
action = ActionChains(bro)
-
-
点击且长按指定的标签
-
action.click_and_hold(tagName)
-
-
偏移
-
action.move_by_offset(xoffset, yoffset)
一点一点偏移 -
action.move_to_element(to_element)
-
action.move_to_element_with_offset(to_element, xoffset, yoffset)
-
-
偏移.perform()
:动作链立即执行
示例代码
- 标签嵌套子页面中,菜鸟教程例子地址
from selenium import webdriver
from selenium.webdriver import ActionChains
from time import sleep
bro = webdriver.Chrome("./chromedriver.exe")
bro.get('https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
# 标签定位
bro.switch_to.frame('iframeResult')
div_tag = bro.find_element_by_id('draggable')
# 需要使用ActionChains定制好的行为动作
# 针对当前浏览器页面实例化了一个动作链对象
action = ActionChains(bro)
# 点击且长按一个指定的标签
action.click_and_hold(div_tag)
for i in range(1,7):
# 一点一点迁移
action.move_by_offset(10,15).perform() # perform() 是动作链立即执行
action.move_to_element
action.move_to_element_with_offset
sleep(0.5)
无头浏览器
- 概念:没有可视化界面的浏览器
- phantomJS无头浏览器,几乎不用了,停止更新维护了,现在不用了
谷歌无头浏览器
- 就是本机安装的谷歌浏览器,只是需要通过代码进行相关配置就可以变成无头浏览器
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
# 无头浏览器开整
# 实例化options对象
chrome_options = Options()
# 调用add_argument方法,进行自定义配置
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')
# 截屏
bro.save_screenshot('./1.png')
print(bro.page_source)
规避检测
-
webServer是如何检测到我们的请求是否使用了
selenium
-
网站开发者工具Consloe中注入js代码:
window.navigator.webdriver
- true:请求是基于selenium发起的(异常请求)
- undefined:请求是基于浏览器发起的(正常请求)
-
网站开发者工具Consloe中注入js代码:
-
环境配置
-
本机谷歌浏览器的驱动程序所在的目录路径添加到环境变量中
-
使用本机谷歌的驱动程序开启一个浏览器
-
chrome.exe --remote-debugging-port=9222 --user-data-dir="D:\selenum\AutomationProfile"
9222:端口(任意空闲端口)
"D:\selenum\AutomationProfile":已经事先存在的一个空目录
-
-
使用托管机制
- Consloe中注入js代码:window.navigator.webdriver,虽然会返回true,但不会提示请停用以开发者模式运行的扩展程序,相当于自己打开的浏览器
# 终端先运行如下代码
chrome.exe --remote-debugging-port=9222 --user-data-dir="D:\selenum\AutomationProfile"
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_experimental_option('debuggerAddress','127.0.0.1:9222')
# 代码托管打开的浏览器,不会实例化一个新的浏览器
driver = webdriver.Chrome(executable_path="./chromedriver.exe",chrome_options=chrome_options)
driver.get('http://www.taobao.com')
-
老版本的
selenium
规避检测的操作- 这个目前会被检测到
from selenium import webdriver
from selenium.webdriver import ChromeOptions
option = ChromeOptions() #实例化一个ChromeOptions对象
option.add_experimental_option('excludeSwitches', ['enable-automation']) #以键值对的形式加入参数
bro = webdriver.Chrome(executable_path='./chromedriver.exe',options=option) #在调用浏览器驱动时传入option参数就能实现undefined
模拟登陆
12306模拟登陆
-
URL:12306登陆
-
分析:
-
识别的验证码图片必须通过截图获取验证码然后存储到本地
- 登陆操作和唯一的验证码图片一一对应
-
识别的验证码图片必须通过截图获取验证码然后存储到本地
-
基于超级鹰识别验证码登录,类型9004
# 超级鹰的包
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()
# 封装一个验证码识别的函数
def transform_code(imgPath,imgType):
chaojiying = Chaojiying_Client('超级鹰用户名', '超级鹰用户名对应的密码', '软件ID')
im = open(imgPath, 'rb').read()
return chaojiying.PostPic(im, imgType)['pic_str']
# 模拟登陆实现代码
from time import sleep
from PIL import Image # pip install Pillow
from selenium import webdriver
from selenium.webdriver import ActionChains
# 实例化一个谷歌浏览器对象
bro = webdriver.Chrome(executable_path="./chromedriver.exe")
# 发起请求
bro.get('https://kyfw.12306.cn/otn/resources/login.html')
# 登录页面第一个展示的是扫码,点击帐号密码登录
bro.find_element_by_xpath('/html/body/div[2]/div[2]/ul/li[2]/a').click()
sleep(2) # 等待2秒,加载验证码图片
# 定位到用户名密码框,输入帐号密码
bro.find_element_by_id('J-userName').send_keys('xxxxxxxx') # 12306用户名
bro.find_element_by_id('J-password').send_keys('********') # 12306用户名对应的密码
# 验证码的点击操作
bro.save_screenshot('./12306.png')# 将页面当作图片保存到本地
# 将验证码图片的标签定位到
img_tag = bro.find_element_by_id('J-loginImg')
# 验证码的坐标和大小
location = img_tag.location
size = img_tag.size
# 裁剪的范围,这个根据截图自己情况调整,自己调试的(699, 284, 1015, 472)
rangle = (int(location['x'])-65,int(location['y']),int(location['x']+size['width'])-49,int(location['y']+size['height']))
# 使用Image类根据rangle裁剪范围进行验证码图片的裁剪
i = Image.open('./12306.png') # bytes类型数据
frame = i.crop(rangle) # 验证码对应的二进制数据
frame.save('./code.png')
img_coor = transform_code('./code.png',9004) # 返回坐标值 274,146|37,147
# 将坐标字符串转换为嵌套的列表
all_lst = [] # [[274,146],[37,147]...]
if '|' in img_coor:
lst_1 = img_coor.split("|")
count_1 = len(lst_1)
for i in range(count_1):
xy_lst = []
x = int(lst_1[i].split(',')[0])
y = int(lst_1[i].split(',')[1])
xy_lst.append(x)
xy_lst.append(y)
all_lst.append(xy_lst)
else:
x = int(img_coor.split(',')[0])
y = int(img_coor.split(',')[1])
xy_lst = []
xy_lst.append(x)
xy_lst.append(y)
all_lst.append(xy_lst)
for data in all_lst:
# 每个data都是一个列表中有2个元素
x = data[0]
y = data[1]
# 实例化一个动作链,在指定范围(验证码标签范围),找到x,y坐标,点击,动作链立即执行
ActionChains(bro).move_to_element_with_offset(img_tag,x,y).click().perform()
# 执行一次等待0.5秒,防止过快
sleep(0.5)
# 点击登录按钮,实现登录
bro.find_element_by_id('J-login').click()
sleep(2)
# 关闭浏览器
bro.quit()
栏目列表
最新更新
如何使用OS模块中的stat方法
Python os 模块
seek() 方法
python打开文件实例1
Python写入文件
什么是流?
文件操作如何进制逐行读取
Python相对路径
with创建临时运行环境
Python文件操作
.Net Standard(.Net Core)实现获取配置信息
Linux PXE + Kickstart 自动装机
Shell 编程 基础
Shell 编程 条件语句
CentOS8-网卡配置及详解
Linux中LVM逻辑卷管理
1.数码相框-相框框架分析(1)
Ubuntu armhf 版本国内源
Linux中raid磁盘阵列
搭建简易网站
access教程之Access简介
mysql 安装了最新版本8.x版本后的报错:
Mysql空间数据&空间索引(spatial)
如何远程连接SQL Server数据库的图文教程
复制SqlServer数据库的方法
搜索sql语句
sql中返回参数的值
sql中生成查询的模糊匹配字符串
数据定义功能
数据操作功能