Selenium-python

Selenium-python

有时web页面太复杂,无法找到API请求。这是我们就可以使用selenium了。

一、Selenium-python模块

1.selenium介绍

selenium是一个自动化的浏览器。你如何运用它完全取决于你自己。它主要用于自动化web应用程序以进行测试,但当然不限于此。无聊的基于web的管理任务也可以(而且应该)自动化。

Selenium得到一些最大的浏览器供应商的支持,这些供应商已经(或正在)采取步骤使Selenium成为他们浏览器的一部分。它也是无数其他浏览器自动化工具、api和框架中的核心技术。

总之是一个很牛逼的软件,也可以用来做爬虫。selenium通过浏览器驱动驱动浏览器,就好像一个真正的用户在操作一样,支持大部分的主流浏览器,包括IE,Firefox,Safari,Chrome,Opera等。我们可以利用它来模拟用户访问页面,点击按钮等,可以绕过一些复杂的认证场景,和js参数构造等反爬措施。

selenium官方文档:https://seleniumhq.github.io/selenium/docs/api/py/index.html

2.安装

2.1 selenium的安装

selenium的安装非常简单,一般情况下在命令行运行:

pip install selenium

即可搞定。

2.2浏览器驱动安装

selenium是通过浏览器驱动来操作浏览器的。不同的浏览器需要下载不同的驱动。

浏览器地址
Chrome:https://sites.google.com/a/chromium.org/chromedriver/downloads
Edge:https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
Firefox:https://github.com/mozilla/geckodriver/releases
Safari:https://webkit.org/blog/6900/webdriver-support-in-safari-10/

上表是主要的几大浏览器的驱动下载地址。

以chrome为例,驱动和浏览器版本对应,所以首先你要看你电脑中的浏览器版本。

在这里插入图片描述

在这里插入图片描述

根据查看到的版本下载相应驱动
在这里插入图片描述
在这里插入图片描述

下载好的驱动解压后是一个可执行文件,windows下是chromedriver.exe,linux下是chromedriver。下载好后将驱动文件放到环境变量中的文件夹下,可以放到python解释器的根目录。

3.开始使用

3.1简单案例

安装好环境后,我们就可以开始使用了

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
# 打开谷歌浏览器
driver = webdriver.Chrome()
# 访问页面
driver.get('http://www.python.org')
# 获取属性name='q'的元素
elem = driver.find_element_by_name('q')
# 清空它的text值,如果它是一个可以输入text的元素
elem.clear()
# 模拟输入'pycon'
elem.send_keys('pycon')
# 模拟回车键进行搜索
elem.send_keys(Keys.ENTER)
# 关闭浏览器
driver.close()

上面的代码会代开谷歌浏览器,然后访问http://www.python.org,在搜索框输入pycon,然后回车,最后关闭浏览器,这一切就像有人操作一样。

3.2代码解释

selenium.webdriver模块提供了所有的浏览器驱动实现。目前支持的浏览器有,Firefox, Chrome,IE等主流浏览器。Keys类提供了键盘按键例如Enter,F1,ALT等等。

from selenium import webdriver
from selenium.webdriver.common.keys import Keys

接下来,创建谷歌浏览器驱动的实例

driver = webdriver.Chrome()

driver.get方法将会访问提供的URL的页面。WebDriver会等到页面完全加载(也就是说,“onload”事件已经触发)之后才会返回。值得注意的是,如果您的页面在加载时使用了大量AJAX,那么WebDriver可能不知道它何时完全加载完毕。

driver.get("http://www.python.org")

WebDriver提供了一些通过find_element_by_*的方法来查找元素。例如,元素input text能够被方法find_element_by_name方法通过它的name属性定位。

elem = driver.find_element_by_name("q")

接下来,我们发送键,这类似于使用键盘输入键。可以使用selenium.webdriver.common.keys导入的Keys类来发送特殊的功能键。为了安全,我们首先清空任何input输入框中预填充的文本(例如“Search”)以免它会影响我们的搜索结果:

elem.clear()
elem.send_keys("pycon")
elem.send_keys(Keys.RETURN)

