很多网站数据是来自于接口,且对接口做了加密,我们可以使用selenium打开浏览器,访问网页让动态数据变成静态,从而绕过反爬虫手段。
- 掌握 selenium基本使用方法
1.1 环境安装
pip install selenium
1.2 安装驱动
官网:http://chromedriver.storage.googleapis.com/index.html
驱动要对应浏览器版本,否者会无法启动
禁止浏览器更新 打开cmd 输入services.msc 打开后台服务,把浏览器自动更新给禁止
2. 声明浏览器对象
选择一个浏览器启动,我们选择chrom测试:
2.1初始化:
from selenium import webdriver
browser = webdriver.Chrome()
这样就完成了浏览器对象的初始化并将其赋值为 browser 对象。接下来,调用 browser 对象,让其执行模拟浏览器操作。
基本操作:
from selenium import webdriver
import time
from selenium.webdriver.common.by import By
# 打开指定(chrome)浏览器
browser = webdriver.Chrome()
# 指定加载页面
browser.get("http://www.baidu.com/")
# 通过name属性选择文本框元素,并设置内容
browser.find_element(By.NAME,'wd').send_keys("python")
# 通过通过ID属性获取“百度一下”按钮,并执行点击操作
browser.find_element(By.ID,"su").click()
# 提取页面
print(browser.page_source.encode('utf-8'))
# 提取cookie
print(browser.get_cookies())
# 获取当前页面截屏
print(browser.get_screenshot_as_file('123.png'))
# 提取当前请求地址
print(browser.current_url)
# 设置五秒后执行下一步
time.sleep(5)
# 关闭浏览器
browser.quit()
运行代码后发现,会自动弹出一个 Chrome 浏览器。浏览器首先会跳转到百度,然后在搜索框中输入 Python,接着跳转到搜索结果页
初始化配置:
from selenium import webdriver
options = webdriver.ChromeOptions()
# 禁止图片
prefs = {"profile.managed_default_content_settings.images": 2}
options.add_experimental_option("prefs", prefs)
# 无头模式 在后台运行
# options.add_argument("-headless")
# 通过设置user-agent
user_ag='MQQBrowser/26 Mozilla/5.0 (Linux; U; Android 2.3.7; zh-cn; MB200 Build/GRJ22;CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1'
options.add_argument('user-agent=%s'% user_ag)
#隐藏"Chrome正在受到自动软件的控制"
options.add_experimental_option('useAutomationExtension', False) # 去掉开发者警告
options.add_experimental_option('excludeSwitches', ['enable-automation'])
# 拓展使用
extension_path = r'E:\BaiduNetdiskDownload\Chrome插件\iguge_2011\igg_2.0.11.crx'
options.add_extension(extension_path)
#设置代理
# options.add_argument("--proxy-server=http://58.20.184.187:9091")
# 初始化配置
browser = webdriver.Chrome(chrome_options=options)
#将浏览器最大化显示
browser.maximize_window()
# 设置宽高
browser.set_window_size(480, 800)
# 通过js新打开一个窗口
browser.execute_script('window.open("http://httpbin.org/ip");')
代码案例一:1.selenium基本使用
from selenium import webdriver
from selenium.webdriver.common.by import By
brower = webdriver.Chrome()
brower.get('https://www.baidu.com/')
input = brower.find_element_by_id("kw")
input.send_keys("python")
brower.find_element(By.ID,"su").click()
print(brower.page_source.encode("utf-8"))
代码案例二:2.模拟键盘操作
from selenium import webdriver
import time
from selenium.webdriver.common.keys import Keys #导入模拟键盘的模块
brower = webdriver.Chrome()
brower.get('https://www.baidu.com/')
input = brower.find_element_by_id('kw')
input.send_keys('python')
input.send_keys(Keys.ENTER) #按键盘enter
time.sleep(5)
brower.close()
代码案例三:css选择器:
from selenium import webdriver
from selenium.webdriver.common.by import By
brower = webdriver.Chrome()
brower.get('https://www.taobao.com/')
li = brower.find_elements_by_css_selector('.service-bd li')
print(list(li))
代码案例四:隐藏受到软件控制;
from selenium import webdriver
options = webdriver.ChromeOptions()
#隐藏"Chrome正在受到自动软件的控制"
options.add_experimental_option('useAutomationExtension', False)
options.add_experimental_option('excludeSwitches', ['enable-automation'])
brower = webdriver.Chrome(chrome_options=options)
5. 查找节点
Selenium 可以驱动浏览器完成各种操作,比如填充表单、模拟点击等。比如,我们想要完成向某个输入框输入文字的操作或者抓取数据,而 Selenium 提供了一系列查找节点的方法,我们可以用这些方法来获取想要的节点,以便下一步执行一些动作或者提取信息。
新版selenium提供了2种方法
find_element()系列:用于定位单个的页面元素。
find_elements()系列:用于定位一组页面元素,获取到的是一组列表。
以后就用这个系列,通过By模块提取,定位,# ID选折起定位,# CSS 选择器定位 # xpath 选择器定位
代码案例:find_element()
from selenium import webdriver
from selenium.webdriver.common.keys import Keys # 模拟键盘操作
from selenium.webdriver.common.by import By
browser = webdriver.Chrome()
browser.get("http://www.baidu.com")
# 通过name属性选择文本框元素,并设置内容
s = browser.find_element(By.NAME,'wd')
s.send_keys('衣服')
s.send_keys(Keys.ENTER) # 回车 确定的意思
代码案例:find_elements()
browser.get("http://www.baidu.com")
# ID选折起定位
input_text = browser.find_element(By.ID, "kw")
input_text.send_keys("selenium")
# CSS 选择器定位
s =browser.find_element(By.CSS_SELECTOR,'input.s_ipt')
s.send_keys('衣服')
# xpath 选择器定位
s = browser.find_element(By.XPATH,'//input[@id="kw"]')
s.send_keys('衣服')
6. 节点交互
Selenium 可以驱动浏览器来执行一些操作,也就是说可以让浏览器模拟执行一些动作。比较常见的用法有:输入文字时用 send_keys 方法,清空文字时用 clear 方法,点击按钮时用 click 方法。示例如下:
节点交互:输入衣服,清除,再输入裤子
from selenium import webdriver
import time
brower = webdriver.Chrome()
brower.get('https://www.taobao.com/')
input = brower.find_element_by_id('q')
input.send_keys('衣服')
time.sleep(3)
input.clear()
input.send_keys('裤子')
button = brower.find_element_by_css_selector('div.search-button>button')
button.click()
brower.close()
7. 切换 IFrame
我们知道网页中有一种节点叫作 iframe,也就是子 Frame,相当于页面的子页面,它的结构和外部网页的结构完全一致。Selenium 打开页面后,它默认是在父级 Frame 里面操作,而此时如果页面中还有子 Frame,它是不能获取到子 Frame 里面的节点的。这时就需要使用 switch_to.frame() 方法来切换 Frame。示例如下:
browser.get('https://www.douban.com/')
login_iframe = browser.find_element(By.XPATH,'//div[@class="login"]/iframe') #定位子页面
browser.switch_to.frame(login_iframe)#
browser.find_element(By.CLASS_NAME,'account-tab-account').click() #定位账号密码登录,点击
browser.find_element(By.ID,'username').send_keys('123123123')
8. 动作链
在上面的实例中,一些交互动作都是针对某个节点执行的。比如,对于输入框,我们就调用它的输入文字和清空文字方法;对于按钮,就调用它的点击方法。其实,还有另外一些操作,它们没有特定的执行对象,比如鼠标拖曳、键盘按键等,这些动作用另一种方式来执行,那就是动作链。
比如,现在实现一个节点的拖曳操作,将某个节点从一处拖曳到另外一处,可以这样实现:
from selenium import webdriver
from selenium.webdriver import ActionChains
browser = webdriver.Chrome()
url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)
log = browser.find_element(By.XPATH, '//div[@id="iframewrapper"]/iframe') #定位子页面
browser.switch_to.frame(log)#进入子页面
source = browser.find_element(By.CSS_SELECTOR,'#draggable') #定位拖拽
target = browser.find_element(By.CSS_SELECTOR,'#droppable')#定位放到位置
actions = ActionChains(browser) #开启动作
actions.drag_and_drop(source, target) # 从哪移动到哪
actions.perform()#展示
9. 页面滚动
# 浏览器滚动到底部 10000位置
document.documentElement.scrollTop=10000
# 滚动到顶部
document.documentElement.scrollTop=0
# 移动到页面最底部
browser.execute_script("window.scrollTo(0, document.body.scrollHeight)")
# 移动到指定的坐标(相对当前的坐标移动)
driver.execute_script("window.scrollBy(0, 700)")
# 结合上面的scrollBy语句,相当于移动到700+800=1600像素位置
driver.execute_script("window.scrollBy(0, 800)")
# 移动到窗口绝对位置坐标,如下移动到纵坐标1600像素位置
driver.execute_script("window.scrollTo(0, 1600)")
# 结合上面的scrollTo语句,仍然移动到纵坐标1200像素位置
driver.execute_script("window.scrollTo(0, 1200)")
直接使用通用代码:页面下拉
for x in range(1, 10):
j = x / 10
js = f"document.documentElement.scrollTop =document.documentElement.scrollHeight * {j}"
brower.execute_script(js)
time.sleep(random.randint(400,800)/1000)
10. 获取节点信息
获取属性
代码:通过 get_attribute() 方法,然后传入想要获取的属性名,就可以得到它的值了。
from selenium import webdriver
url = 'https://pic.netbian.com/4kmeinv/index.html'
browser.get(url)
src = browser.find_elements(By.XPATH,'//ul[@class="clearfix"]/li/a/img')#定位
for i in src:#迭代
url = i.get_attribute('src')#取属性
print(url)
11。取 ID、位置、标签名、大小
通过坐标取部分截图
from io import BytesIO
from selenium import webdriver
from PIL import Image
browser = webdriver.Chrome()
browser.maximize_window()
browser.get('https://pic.netbian.com/4kmeinv/index.html')
browser.maximize_window()
img = browser.find_element_by_xpath('//ul[@class="clearfix"]/li[1]/a/img')
location = img.location
print(location)
size = img.size
print(size)
top, bottom, left, right = location['y'], location['y'] + size['width'],location['x'], location['x'] + size['height']
screen = browser.get_screenshot_as_png()
screen = Image.open(BytesIO(screen))
cap = screen.crop((left,top,right,bottom))
cap.save('asas.png')
browser.close()
12. 延时等待
在 Selenium 中,get() 方法会在网页框架加载结束后结束执行,此时如果获取 page_source,可能并不是浏览器完全加载完成的页面,如果某些页面有额外的 Ajax 请求,我们在网页源代码中也不一定能成功获取到。所以,这里需要延时等待一定时间,确保节点已经加载出来
使用方法
指定要查找的节点,然后指定一个最长等待时间。如果在规定时间内加载出来了这个节点,就返回查找的节点;如果到了规定时间依然没有加载出该节点,则抛出超时异常。示例如下:
代码:这样可以做到的效果就是,在 10 秒内如果 ID 为 q 的节点(即搜索框)成功加载出来,就返回该节点;如果超过 10 秒还没有加载出来,就抛出异常
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait #导入模块
from selenium.webdriver.support import expected_conditions as EC #导入模块
brower = webdriver.Chrome()
brower.get('https://www.taobao.com/')
wait = WebDriverWait(brower,10)
input = wait.until(EC.presence_of_element_located((By.ID,'q'))) #等待加载10s
#也就是可点击,所以查找按钮时查找 CSS 选择器为.btn-search 的按钮,如果 10 秒内它是可点击的,也就是成功加载出来了,就返回这个按钮节点;如果超过 10 秒还不可点击,也就是没有加载出来,就抛出异常。
button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn-search')))#
print(input,button)
更多用法:
等待条件
含义
title_is
标题是某内容
title_contains
标题包含某内容
presence_of_element_located
节点加载出,传入定位元组,如 (By.ID, 'p')
visibility_of_element_located
节点可见,传入定位元组
visibility_of
可见,传入节点对象
presence_of_all_elements_located
所有节点加载出
text_to_be_present_in_element
某个节点文本包含某文字
text_to_be_present_in_element_value
某个节点值包含某文字
frame_to_be_available_and_switch_to_it frame
加载并切换
invisibility_of_element_located
节点不可见
element_to_be_clickable
节点可点击
staleness_of
判断一个节点是否仍在 DOM,可判断页面是否已经刷新
element_to_be_selected
节点可选择,传节点对象
element_located_to_be_selected
节点可选择,传入定位元组
element_selection_state_to_be
传入节点对象以及状态,相等返回 True,否则返回 False
element_located_selection_state_to_be
传入定位元组以及状态,相等返回 True,否则返回 False
alert_is_present
是否出现 Alert
13.前进后退
import time
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.baidu.com/')
browser.get('https://www.taobao.com/')
browser.get('https://www.python.org/')
browser.back()
time.sleep(2)
browser.forward()
time.sleep(1)
browser.close()
14. 选项卡管理
在访问网页的时候,会开启一个个选项卡。在 Selenium 中,我们也可以对选项卡进行操作。示例如下:
import time
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.baidu.com')
browser.execute_script('window.open()') #新建选项卡
print(browser.window_handles)
browser.switch_to.window(browser.window_handles[1])#切换选项卡
browser.get('https://www.baidu.com') #访问百度
time.sleep(1)
browser.switch_to.window(browser.window_handles[0])#切换选项卡
browser.get('https://pic.netbian.com')#访问图片网
15. 异常处理
在使用 Selenium 的过程中,难免会遇到一些异常,例如超时、节点未找到等错误,一旦出现此类错误,程序便不会继续运行了。这里我们可以使用 try except 语句来捕获各种异常。
代码:
from selenium import webdriver
from selenium.common.exceptions import TimeoutException, NoSuchElementException
browser = webdriver.Chrome()
try:
browser.get('https://www.baidu.com')
except TimeoutException:
print('Time Out')
try:
browser.find_element(By.ID,'hello')
except NoSuchElementException:
print('No Element')
finally:
browser.close()
下篇文章上案例
版权归原作者 激进的猴哥 所有, 如有侵权,请联系我们删除。