通过直接分析ajax信息,我们仍然可以利用request或者urllib来获取信息,但是,JavaScript动态渲染页面的方式不仅只有ajax一种,也不是传统的html页面信息,运用模拟浏览器的运行方式来获取信息,只要浏览器能接收到,我们就能获取出来.在 Python 中提供了许多模拟浏览器运行的库,如 Selenium、Splash
安装ChromeDriver的地址http://npm.taobao.org/mirrors/chromedriver/,将exe可执行文件放到Scripts文件夹下,安装selenium
pip3 install selenium
然后验证安装是否成功
from selenium import webdriver
browser = webdriver.Chrome()
https://github.com/mozilla/geckodriver/releases
geckodriver
from selenium import webdriver
browser = webdriver.Firefox()
启动浏览器则认为成功,不成功只能是版本的问题,可以百度或者谷歌一下Chrome版本对应的ChromeDriver
Selenium:
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
from selenium.webdriver import ActionChains
from selenium.common.exceptions import NoSuchElementException
browser=webdriver.Chrome()
browser.get('http://taobao.com')
#查找
input_first=browser.find_element_by_id('q')
input_second=browser.find_element_by_css_selector('#q')
input_third=browser.find_element_by_xpath('//*[@id="q"]')
print(input_first,input_second,input_third)
#给进函数的查找
input_forth=browser.find_element(By.ID,'q')
print(input_forth)
#查找多个节点
lis=browser.find_elements_by_css_selector('.service-bd li')
print(lis)
#如果我们用 find_element() 方法,只能获取匹配的第一个节点,结果是 WebElement 类型,如果用 find_elements() 方法,则结果是列表类型,列表的每个节点是 WebElement 类型。
#节点交互
input=browser.find_elements_by_id('q')
# input.send_keys('Iphone')
# time.sleep(1)
# input.clear()
# input.send_keys('ipad')
#按钮的点击
button=browser.find_element_by_class_name('btn-search')
button.click()
#动作链
url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)
browser.switch_to.frame('iframeResult')
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()
#执行JavaScript
browser.get('http://www.zhihu.com/explore')
browser.execute_script('window.scrollTo(0,document.body.scrollHeight)')
browser.execute_script('alert("To Bottom")')
#获取节点信息
logo=browser.find_elements_by_id('zh-top-link-logo')
print(logo)
print(logo.get_attribute('class'))
#获取文本值
input=browser.find_elements_by_class_name('zu-top-add-question')
print(input.text)
#获取id,位置,标签名,大小
print(input.id)
print(input.location)
print(input.tag_name)
print(input.size)
#切换frame
url='http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)
browser.switch_to_frame('iframeResult')
try:
logo=browser.find_elements_by_class_name('logo')
except NoSuchElementException:
print('No LOGO')
browser.switch_to.parent_frame()
logo=browser.find_elements_by_class_name('logo')
print(logo)
print(logo.text)
#等待
隐式等待
当使用了隐式等待执行测试的时候,如果 Selenium 没有在DOM 中找到节点,将继续等待,超出设定时间后则抛出找不到节点的异常, 换句话说,当查找节点而节点并没有立即出现的时候,隐式等待将等待一段时间再查找 DOM,默认的时间是 0。
from selenium import webdriver
browser = webdriver.Chrome()
browser.implicitly_wait(10)
browser.get('https://www.zhihu.com/explore')
input = browser.find_element_by_class_name('zu-top-add-question')
print(input)
显示等待
隐式等待的效果其实并没有那么好,因为我们只是规定了一个固定时间,而页面的加载时间是受到网络条件影响的。
所以在这里还有一种更合适的显式等待方法,它指定好要查找的节点,然后指定一个最长等待时间。如果在规定时间内加载出来了这个节点,那就返回查找的节点,如果到了规定时间依然没有加载出该节点,则会抛出超时异常。
我们用一个实例来感受一下:
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
browser = webdriver.Chrome()
browser.get('https://www.taobao.com/')
wait = WebDriverWait(browser, 10)
input = wait.until(EC.presence_of_element_located((By.ID, 'q')))
button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn-search')))
print(input, button)
平常使用浏览器都有前进和后退功能,使用 Selenium 也可以完成这个操作,使用 back() 方法可以后退,forward() 方法可以前进。
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(1)
browser.forward()
browser.close()
使用 Selenium 还可以方便地对 Cookies 进行操作,例如获取、添加、删除 Cookies 等等。
我们再用实例来感受一下:
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
print(browser.get_cookies())
browser.add_cookie({'name': 'name', 'domain': 'www.zhihu.com', 'value': 'germey'})
print(browser.get_cookies())
browser.delete_all_cookies()
print(browser.get_cookies())
在访问网页的时候会开启一个个选项卡,那么在 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.taobao.com')
time.sleep(1)
#browser.switch_to_window(browser.window_handles[0])该方法已经弃用
browser.get('https://python.org')
异常处理
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()