最后,关闭浏览器窗口。您还可以调用quit方法而不是close。退出将退出整个浏览器,而关闭’将关闭一个标签页,但如果只有一个标签页是打开的,默认情况下,大多数浏览器将完全退出。

driver.close()	

4.页面导航

使用WebDriver要做的第一件事是导航到一个链接。通常通过调用get方法:

driver.get("http://www.google.com")
4.1与页面交互

仅仅是能够打开不同的页面并没有什么用。我们真正想做的是与页面交互,或者更具体的说,与页面中对的HTML元素交互。首先我们要找到一个元素。WebDriver 提供了一些方法查找元组。例如,给定一个元素定义为:

<input type="text" name="passwd" id="passwd-id" />

你可以找到它使用下面任何一个方法:

element = driver.find_element_by_id("passwd-id")
element = driver.find_element_by_name("passwd")
element = driver.find_element_by_xpath("//input[@id='passwd-id']")

你也可以通过它的text查找,但是要小心。文本必须完全匹配。在WebDriver中使用XPATH时也应该小心。如果有多个元素与查询匹配,则只返回第一个元素。如果什么也找不到,则会引发NoSuchElementException

WebDriver有一个“基于对象”的API;我们使用相同的接口表示所有类型的元素。这意味着,尽管您可能会看到许多可能的方法,当您点击IDE的自动完成键组合时,您可以调用它们,但并不是所有这些方法都有意义或有效。别担心!WebDriver将尝试做正确的事情,如果您调用一个没有意义的方法(例如,“meta”标签上的“setSelected()”),将引发异常。

你有一个元素。你能用它做什么?首先,你可能想在文本框中输入一些文本:

element.send_keys("some text")

你可以使用Keys类模拟按箭头键:

element.send_keys(" and some", Keys.ARROW_DOWN)

可以在任何元素上调用send_keys,这样就可以测试键盘快捷方式,比如GMail上使用的快捷方式。这样做的一个副作用是,在文本字段中键入一些内容,但不会自动清除它。相反,您键入的内容将附加到已经存在的内容后面。使用clear方法可以轻松清除文本字段或文本区域的内容:

element.clear()
4.2填充表单

我们已经了解了如何在文本区域或文本字段中输入文本,那么其他元素呢?您可以“切换”下拉框的状态,并且可以使用“setSelected”设置类似于“OPTION tag selected”的内容。

element = driver.find_element_by_xpath("//select[@name='name']")
all_options = element.find_elements_by_tag_name("option")
for option in all_options:
    print("Value is: %s" % option.get_attribute("value"))
    option.click()

这将找到页面上的第一个“SELECT”元素,并依次循环遍历它的每个选项,打印出它们的值,并依次选择它们。

如您所见,这不是处理SELECT元素最有效的方法。WebDriver的支持类包括一个名为“Select”的类,它提供了与select标签交互的有用方法:

from selenium.webdriver.support.ui import Select
select = Select(driver.find_element_by_name('name'))
select.select_by_index(index)
select.select_by_visible_text("text")
select.select_by_value(value)

WebDriver还提供了取消选择所有选项的功能:

select = Select(driver.find_element_by_id('id'))
select.deselect_all()

这将从页面上的特定select标签中取消选择所有选项。假设在一个测试中,我们需要所有默认选中选项的列表,Select class提供了一个属性方法,返回一个列表:

select = Select(driver.find_element_by_xpath("//select[@name='name']"))
all_selected_options = select.all_selected_options

获取所有可用选项:

options = select.options

一旦您完成了表单的填写,您可能想要提交它。一种方法是找到“提交”按钮并点击它:

# Assume the button has the ID "submit" :)
driver.find_element_by_id("submit").click()

另外,WebDriver对每个元素都有快捷的方法“submit”。如果您对表单中的元素调用此函数,WebDriver将遍历DOM,直到找到所包含的表单,然后在此基础上调用submit。如果元素不在表单中,则会引发NoSuchElementException:

element.submit()
4.3拖放

您可以使用拖放操作,将一个元素移动一定的距离,或者移动到另一个元素上:

element = driver.find_element_by_name("source")
target = driver.find_element_by_name("target")

