爬虫基础库之Selenium
1.简介
selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题
selenium本质是通过驱动浏览器,完全模拟浏览器的操作,比如跳转、输入、点击、下拉等,来拿到网页渲染之后的结果,可支持多种浏览器
from selenium import webdriver browser=webdriver.Chrome() #谷歌 browser=webdriver.Firefox() #火狐 browser=webdriver.PhantomJS() #无界面浏览器 browser=webdriver.Safari() browser=webdriver.Edge()
2.安装
(1)selenium+chromedriver
#安装:selenium+chromedriver pip3 install selenium 下载chromdriver.exe放到python安装路径的scripts目录中即可,注意最新版本是2.29,并非2.9 国内镜像网站地址:http://npm.taobao.org/mirrors/chromedriver/2.29/ 最新的版本去官网找:https://sites.google.com/a/chromium.org/chromedriver/downloads #验证安装 C:\Users\Administrator>python3 Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> from selenium import webdriver >>> driver=webdriver.Chrome() #弹出浏览器 >>> driver.get('https://www.baidu.com') >>> driver.page_source #注意: selenium3默认支持的webdriver是Firfox,而Firefox需要安装geckodriver 下载链接:https://github.com/mozilla/geckodriver/releases
(2)selenium+phantomjs
#安装:selenium+phantomjs pip3 install selenium 下载phantomjs,解压后把phantomjs.exe所在的bin目录放到环境变量 下载链接:http://phantomjs.org/download.html #验证安装 C:\Users\Administrator>phantomjs phantomjs> console.log('egon gaga') egon gaga undefined phantomjs> ^C C:\Users\Administrator>python3 Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> from selenium import webdriver >>> driver=webdriver.PhantomJS() #无界面浏览器 >>> driver.get('https://www.baidu.com') >>> driver.page_source
3.基本使用
from selenium import webdriver #驱动浏览器 from selenium.webdriver import ActionChains #滑动验证 from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR from selenium.webdriver.common.keys import Keys #键盘按键操作 from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素 browser=webdriver.Chrome() try: browser.get('https://www.baidu.com') #请求百度页面,可以看到它帮你打开了 input_tag=browser.find_element_by_id('kw') #找到input标签 input_tag.send_keys('美女') #python2中输入中文错误,字符串前加个u input_tag.send_keys(Keys.ENTER) #输入回车 wait=WebDriverWait(browser,10) wait.until(EC.presence_of_element_located((By.ID,'content_left'))) #等到id为content_left的元素加载完毕,最多等10秒 print(browser.page_source) print(browser.current_url) print(browser.get_cookies()) finally: #不论怎样,下面的代码都会执行 browser.close()
4.选择器
(1)元素选取
想要对页面进行操作,首先要做的是选中页面元素。
定位一个元素 | 定位多个元素 | 含义 |
find_element_by_id | find_elements_by_id | 通过元素ID进行定位 |
find_element_by_name | find_elements_by_name | 通过元素名称定位 |
find_element_by_xpath | find_elements_by_xpath | 通过xpath表达式进行定位 |
find_element_by_link_text | find_elements_by_link_text | 通过完成超链接文本进行定位 |
find_element_partial_link | find_elements_partial_link | 通过部分超链接文本进行定位 |
find_element_by_tag_name | find_elements_by_tag_name | 通过标签名称进行定位 |
find_element_by_class_name | find_elements_by_class_name | 通过类名进行定位 |
find_element_by_css_selector | find_elements_by_css_selector | 通过CSS选择器进行定位 |
定位元素示例:
river = webdriver.Chrome() driver.get('https://www.baidu.com') print(1,driver.find_element_by_id('u')) print(2,driver.find_element_by_link_text('新闻')) print(3,driver.find_element_by_partial_link_text('闻')) print(4,driver.find_element_by_tag_name('a')) print(5,driver.find_element_by_class_name('s_tab')) print(6,driver.find_element_by_name('tj_settingicon')) print(7,driver.find_element_by_css_selector('.c-icon-triangle-down')) time.sleep(20) driver.close() 结果:都是一些对象 1 <selenium.webdriver.remote.webelement.WebElement (session="066063ad1cc136382f8c6a92d57e8d44", element="0.1652270453979785-1")> 2 <selenium.webdriver.remote.webelement.WebElement (session="066063ad1cc136382f8c6a92d57e8d44", element="0.1652270453979785-2")> 3 <selenium.webdriver.remote.webelement.WebElement (session="066063ad1cc136382f8c6a92d57e8d44", element="0.1652270453979785-2")> 4 <selenium.webdriver.remote.webelement.WebElement (session="066063ad1cc136382f8c6a92d57e8d44", element="0.1652270453979785-3")> 5 <selenium.webdriver.remote.webelement.WebElement (session="066063ad1cc136382f8c6a92d57e8d44", element="0.1652270453979785-4")> 6 <selenium.webdriver.remote.webelement.WebElement (session="066063ad1cc136382f8c6a92d57e8d44", element="0.1652270453979785-5")> 7 <selenium.webdriver.remote.webelement.WebElement (session="066063ad1cc136382f8c6a92d57e8d44", element="0.1652270453979785-6")>
除了上面具有确定功能的方法,还有两个方法find_element和find_elements,可以通过传入参数来指定功能,其实和上面的类似:
print(8,driver.find_element(By.ID,'u'))
常见的参数:
BY.ID BY.NAME BY.TAG_NAME BY.LINK_TEXT BY.CLASS_NAME BY.PARTIAL+LINK_TEXT BY.XPATH BY.CSS_SELECTOR
用法示例:
print(8,driver.find_element(By.ID,'u')) print(9,driver.find_element(By.LINK_TEXT,'新闻')) print(10,driver.find_element(By.NAME,'tj_settingicon')) print(11,driver.find_element(By.PARTIAL_LINK_TEXT,'闻')) print(12,driver.find_element(By.TAG_NAME,'a')) print(13,driver.find_element(By.CLASS_NAME,'s_tab')) print(14,driver.find_element(By.CSS_SELECTOR,'.c-icon-triangle-down'))
(2)获取标签属性
在获取到相应的标签以后,可以查询相应的属性。
driver = webdriver.Chrome() driver.get('https://daohang.qq.com') wite = WebDriverWait(driver,10) #显示等待 tag = driver.find_element(By.CSS_SELECTOR,'.tianmao a') print(tag.get_attribute('href')) print(tag.location) print(tag.tag_name) print(tag.size) print(tag.id) 结果: https://s.click.taobao.com/lk7o3Bx {'x': 169, 'y': 391} a {'height': 18, 'width': 55} 0.38338966910989525-1
(3)xpath
from selenium import webdriver from selenium.webdriver import ActionChains from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR from selenium.webdriver.common.keys import Keys #键盘按键操作 from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素 browser=webdriver.Chrome() browser.get('https://www.amazon.cn/') wait=WebDriverWait(browser,10) wait.until(EC.presence_of_element_located((By.ID,'cc-lm-tcgShowImgContainer'))) tag=browser.find_element(By.CSS_SELECTOR,'#cc-lm-tcgShowImgContainer img') #获取标签属性, print(tag.get_attribute('src')) #获取标签ID,位置,名称,大小(了解) print(tag.id) print(tag.location) print(tag.tag_name) print(tag.size) browser.close()
5.等待元素被加载
selenium只是模拟浏览器的行为,二浏览器解析页面是需要时间的(执行CSS、JS),
有些元素可能需要加载时间,在没有加载成功的时候,肯定获取不到相应的结果。
等待的方式有两种:
隐式等待:在browser.get(' ')之前就设置,针对所有元素都有效
显示等待:在browser.get(' ')之后设置,只正对某个元素有效
from selenium import webdriver from selenium.webdriver import ActionChains from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR from selenium.webdriver.common.keys import Keys #键盘按键操作 from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素 browser=webdriver.Chrome() #隐式等待:在查找所有元素时,如果尚未被加载,则等10秒 browser.implicitly_wait(10) browser.get('https://www.baidu.com') input_tag=browser.find_element_by_id('kw') input_tag.send_keys('美女') input_tag.send_keys(Keys.ENTER) contents=browser.find_element_by_id('content_left') #没有等待环节而直接查找,找不到则会报错 print(contents) browser.close()
from selenium import webdriver from selenium.webdriver import ActionChains from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR from selenium.webdriver.common.keys import Keys #键盘按键操作 from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素 browser=webdriver.Chrome() browser.get('https://www.baidu.com') input_tag=browser.find_element_by_id('kw') input_tag.send_keys('美女') input_tag.send_keys(Keys.ENTER) #显式等待:显式地等待某个元素被加载 wait=WebDriverWait(browser,10) wait.until(EC.presence_of_element_located((By.ID,'content_left'))) contents=browser.find_element(By.CSS_SELECTOR,'#content_left') print(contents) browser.close()
6.元素交互操作
(1)clear()
对于某些赋值的操作,在它里面有值得时候如果再进行赋值,就会出现报错,应次需要清空。
browser=webdriver.Chrome() browser.get('https://www.amazon.cn/') wait=WebDriverWait(browser,10) input_tag=wait.until(EC.presence_of_element_located((By.ID,'twotabsearchtextbox'))) input_tag.send_keys('iphone 8') button=browser.find_element_by_css_selector('#nav-search > form > div.nav-right > div > input') button.click() import time time.sleep(3) input_tag=browser.find_element_by_id('twotabsearchtextbox') input_tag.clear() #清空输入框 input_tag.send_keys('iphone7plus') button=browser.find_element_by_css_selector('#nav-search > form > div.nav-right > div > input') button.click()
(2)按住、移动、松开按钮
from selenium import webdriver from selenium.webdriver import ActionChains from selenium.webdriver.common.by import By # 按照什么方式查找,By.ID,By.CSS_SELECTOR from selenium.webdriver.common.keys import Keys # 键盘按键操作 from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait # 等待页面加载某些元素 import time driver = webdriver.Chrome() driver.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable') wait=WebDriverWait(driver,3) # driver.implicitly_wait(3) # 使用隐式等待 try: driver.switch_to.frame('iframeResult') ##切换到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() #方式二:不同的动作链,每次移动的位移都不同 ActionChains(driver).click_and_hold(sourse).perform() distance=target.location['x']-sourse.location['x'] track=0 while track < distance: ActionChains(driver).move_by_offset(xoffset=2,yoffset=0).perform() track+=2 ActionChains(driver).release().perform() time.sleep(10) finally: driver.close()
7.其它:
(1)模拟浏览器前进后退
#模拟浏览器的前进后退 import time from selenium import webdriver browser=webdriver.Chrome() browser.get('https://www.baidu.com') browser.get('https://www.taobao.com') browser.get('http://www.sina.com.cn/') browser.back() time.sleep(10) browser.forward() browser.close()
(2)cookie
from selenium import webdriver driver = webdriver.Chrome() driver.get('https://zhihu.com/explore') print(driver.get_cookies()) driver.add_cookie({'name':'vi','value':'v2'}) print(driver.get_cookies()) driver.close()
(3)选项卡管理
#选项卡管理:切换选项卡,有js的方式windows.open,有windows快捷键:ctrl+t等,最通用的就是js的方式 import time from selenium import webdriver driver = webdriver.Chrome() driver.get('https://baidu.com') driver.execute_script('window.open()') #利用选项卡打开js代码,打开一个弹窗 print(driver.window_handles) driver.switch_to_window(driver.window_handles[1]) #新开一个窗口打开淘宝 driver.get('https://www.taobao.com') driver.switch_to_window(driver.window_handles[0]) #将之前百度得页面替换成天猫 driver.get('https://www.tmall.com') time.sleep(5) driver.close()