人生苦短, 我用 Python
前文传送门:
小白学 Python 爬虫(1): 开篇 https://www.geekdigging.com/2019/11/13/3303836941/
小白学 Python 爬虫 (2): 前置准备(一) 基本类库的安装 https://www.geekdigging.com/2019/11/20/2586166930/
小白学 Python 爬虫(3): 前置准备(二)Linux 基础入门 https://www.geekdigging.com/2019/11/21/1005563697/
小白学 Python 爬虫(4): 前置准备(三)Docker 基础入门 https://www.geekdigging.com/2019/11/22/3679472340/
小白学 Python 爬虫 (5): 前置准备(四) 数据库基础 https://www.geekdigging.com/2019/11/24/334078215/
小白学 Python 爬虫 (6): 前置准备(五) 爬虫框架的安装 https://www.geekdigging.com/2019/11/25/1881661601/
小白学 Python 爬虫(7):HTTP 基础 https://www.geekdigging.com/2019/11/26/1197821400/
小白学 Python 爬虫(8): 网页基础 https://www.geekdigging.com/2019/11/27/101847406/
小白学 Python 爬虫(9): 爬虫基础 https://www.geekdigging.com/2019/11/28/1668465912/
小白学 Python 爬虫(10):Session 和 Cookies https://www.geekdigging.com/2019/12/01/2475257648/
小白学 Python 爬虫(11):urllib 基础使用(一) https://www.geekdigging.com/2019/12/02/2333822325/
小白学 Python 爬虫(12):urllib 基础使用(二) https://www.geekdigging.com/2019/12/03/819896244/
小白学 Python 爬虫(13):urllib 基础使用(三) https://www.geekdigging.com/2019/12/04/2992515886/
小白学 Python 爬虫(14):urllib 基础使用(四) https://www.geekdigging.com/2019/12/05/104488944/
小白学 Python 爬虫(15):urllib 基础使用(五) https://www.geekdigging.com/2019/12/07/2788855167/
小白学 Python 爬虫(16):urllib 实战之爬取妹子图 https://www.geekdigging.com/2019/12/09/1691033431/
小白学 Python 爬虫(17):Requests 基础使用 https://www.geekdigging.com/2019/12/10/1910005577/
小白学 Python 爬虫(18):Requests 进阶操作 https://www.geekdigging.com/2019/12/11/1468953802/
小白学 Python 爬虫(19):Xpath 基操 https://www.geekdigging.com/2019/12/12/3568648672/
小白学 Python 爬虫(20):Xpath 进阶 https://www.geekdigging.com/2019/12/13/2569867940/
小白学 Python 爬虫(21): 解析库 Beautiful Soup(上) https://www.geekdigging.com/2019/12/15/2789385418/
小白学 Python 爬虫(22): 解析库 Beautiful Soup(下) https://www.geekdigging.com/2019/12/16/876770087/
小白学 Python 爬虫(23): 解析库 pyquery 入门 https://www.geekdigging.com/2019/12/17/876770088/
小白学 Python 爬虫(24):2019 豆瓣电影排行 https://www.geekdigging.com/2019/12/18/1275791678/
小白学 Python 爬虫(25): 爬取股票信息 https://www.geekdigging.com/2019/12/19/1066903974/
小白学 Python 爬虫(26): 为啥买不起上海二手房你都买不起 https://www.geekdigging.com/2019/12/20/788803015/
小白学 Python 爬虫(27): 自动化测试框架 Selenium 从入门到放弃(一) https://www.geekdigging.com/2019/12/22/151891020/
Ajax
在介绍交互之前, 我们先简单了解一下新名词: Ajax .
Ajax 全写为 "Asynchronous Javascript And XML" (异步 JavaScript 和 xml), 是指一种创建交互式网页应用的网页开发技术.
Ajax 是一种在无需重新加载整个网页的情况下, 能够更新部分网页的技术.
重点来了, 我们如果在网站中使用 Ajax , 可以在整个网页不刷新的情况下, 更够更新网页上的显示信息(DOM 节点), 也就是 DOM 节点, 这种技术被广泛的应用到各个网站之中, 最开始的时候, 大家都只是使用它更新部分的网页, 也不知道是哪位大佬异想天开: 既然 Ajax 可以更新部分网页, 那么能不能用它来更新全部网页呢? 这就产生了现代的前端框架: React , vue 和 Angular.
这种思想, 现在被更加广泛的应用于各大网站之中, 因为这种方式, 前端页面上只有最基础的 DOM 节点, 其余所有的 DOM 节点都是由 JavaScript 动态渲染出来的, 而 JavaScript 都是经过打包处理的, 可读性极差.
那么为什么要选用前端框架呢? html + CSS + jQuery 就不行么?
当然不是, 其实之所以现在我们需要选择框架, 本质上是因为我们面临的需求变了. 大家肯定都明白如果我们只写一个纯展示信息的页面, 没有任何交互功能的页面, 其实即便是现在, 我们也是不需要选择框架的, 我们只需要写几行 CSS 和 HTML 就可以完成任务.
所以是因为我们面临的需求变得复杂了, 我们的应用经常需要在运行时做一些交互.
现代的前端开发, 我们开发的应用经常需要在运行时来做一些交互, 这些交互在早期只是个幻灯片或者 Tab 切换下拉菜单等一些简单的交互, 这些交互用 jQuery 实现完全没什么问题. 但现代的前端我们的目标是用 web 去 PK 原生应用, 去和 Native 进行 PK .
emmmmmmmmm, 聊偏了, 下面我们接着聊 Selenium .
等待
如今, 大多数 Web 应用程序都在使用 Ajax 技术. 当浏览器加载页面时, 该页面中的元素可能会以不同的时间间隔加载. 这使定位元素变得困难: 如果 DOM 中尚不存在元素, 则定位函数将引发 ElementNotVisibleException 异常. 使用等待, 我们可以解决此问题. 等待在执行的动作之间提供了一定的松弛时间 - 主要是定位元素或对该元素进行的任何其他操作.
Selenium Webdriver 提供两种类型的等待 - 隐式和显式. 显式等待使 WebDriver 等待特定条件发生, 然后再继续执行. 隐式等待使 WebDriver 在尝试查找元素时轮询 DOM 一定时间.
显式等待
我们可以使用 time.sleep() 来设定等待时间, 完全没有问题, 但是它需要将条件设置为要等待的确切时间段. 如果我们不知道准确的渲染时间, 我们就无法设定一个比较合适的值.
Selenium 为我们提供了 WebDriverWait 与 ExpectedCondition 来完成这件事情, 看代码:
- 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
- driver = webdriver.Chrome()
- driver.get("https://www.jd.com/")
- try:
- element = WebDriverWait(driver, 10).until(
- EC.presence_of_element_located((By.ID, "key"))
- )
- finally:
- driver.quit()
结果如下:
<selenium.webdriver.remote.webelement.WebElement (session="b1baacca997d18d7d54447127c844d15", element="a472369e-3196-4456-b43e-4e1b280bf5b9")>
上面我们使用了 WebDriverWait 来设置最长等待时间, 这里我们选择获取 JD 首页的输入框, 我们限定的等待时间为 10s , 如果它在 10s 内都无法返回结果, 将会抛出 TimeoutException . 默认情况下, WebDriverWait 每 500 毫秒调用 ExpectedCondition , 直到成功返回.
隐式等待
隐式等待告诉 WebDriver 在尝试查找不立即可用的一个或多个元素时在一定时间内轮询 DOM . 默认设置为 0 . 设置后, 将在 WebDriver 对象的生存期内设置隐式等待.
- from selenium import webdriver
- driver = webdriver.Chrome()
- driver.implicitly_wait(10) # seconds
- driver.get("https://www.jd.com/")
- key = driver.find_element_by_id("key")
- print(key)
节点交互
Selenium 为我们提供了一些节点的交互动作, 如输入文字时可以用 send_keys() 方法, 清空文字时可以用 clear() 方法, 点击按钮时可以用 click() 方法.
- from selenium import webdriver
- import time
- driver = webdriver.Chrome()
- driver.implicitly_wait(10)
- driver.get('https://www.taobao.com/')
- input = driver.find_element_by_id('q')
- input.send_keys('IPad')
- time.sleep(1)
- input.clear()
- input.send_keys('Surface Pro')
- button = driver.find_element_by_class_name('btn-search')
- button.click()
在上面这个示例中, 我们先打开淘宝网, 并且开启了隐式等待, 先在搜索框中输入了 iPad , 在等待 1s 后删除, 再输入了 Surface Pro , 然后点击了搜索按钮, 先在淘宝搜索需要用户登录才能搜索, 所以我们直接跳转到了登录页.
执行 JavaScript
对于某些 Selenium API 没有提供的操作, 我们可以通过模拟运行 JavaScript 的方式来完成, 用到的方法是 execute_script() , 比如我们在淘宝首页将滚动条滑到底部:
- from selenium import webdriver
- driver = webdriver.Chrome()
- driver.get('https://www.taobao.com/')
- driver.execute_script('window.scrollTo(0, document.body.scrollHeight)')
获取信息
前面我们介绍了如何拿到 DOM 节点, 那么最重要的是我们要从 DOM 节点上来获取我们需要的信息.
因为我们获取的是 WebElement 类型, 而 WebElement 也提供了相关的方法来提取节点信息.
- from selenium import webdriver
- from selenium.webdriver.Chrome.options import Options
- # 实例化一个启动参数对象
- chrome_options = Options()
- # 设置浏览器窗口大小
- chrome_options.add_argument('--window-size=1366, 768')
- # 启动浏览器
- driver = webdriver.Chrome(chrome_options=chrome_options)
- url = 'https://www.geekdigging.com/'
- driver.get(url)
- title = driver.find_element_by_xpath('//*[@id="text-4"]/div/div/div[1]/div[2]/a')
- print(title)
- # 获取属性信息
- print(title.get_attribute('href'))
- # 获取文本信息
- print(title.text)
- # 获取位置
- print(title.location)
- # 获取大小
- print(title.size)
上面因为 Chrome 默认打开大小有点小, 打开小编博客的时候小编选择的这个 DOM 节点正好看到, 所以小编设置了一下 Chrome 浏览器打开时的大小.
具体信息的提取小编列出了一部分, 都加好注释了, 还有一部分比较有意思的属性小编列在下面, 供大家参考:
parent: 查找到此元素的 WebDriver 实例的内部引用.
rect: 具有元素大小和位置的字典.
screenshot_as_base64: 以 base64 编码字符串的形式获取当前元素的屏幕快照.
screenshot_as_png: 以二进制数据获取当前元素的屏幕截图.
最后这两个获取元素屏幕快照, 在获取验证码的时候将验证码截取出来会很好用的.
前进和后退
我们使用浏览器最上面的地方有一个前进和后退按钮, Selenium 完成这两个动作使用了 back() 和 forward() 这两个方法.
- import time
- from selenium import webdriver
- browser = webdriver.Chrome()
- browser.get('https://www.jd.com/')
- browser.get('https://www.taobao.com/')
- browser.get('https://www.geekdigging.com/')
- browser.back()
- time.sleep(1)
- browser.forward()
这个各位同学应该都看的懂, 小编就不多啰嗦了.
Cookies
又到了一个重点内容, Cookies , 它是和服务端保持会话的一个重要元素. Selenium 为我们提供了一些方法, 让我们可以方便的对 Cookies 进行增删改查等操作. 示例如下:
- from selenium import webdriver
- browser = webdriver.Chrome()
- browser.get('https://www.geekdigging.com/')
- # 获取 cookies
- print(browser.get_cookies())
- # 添加一个 cookie
- browser.add_cookie({
- 'name': 'name', 'domain': 'www.geekdigging.com', 'value': 'geekdigging'
- })
- print(browser.get_cookies())
- # 删除所有 cookie
- browser.delete_all_cookies()
- print(browser.get_cookies())
Selenium 的简单介绍就到这里了, 希望各位同学看完后能自己动手试一试, 毕竟并不难.
示例代码
本系列的所有代码小编都会放在代码管理仓库 GitHub 和 Gitee 上, 方便大家取用.
示例代码 - GitHub
示例代码 - Gitee
参考
- https://www.jianshu.com/p/02af89375b54
- https://cuiqingcai.com/5630.html
来源: https://www.cnblogs.com/babycomeon/p/12105449.html