from selenium.webdriver import ActionChains
action_chains = ActionChains(driver)
action_chains.drag_and_drop(element, target).perform()

没有成功,不知道为啥。http://www.w3school.com.cn/tiy/loadtext.asp?f=html5_draganddrop

4.4在窗口和frames之间移动

现代web应用程序很少出现一个页面中不包含任何frame或者只包含一个单一的窗口。WebDriver支持使用“switch_to_window”方法在指定窗口之间移动:

driver.switch_to_window("windowName")

所有对驱动程序的调用现在都将被解释为指向特定窗口。但是你怎么知道窗户的名字呢?看看打开它的javascript或链接:

<a href="somewhere.html" target="windowName">Click here to open a new window</a>

或者,您可以将“窗口句柄”传递给“switch_to_window()”方法。

知道了这一点,就可以像这样遍历每个打开的窗口:

for handle in driver.window_handles:
    driver.switch_to_window(handle)

你也可以从一个frame进入另一个frame(或进入iframe):

driver.switch_to_frame("frameName")

可以通过用点分隔路径来访问子frame,还可以通过它的索引指定frame。

driver.switch_to_frame("frameName.0.child")

上面的代码将转到名为“frameName”的frame第一个名为“child”的子frame。

一旦我们完成了frame的工作,我们将不得不回到父frame,可以使用:

driver.switch_to_default_content()
4.5弹出对话框

Selenium WebDriver内置了处理弹出对话框的支持。当你触发了一个会弹出窗口的动作后,你可以通过以下方式访问弹框:

alert = driver.switch_to.alert

这将返回当前打开的alert对象。使用该对象,您现在可以接受、取消、读取其内容。此接口在警报、确认和提示上同样有效。

4.6导航:历史和位置

前面,我们讨论了使用“get”命令(driver.get(“http://www.example.com”))导航到一个页面。正如您所看到的,WebDriver有许多更小的、以任务为中心的界面,导航是一个有用的任务。要浏览网页,你可以使用get方法:

driver.get("http://www.example.com")

要在浏览器的历史中来回移动:

driver.forward()
driver.back()

请注意,此功能完全依赖于底层驱动程序。

4.7Cookies
# Go to the correct domain
driver.get("http://www.example.com")

# Now set the cookie. This one's valid for the entire domain
cookie = {‘name’ : ‘foo’, ‘value’ : ‘bar’}
driver.add_cookie(cookie)

# And now output all the available cookies for the current URL
driver.get_cookies()

5.元素定位

有多种策略可以定位页面中的元素。你可以在你的案例中使用最合适的一个。Selenium提供了以下方法来定位页面中的元素:

  • find_element_by_id
  • find_element_by_name
  • find_element_by_xpath
  • find_element_by_link_text
  • find_element_by_partial_link_text
  • find_element_by_tag_name
  • find_element_by_class_name
  • find_element_by_css_selector

要查找多个元素(这些方法将返回一个列表):

  • find_elements_by_name
  • find_elements_by_xpath
  • find_elements_by_link_text
  • find_elements_by_partial_link_text
  • find_elements_by_tag_name
  • find_elements_by_class_name
  • find_elements_by_css_selector

除了上面给出的公共方法之外,还有两个私有方法可能对page对象中的定位器有用。

这是两种私有方法:

find_element and find_elements.

代码示例:

from selenium.webdriver.common.by import By

driver.find_element(By.XPATH, '//button[text()="Some text"]')
driver.find_elements(By.XPATH, '//button')

以下是按类提供的属性:

ID = "id"
XPATH = "xpath"
LINK_TEXT = "link text"
PARTIAL_LINK_TEXT = "partial link text"
NAME = "name"
TAG_NAME = "tag name"
CLASS_NAME = "class name"
CSS_SELECTOR = "css selector"

6.Waits

如今,大多数web应用程序都使用AJAX技术。当浏览器加载页面时,页面内的元素可能在不同的时间间隔加载。

这使得定位元素变得困难:如果DOM中还没有元素,那么locate函数将引发一个ElementNotVisibleException异常。使用waits我们可以解决这个问题。等待在执行的操作之间提供了一些空闲——主要是定位元素或使用元素的任何其他操作。

Selenium Webdriver提供两种类型的等待——隐式和显式。显式等待使WebDriver在继续执行之前等待某个条件的发生。隐式等待使WebDriver在试图定位元素时轮询DOM一段时间。

6.1显示等待

显式等待是您定义的代码,用于在继续执行代码之前等待特定条件的发生。这种情况的极端情况是time.sleep(),它将条件设置为等待的确切时间。这里提供了一些方便的方法,可以帮助您编写只需等待所需时间的代码。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.Firefox()
driver.get("http://somedomain/url_that_delays_loading")
try:
    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "myDynamicElement"))
    )
