一。环境部署
1.selenium安装
pip3 install selenium
1.安装浏览器驱动
WebDriver
需要通过浏览器驱动
来与浏览器
交互,以下列出几种常用的浏览器驱动下载地址:
Chrome:
http://chromedriver.storage.googleapis.com/index.html
Firefox:
https://github.com/mozilla/geckodriver/releases
Edge:
https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver
Safari:
https://webkit.org/blog/6900/webdriver-support-in-safari-10
使用不同的浏览器,需要下载对应版本驱动,并且确保驱动文件如chromedriver.exe放到你的系统环境PATH中,这里我将它放到python安装目录下。D:Python36chromedriver.exe
selenium思维导图详细使用介绍:
二。元素定位:
1 <!DOCTYPE html> 2 <html lang="zh-CN"> 3 <body> 4 <h1 class="head_title">你好,<span id="world">世界!</span></h1> 5 <a href="https://www.kancloud.cn/@guanfuchang" target="_blank">我的看云首页</a> 6 <br/> 7 <br/> 8 <div id="login_form" class="login"> 9 用户名:<input name="username" class="ptqa user_name" placeholder="用户名" value="Milton" required/> 10 密码:<input type="text" name="password" class="ptqa pwd" placeholder="密码" value="ptqa" required/> 11 地区: 12 <select class="city"> 13 <option value="gz">广州</option> 14 <option value="fs">佛山</option> 15 <option value="mm">茂名</option> 16 <option value="hb">襄樊</option> 17 </select> 18 19 <br> 20 <br> 21 <button>提交</button> 22 <br> 23 24 </div> 25 </body> 26 </html>
1 在同个目录下创建一个find_location.py文件,初始化工作 2 from selenium import webdriver 3 import os 4 5 # 创建Chrome驱动实例 6 driver = webdriver.Chrome() 7 8 # 启动浏览器并且导航到指定URL 9 # 这里为了覆盖更多的元素定位,我自己编写了一个本地的hello.html文件。 10 file_path = 'file:///' + os.path.abspath('hello.html') 11 driver.get(file_path)
find_element_by_class_name(self, name): find_elements_by_class_name(self, name): # 定位class名称为“head_title"的元素 head_title = driver.find_element_by_class_name("head_title") print(head_title.text)
find_element_by_id(self, id_): find_elements_by_id(self, id_): # 定位id为“world”的元素 world = driver.find_element_by_id("world") print(world.text)
find_element_by_name(self, name): find_elements_by_name(self, name): # 定位name为“username”的元素 username = driver.find_element_by_name("username") print(username.get_attribute("value"))
1 find_element_by_tag_name(self, name): 2 find_elements_by_tag_name(self, name): 3 # 定位标签为<button>的元素 4 submit_btn = driver.find_element_by_tag_name("button") 5 print(submit_btn.text)
1 find_element_by_link_text(self, link_text): 2 find_element_by_partial_link_text(self, link_text): 3 4 # 定位链接文本完全匹配“我的看云首页”的元素 5 kancloud = driver.find_element_by_link_text("我的看云首页") 6 print(kancloud.get_attribute("href")) 7 8 # 定位链接文本部分匹配“看云首页”的元素 9 kancloud = driver.find_element_by_partial_link_text("看云首页") 10 print(kancloud.get_attribute("href"))
1 find_element_by_xpath(self, xpath): 2 find_elements_by_xpath(self, xpath): 3 4 # xpath定位,相对路径定位用户名输入框 5 username = driver.find_element_by_xpath("//body/div/input") 6 print(username.get_attribute("value")) 7 8 # xpath定位,相对路径与属性结合 定位密码输入框 9 password = driver.find_element_by_xpath("//input[@name='password']") 10 print(password.get_attribute("value")) 11 12 # xpath定位,多个属性结合 定位密码输入框 13 password = driver.find_element_by_xpath("//input[@name='password'][@type='text']") 14 print(password.get_attribute("value"))
1 find_element_by_css_selector(self, css_selector): 2 find_elements_by_css_selector(self, css_selector): 3 4 # css选择器,标签+属性 定位用户名输入框 5 username = driver.find_element_by_css_selector("input[name='username']") 6 print(username.get_attribute("value")) 7 8 复制 9 # css选择器,标签+class类名 定位用户名输入框 10 username = driver.find_element_by_css_selector("input.user_name") 11 print(username.get_attribute("value")) 12 13 # css选择器,标签+多个class类名,定位密码输入框,注意不要空格,空格代表下一级子元素 14 password = driver.find_element_by_css_selector("input.ptqa.pwd") 15 print(password.get_attribute("value")) 16 17 # css选择器,id+多个class类名,定位密码输入框 18 password = driver.find_element_by_css_selector("#login_form .ptqa.pwd") 19 print(password.get_attribute("value")) 20 21 # css选择器,多级class类名,定位密码输入框 22 password = driver.find_element_by_css_selector(".login .ptqa.pwd") 23 print(password.get_attribute("value")) 24 25 # css选择器,class类名+属性,定位密码输入框 26 password = driver.find_element_by_css_selector(".login .ptqa[name='password']") 27 print(password.get_attribute("value")) 28 29 #css 选择器,根据父子关系,定位密码输入框 30 password = driver.find_element_by_css_selector("div[id='login_form']>input[name='password']") 31 print(password.get_attribute("value")) 32 33 # css 选择器,根据兄弟关系,定位密码输入框 34 password = driver.find_element_by_css_selector("input[name='username']+input") 35 print(password.get_attribute("value"))
1 上面的所有元素定位 find_element_by_xxx和find_elements_by_xxx调用的结果,实际上都是在调用以下两种方法,我们也可以直接调用一下两种方法即可。 2 3 find_element(self, by=By.ID, value=None): 4 find_elements(self, by=By.ID, value=None): 5 6 class By(object): 7 """ 8 Set of supported locator strategies. 9 """ 10 11 ID = "id" 12 XPATH = "xpath" 13 LINK_TEXT = "link text" 14 PARTIAL_LINK_TEXT = "partial link text" 15 NAME = "name" 16 TAG_NAME = "tag name" 17 CLASS_NAME = "class name" 18 CSS_SELECTOR = "css selector" 19 20 21 例如: 22 from selenium.webdriver.common.by import By 23 # 根据id,定位id为“world”的元素 24 world = driver.find_element(By.ID,"world") 25 print(world.text) 26 27 # xpath定位,相对路径与属性结合 定位密码输入框 28 password = driver.find_element(By.XPATH,"//input[@name='password']") 29 print(password.get_attribute("value")) 30 31 # css选择器,标签+属性 定位用户名输入框 32 username = driver.find_element(By.CSS_SELECTOR,"input[name='username']") 33 print(username.get_attribute("value"))
三。元素操作:
1 清除文本输入框 2 clear(self) 3 4 点击元素 5 click(self) 6 7 提交表单 8 submit(self) 9 10 发送信息 11 send_keys(self, *value) 12 13 获取元素的文本 14 text
1 获取元素属性 2 get_attribute(self, name) 3 4 判断元素可见 5 is_displayed(self) 6 7 判断元素可用 8 is_enabled(self) 9 10 判断元素是否被选中 11 is_selected(self)
1 获取元素位置 2 location 3 4 获取元素大小 5 size 6 7 获取元素的文本 8 text
1 ActionChains中提供一些复杂操作,如鼠标移动,鼠标按钮操作,按键操作和上下文菜单交互等,这些操作在实际运用中其实复杂操作并不常用,这里只简单介绍一个元素拖拽的例子,其他方法,请自行查看源码。 2 3 element = driver.find_element_by_name("source") 4 target = driver.find_element_by_name("target") 5 6 from selenium.webdriver import ActionChains 7 action_chains = ActionChains(driver) 8 # 拖拽(在元素A上按住鼠标左键不放,拖动到元素B上,然后松开鼠标) 9 action_chains.drag_and_drop(element, target).perform()
四。浏览器当行操作:
五。元素等待;
六。 示例演示
获取页面源码数据:
通过page_source
属性可以获取网页的源代码,接着就可以使用解析库(如正则表达式、Beautiful Soup、pyquery等)来提取信息了。
动作链:它们没有特定的执行对象,比如鼠标拖曳、键盘按键等,这些动作用另一种方式来执行,那就是动作链。
from selenium import webdriver from selenium.webdriver import ActionChains import time browser = webdriver.Chrome() 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() #执行动作链 actions.click_and_hold(source) time.sleep(3) for i in range(5): actions.move_by_offset(xoffset=17,yoffset=0).perform() time.sleep(0.5) actions.release()
浏览器前进后退演示:
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()
Cookie处理:
使用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())
异常处理:
from selenium import webdriver from selenium.common.exceptions import TimeoutException,NoSuchElementException,NoSuchFrameException try: browser=webdriver.Chrome() browser.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable') browser.switch_to.frame('iframssseResult') except TimeoutException as e: print(e) except NoSuchFrameException as e: print(e) finally: browser.close()
selenium实现模拟百度搜索功能
from selenium import webdriver from time import sleep #实例化一个浏览器对象 bro = webdriver.Chrome(executable_path='./chromedriver.exe') #基于url发起请求 sleep(2) bro.get('https://www.baidu.com/') #实现页面标签的定位 sleep(2) input_tag = bro.find_element_by_id('kw') input_tag.send_keys('周杰伦') sleep(2) btn = bro.find_element_by_id('su') btn.click() sleep(3) #获取当前浏览器打开的页面对应的源码数据 page_text = bro.page_source print(page_text) sleep(2) bro.quit()
selenium实现无可视化展示
from selenium.webdriver.chrome.options import Options from selenium import webdriver from time import sleep chrome_options = Options() chrome_options.add_argument('--headless') chrome_options.add_argument('--disable-gpu') #实例化一个浏览器对象 bro = webdriver.Chrome(executable_path='./chromedriver.exe',chrome_options=chrome_options) #基于url发起请求 sleep(2) bro.get('https://www.baidu.com/') #实现页面标签的定位 sleep(2) input_tag = bro.find_element_by_id('kw') input_tag.send_keys('周杰伦') sleep(2) btn = bro.find_element_by_id('su') btn.click() sleep(3) bro.save_screenshot('./1.jpg') # 进行截图保存 #获取当前浏览器打开的页面对应的源码数据 page_text = bro.page_source # 爬取页面源码 print(page_text) sleep(2) bro.quit()
加载js文件实现动态加载浏览器数据
滚轮向下滑动一屏的高度:window.scrollTo(0,document.body.scrollHeight)
from selenium import webdriver from time import sleep bro = webdriver.Chrome(executable_path='./chromedriver.exe') # bro = webdriver.PhantomJS(executable_path = '') bro.get(url='https://news.163.com/domestic/') # 线程阻塞代码,上一个未执行完,下一个是不会执行的 sleep(2) #让滚轮向下滑动 js = 'window.scrollTo(0,document.body.scrollHeight)' bro.execute_script(js) # 非阻塞代码异步实现,所以这块要给一个暂停时间防止网速不好或者一些因素引起的问题 sleep(2) bro.execute_script(js) sleep(2) bro.execute_script(js) sleep(2) a_tag = bro.find_element_by_xpath('/html/body/div/div[3]/div[4]/div[1]/div/div/a') a_tag.click() sleep(2) #源码数据就包含了所有的新闻数据 page_text = bro.page_source with open('./wangyi.html','w',encoding='utf-8') as fp: fp.write(page_text)
这里引出一个无界面浏览器:phantomjs实现了一个无界面的webkit浏览器。虽然没有界面,但dom渲染、js运行、网络访问、canvas/svg绘制等功能都很完备,在页面抓取、页面输出、自动化测试等方面有广泛的应用。
驱动包百度共享下载:链接:https://pan.baidu.com/s/15j5RpkVAryKRa_VFrjdqDw 提取码:zptn
from selenium import webdriver from time import sleep # bro = webdriver.Chrome(executable_path='./chromedriver.exe') bro = webdriver.PhantomJS(executable_path = './phantomjs.exe') #这里输入的是phantomjs.exe驱动路径 bro.get(url='https://news.163.com/domestic/') # 线程阻塞代码,上一个未执行完,下一个是不会执行的 sleep(2) #让滚轮向下滑动 js = 'window.scrollTo(0,document.body.scrollHeight)' bro.execute_script(js) # 非阻塞代码异步实现,所以这块要给一个暂停时间防止网速不好或者一些因素引起的问题 sleep(2) bro.execute_script(js) sleep(2) bro.execute_script(js) sleep(2) a_tag = bro.find_element_by_xpath('/html/body/div/div[3]/div[4]/div[1]/div/div/a') a_tag.click() sleep(2) #源码数据就包含了所有的新闻数据 page_text = bro.page_source with open('./wangyi.html','w',encoding='utf-8') as fp: fp.write(page_text)
PhantomJS为用户提供了一个截屏的功能,使用save_screenshot函数实现
from selenium import webdriver import time # phantomjs路径 path = r'PhantomJS驱动路径' browser = webdriver.PhantomJS(path) # 打开百度 url = 'http://www.baidu.com/' browser.get(url) time.sleep(3) browser.save_screenshot(r'phantomjsaidu.png') # 查找input输入框 my_input = browser.find_element_by_id('kw') # 往框里面写文字 my_input.send_keys('美女') time.sleep(3) #截屏 browser.save_screenshot(r'phantomjsmeinv.png') # 查找搜索按钮 button = browser.find_elements_by_class_name('s_btn')[0] button.click() time.sleep(3) browser.save_screenshot(r'phantomjsshow.png') time.sleep(3) browser.quit()
selenium实现切换iframe:
from selenium import webdriver from time import sleep bro = webdriver.Chrome(executable_path='./chromedriver.exe') url = 'https://qzone.qq.com/' bro.get(url=url) #将当前页面切换到了指定的iframe中,后续才可以定位到iframe中存在的标签 bro.switch_to.frame('login_frame') a_tag = bro.find_element_by_id('switcher_plogin') a_tag.click() sleep(3) bro.quit()
import requests from selenium import webdriver from lxml import etree import time driver = webdriver.Chrome(executable_path='/Users/bobo/Desktop/chromedriver') driver.get('https://qzone.qq.com/') #在web 应用中经常会遇到frame 嵌套页面的应用,使用WebDriver 每次只能在一个页面上识别元素,对于frame 嵌套内的页面上的元素,直接定位是定位是定位不到的。这个时候就需要通过switch_to_frame()方法将当前定位的主体切换了frame 里。 driver.switch_to.frame('login_frame') driver.find_element_by_id('switcher_plogin').click() #driver.find_element_by_id('u').clear() driver.find_element_by_id('u').send_keys('328410948') #这里填写你的QQ号 #driver.find_element_by_id('p').clear() driver.find_element_by_id('p').send_keys('xxxxxx') #这里填写你的QQ密码 driver.find_element_by_id('login_button').click() time.sleep(2) driver.execute_script('window.scrollTo(0,document.body.scrollHeight)') time.sleep(2) driver.execute_script('window.scrollTo(0,document.body.scrollHeight)') time.sleep(2) driver.execute_script('window.scrollTo(0,document.body.scrollHeight)') time.sleep(2) page_text = driver.page_source tree = etree.HTML(page_text) #执行解析操作 li_list = tree.xpath('//ul[@id="feed_friend_list"]/li') for li in li_list: text_list = li.xpath('.//div[@class="f-info"]//text()|.//div[@class="f-info qz_info_cut"]//text()') text = ''.join(text_list) print(text+' ') driver.close()
selenium规避被检测识别
现在不少大网站有对selenium采取了监测机制。比如正常情况下我们用浏览器访问淘宝等网站的 window.navigator.webdriver的值为 undefined。而使用selenium访问则该值为true。那么如何解决这个问题呢? 只需要设置Chromedriver的启动参数即可解决问题。在启动Chromedriver之前,为Chrome开启实验性功能参数excludeSwitches,它的值为['enable-automation'],完整代码如下:
from selenium.webdriver import Chrome from selenium.webdriver import ChromeOptions option = ChromeOptions() option.add_experimental_option('excludeSwitches', ['enable-automation']) driver = Chrome(options=option)
from selenium import webdriver from time import sleep import time if __name__ == '__main__': url = 'https://movie.douban.com/typerank?type_name=%E6%81%90%E6%80%96&type=20&interval_id=100:90&action=' # 发起请求前,可以让url表示的页面动态加载出更多的数据 path = r'C:UsersAdministratorDesktop爬虫授课day05ziliaophantomjs-2.1.1-windowsinphantomjs.exe' # 创建无界面的浏览器对象 bro = webdriver.PhantomJS(path) # 发起url请求 bro.get(url) time.sleep(3) # 截图 bro.save_screenshot('1.png') # 执行js代码(让滚动条向下偏移n个像素(作用:动态加载了更多的电影信息)) js = 'window.scrollTo(0,document.body.scrollHeight)' bro.execute_script(js) # 该函数可以执行一组字符串形式的js代码 time.sleep(2) bro.execute_script(js) # 该函数可以执行一组字符串形式的js代码 time.sleep(2) bro.save_screenshot('2.png') time.sleep(2) # 使用爬虫程序爬去当前url中的内容 html_source = bro.page_source # 该属性可以获取当前浏览器的当前页的源码(html) with open('./source.html', 'w', encoding='utf-8') as fp: fp.write(html_source) bro.quit()