selenium
目录
selenium基本使用
由于requests不能执行js,有的页面内容,我们在浏览器中可以看到,但是请求下来没有---》selenium模块:模拟操作浏览器,完成人的行为。
selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题
selenium本质是通过驱动浏览器,完全模拟浏览器的操作,比如跳转、输入、点击、下拉等,来拿到网页渲染之后的结果,可支持多种浏览器
# 安装
pip3.8 install selenium
基本使用
# 由于是驱动浏览器:需要确定好驱动哪个浏览器:ie,火狐,谷歌(推荐),下载相应的驱动
https://registry.npmmirror.com/binary.html?path=chromedriver/
浏览器版本要和驱动对应好 103.0.5060.134 下载后解压放在项目路径下
from selenium import webdriver
import time
# 第一步: 等同于你双击谷歌浏览器,打开了浏览器
bro = webdriver.Chrome(executable_path='chromedriver.exe')
bro = webdriver.Chrome() # 不写路径,要放到项目路径或环境变量中
# 第二步:在地址栏输入地址
bro.get('http://www.baidu.com')
# 第三步:关闭浏览器
time.sleep(2)
bro.close() # 关闭标签
bro.quit() # 关闭浏览器
模拟登录百度
from selenium.webdriver.common.by import By
from selenium import webdriver
bro = webdriver.Chrome()
bro.implicitly_wait(10) # 隐式等待
bro.get('https://www.baidu.com/')
# 按钮对象
# 根据标签id号,获取标签
btn=bro.find_element_by_id('s-top-loginbtn') # 老版本
btn = bro.find_element(by=By.ID, value='s-top-loginbtn') # 新版本
# 根据文字找标签:a标签的文字
btn2 = bro.find_element(by=By.LINK_TEXT, value='登录')
# 点击按钮
btn.click()
# 输入框对象
username = bro.find_element(by=By.ID, value='TANGRAM__PSP_11__userName')
password = bro.find_element(by=By.ID, value='TANGRAM__PSP_11__password')
# 输入文本
username.send_keys('xxxxxx')
password.send_keys('xxxxxx')
# 登录按钮
btn_login=bro.find_element(by=By.ID,value='TANGRAM__PSP_11__submit')
btn_login.click()
bro.close() # 关闭标签
查找控件,点击,输入文本
# 查找控件:
bro.find_element(by=By.ID,value='TANGRAM__PSP_11__submit')
1.find_element_by_id # 根据id
2.find_element_by_link_text # 根据a标签的文字
3.find_element_by_partial_link_text # 根据a标签的文字模糊匹配
4.find_element_by_tag_name # 根据标签名
5.find_element_by_class_name # 根据类名
6.find_element_by_name # 根据name属性
7.find_element_by_css_selector # css选择器
8.find_element_by_xpath # xpath
# 点击
对象.click()
# 输入文本
对象.send_keys('内容')
无界面浏览器
不显示的打开浏览器的图形化界面,还能获取数据
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_argument('window-size=1920x3000') # 指定浏览器分辨率
chrome_options.add_argument('--disable-gpu') # 谷歌文档提到需要加上这个属性来规避bug
chrome_options.add_argument('--hide-scrollbars') # 隐藏滚动条, 应对一些特殊页面
chrome_options.add_argument('blink-settings=imagesEnabled=false') # 不加载图片, 提升速度
chrome_options.add_argument('--headless') # 浏览器不提供可视化页面. linux下如果系统不支持可视化不加这条会启动失败
# 需要选择chrome_options
driver = webdriver.Chrome(options=chrome_options)
driver.get('https://dig.chouti.com/')
print(driver.page_source) # 打印当前页面内容
time.sleep(2)
driver.close()
selenium其它用法
获取位置属性大小,文本
import time
import base64
from selenium import webdriver
from selenium.webdriver.common.by import By
bro = webdriver.Chrome()
bro.get('https://kyfw.12306.cn/otn/resources/login.html')
bro.implicitly_wait(10)
btn = bro.find_element(By.LINK_TEXT, '扫码登录')
btn.click()
time.sleep(1)
img = bro.find_element(By.ID, 'J-qrImg')
# 获取属性
img.location
img.size
img.id
img.tag_name
img.get_attribute('src')
# 获取属性并且存入文件中
s = img.get_attribute('src')
with open('code.png', 'wb') as f:
res = base64.b64decode(s.split(',')[-1])
f.write(res)
bro.close()
等待元素被加载
程序操作页面非常快,所以在取每个标签的时候,标签可能没有加载号,需要设置等待
# 隐式等待
bro.implicitly_wait(10)
元素操作
# 搜索标签:
find_element:找第一个
find_elements:找所有
1.find_element_by_id # 根据id
2.find_element_by_link_text # 根据a标签的文字
3.find_element_by_partial_link_text # 根据a标签的文字模糊匹配
4.find_element_by_tag_name # 根据标签名
5.find_element_by_class_name # 根据类名
6.find_element_by_name # 根据name属性
7.find_element_by_css_selector # css选择器
8.find_element_by_xpath # xpath
# 点击
标签.click()
# 文本输入
标签.send_keys()
# 清空
标签.clear()
# 滑动到屏幕底部
bro.execute_script('scrollTo(0,document.body.scrollHeight)')
执行js代码
import time
from selenium import webdriver
bro = webdriver.Chrome()
bro.get('https://www.pearvideo.com/category_8')
time.sleep(1)
# js代码
bro.execute_script('scrollTo(0,document.body.scrollHeight)')
bro.execute_script('alert(md5_vm_test())')
time.sleep(1)
bro.close()
# 执行js用途
1.普通滑屏,打开新标签
2.可以执行js代码,别人网站的变量,函数,都可以拿到并执行的
切换选项卡
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
bro = webdriver.Chrome()
bro.get('https://www.pearvideo.com/category_8')
bro.execute_script('window.open()')
# bro.switch_to_window(bro.window_handles[1]) 老版本,弃用了
bro.switch_to.window(bro.window_handles[1])
bro.get('http://www.baidu.com')
bro.switch_to.window(bro.window_handles[0])
# 关闭选项卡
bro.close()
# 关闭浏览器
bro.quit()
浏览器前进后退
from selenium import webdriver
bro = webdriver.Chrome()
bro.get('https://www.pearvideo.com/category_8')
bro.get('https://www.baidu.com')
# 后退
bro.back()
# 前进
bro.forward()
bro.quit()
异常处理
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException, NoSuchElementException, NoSuchFrameException
bro = webdriver.Chrome()
try:
bro.get('https://www.pearvideo.com/category_8')
time.sleep(1)
bro.get('https://www.baidu.com')
bro.back()
raise Exception('报错')
# 下面不会执行
time.sleep(1)
bro.forward()
except Exception as e:
print(e)
finally:
bro.quit()
selenium登录cnblogs获取cookie
获取cookie
import time
import json
from selenium import webdriver
from selenium.webdriver.common.by import By
bro = webdriver.Chrome()
bro.implicitly_wait(10)
try:
bro.get('https://www.cnblogs.com/')
time.sleep(1)
btn = bro.find_element(By.LINK_TEXT, '登录')
btn.click()
time.sleep(3)
username = bro.find_element(By.ID, 'mat-input-0')
password = bro.find_element(By.ID, 'mat-input-1')
username.send_keys('1814096942@qq.com')
time.sleep(1)
password.send_keys('yyq123456')
btn_login = bro.find_element(By.CSS_SELECTOR,
'body > app-root > app-sign-in-layout > div > div > app-sign-in > app-content-container > div > div > div > form > div > button')
btn_login.click()
# time.sleep(20) # 人工破解验证码,登录成功
input() # 需要在控制台回车
cookies = bro.get_cookies()
print(cookies)
with open('cnblgos.json', 'w', encoding='utf-8') as f:
json.dump(cookies, f)
time.sleep(2)
except Exception as e:
print(e)
finally:
bro.quit()
打开页面
import time
import json
from selenium import webdriver
from selenium.webdriver.common.by import By
bro = webdriver.Chrome()
bro.implicitly_wait(10)
try:
bro.get('https://www.cnblogs.com/')
time.sleep(2)
# 把cookie写入浏览器,刷新一下,就登录了
with open('cnblgos.json', 'r', encoding='utf-8') as f:
res = json.load(f)
for item in res:
bro.add_cookie(item)
# 刷新浏览器
bro.refresh()
time.sleep(2)
except Exception as e:
print(e)
finally:
bro.quit()
抽屉新热榜半自动点赞
from bs4 import BeautifulSoup
from selenium.webdriver.chrome.options import Options
import json
from selenium import webdriver
import requests
# 修改cookie为requests的格式
with open('chouti.json', 'r', encoding='utf-8')as f:
res = json.load(f)
cookies = {}
for i in res:
cookies[i['name']] = i['value']
header = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36",
"Referer": "https://dig.chouti.com/"
}
# 无界面浏览器
chrome_options = Options()
chrome_options.add_argument('window-size=1920x3000') # 指定浏览器分辨率
chrome_options.add_argument('--disable-gpu') # 谷歌文档提到需要加上这个属性来规避bug
chrome_options.add_argument('--hide-scrollbars') # 隐藏滚动条, 应对一些特殊页面
chrome_options.add_argument('blink-settings=imagesEnabled=false') # 不加载图片, 提升速度
chrome_options.add_argument('--headless') # 浏览器不提供可视化页面. linux下如果系统不支持可视化不加这条会启动失败
# 打开页面
bro = webdriver.Chrome(options=chrome_options)
bro.implicitly_wait(10)
try:
bro.get('https://dig.chouti.com/')
# 把cookie写入浏览器,刷新一下,就登录了
with open('chouti.json', 'r', encoding='utf-8') as f:
res = json.load(f)
for item in res:
bro.add_cookie(item)
bro.refresh() # 刷新
# 获取页面内容
soup = BeautifulSoup(bro.page_source, 'html.parser')
# 筛选出id
id_list = soup.find_all(class_="link-title link-statistics")
# for循环发送请求
for i in id_list:
id = i['data-id']
requests.post('https://dig.chouti.com/link/vote', headers=header, cookies=cookies, data={"linkId": id})
except Exception as e:
print(e)
finally:
bro.quit()
动作链
from selenium import webdriver
from selenium.webdriver import ActionChains
import time
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
driver.implicitly_wait(10)
driver.maximize_window()
try:
driver.switch_to.frame('iframeResult')
sourse = driver.find_element(By.ID, 'draggable')
target = driver.find_element(By.ID, 'droppable')
# 方式一:基于同一个动作链串行执行
actions = ActionChains(driver)
# 平行移动等于解锁的长度的距离
actions.drag_and_drop(sourse, target)
actions.perform()
actions = ActionChains(driver).click_and_hold(sourse)
# 平行移动大于解锁的长度的距离
actions.drag_and_drop_by_offset(target, 10, 20)
actions.perform()
# 方式二:不同的动作链,每次移动的位移都不同
ActionChains(driver).click_and_hold(sourse).perform()
distance = target.location['x'] - sourse.location['x'] # 两个控件的x轴的距离
track = 0
while track < distance:
ActionChains(driver).move_by_offset(xoffset=4, yoffset=0).perform()
track += 2
ActionChains(driver).move_by_offset(xoffset=distance, yoffset=0).perform()
ActionChains(driver).release().perform()
time.sleep(10)
finally:
driver.close()
'''--------------实例------------'''
ActionChains(driver).move_by_offset(xoffset=2,yoffset=0).perform() # 滑块,滑动验证码的破解
actions.drag_and_drop_by_offset(target,10,20) # 原来的12306的点选,cnblgs选出所有红绿灯的验证码
actions=ActionChains(driver)
actions.drag_and_drop_by_offset(target,10,20)
xpath的使用
一般解析库都会有子的的搜索标签的方法,一般都会支持css
和xpath
,XPath 是用于在 XML 文档中查找信息
表达式 | 描述 |
---|---|
nodename | 选取此节点的所有子节点。 |
/ | 从根节点选取(取子节点)。 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置(取子孙节点)。 |
. | 选取当前节点。 |
.. | 选取当前节点的父节点。 |
@ | 选取属性。 |
div | 选取div标签 |
# 也可以直接打开浏览器复制
//*[@id="content"]/table[3]/tbody/tr[1]/th[1]
打码平台使用
简单的数字字母组合可以使用图像识别(python 现成模块),成功率不高
使用第三方打码平台(破解验证码平台),花钱,把验证码图片给它,它给你识别完,返回给你(云打码,超级鹰)
from selenium import webdriver
from selenium.webdriver.common.by import By
from PIL import Image
bro = webdriver.Chrome()
bro.get('http://www.chaojiying.com/user/login/')
bro.maximize_window()
try:
bro.save_screenshot('main.png') # 把当前页面截图截图
img = bro.find_element(By.XPATH, '/html/body/div[3]/div/div[3]/div[1]/form/div/img')
location = img.location
size = img.size
print(location)
print(size)
# 使用pillow扣除大图中的验证码
img_tu = (
int(location['x']), int(location['y']), int(location['x'] + size['width']), int(location['y'] + size['height']))
# # 抠出验证码
# #打开
img = Image.open('./main.png')
# 抠图
fram = img.crop(img_tu)
# 截出来的小图
fram.save('code.png')
from chaojiying import ChaojiyingClient
chaojiying = ChaojiyingClient('306334678', 'lqz12345', '937234')
im = open('a.jpg', 'rb').read() # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
print(chaojiying.PostPic(im, 1902))
except:
pass
finally:
bro.close()