finally:
    driver.quit()

除非在10秒内找到要返回的元素,否则在抛出TimeoutException之前,将等待10秒。默认情况下,WebDriverWait每500毫秒调用ExpectedCondition一次,直到成功返回。成功的返回是针对ExpectedCondition类型的布尔返回true或not null返回值,用于所有其他ExpectedCondition类型。

预期的条件

在自动化web浏览器时,经常使用一些常见的条件。Selenium Python绑定提供了一些方便的方法,因此您不必自己编写一个expected_condition类,也不必为它们创建自己的实用程序包。

  • title_is
  • title_contains
  • presence_of_element_located
  • 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
  • invisibility_of_element_located
  • element_to_be_clickable
  • staleness_of
  • element_to_be_selected
  • element_located_to_be_selected
  • element_selection_state_to_be
  • element_located_selection_state_to_be
  • alert_is_present
from selenium.webdriver.support import expected_conditions as EC

wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID, 'someid')))

expected_conditions模块包含一组预定义的条件,用于WebDriverWait。

自定义等待条件

当前面的便利方法都不符合您的需求时,您还可以创建自定义的等待条件。可以使用带有_call__方法的类创建自定义等待条件,当条件不匹配时,该类返回False。

class element_has_css_class(object):
  """An expectation for checking that an element has a particular css class.

  locator - used to find the element
  returns the WebElement once it has the particular css class
  """
  def __init__(self, locator, css_class):
    self.locator = locator
    self.css_class = css_class

  def __call__(self, driver):
    element = driver.find_element(*self.locator)   # Finding the referenced element
    if self.css_class in element.get_attribute("class"):
        return element
    else:
        return False

# Wait until an element with id='myNewInput' has class 'myCSSClass'
wait = WebDriverWait(driver, 10)
element = wait.until(element_has_css_class((By.ID, 'myNewInput'), "myCSSClass"))
6.2隐式条件

一个隐式的等待告诉WebDriver,当试图找到任何(或多个)不能立即使用的元素时,要轮询DOM一段时间。默认设置为0。一旦设置好,就为WebDriver对象的生命周期设置了隐式等待。

from selenium import webdriver

driver = webdriver.Firefox()
driver.implicitly_wait(10) # seconds
driver.get("http://somedomain/url_that_delays_loading")
myDynamicElement = driver.find_element_by_id("myDynamicElement")

7.WebDriver API

7.1 Action Chains
class selenium.webdriver.common.action_chains.ActionChains(driver)

动作链是一种自动化低层交互的方法,例如鼠标移动、鼠标按钮操作、按键和上下文菜单交互。这对于执行更复杂的操作非常有用,比如悬停和拖放。

生成用户操作。

当在actionchain对象上调用操作方法时,操作被存储在actionchain对象中的队列中。当您调用execute()时,将按事件排队的顺序触发事件。

动作链可以在链模式中使用:

menu = driver.find_element_by_css_selector(".nav")
hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1")

ActionChains(driver).move_to_element(menu).click(hidden_submenu).perform()

或者动作可以一个一个排队,然后执行。

menu = driver.find_element_by_css_selector(".nav")
hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1")

actions = ActionChains(driver)
actions.move_to_element(menu)
actions.click(hidden_submenu)
actions.perform()

无论哪种方式,操作都是按照调用它们的顺序执行的,一个接一个。

文档地址:https://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.common.action_chains

二、案例,实现微博登录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值