Selenium是一种自动控制任何类型的网络浏览器的工具,它可以与Python、Java、C#、Ruby等语言一起使用。 在本教程中,我们将研究如何用Python来使用Selenium。 通过使用Python和Selenium,你可以启动你选择的浏览器,获取任何网页,以编程方式点击链接,填写网络表格,并使用其他浏览器功能,如返回、前进和重新加载。 Selenium非常强大,比[Beautiful Soup]和[Scrapy]等网络搜刮工具更方便灵活。 它可以直接处理完全由JavaScript渲染的页面,如单页应用程序,而其他工具则不能。 这样做的好处是,启动浏览器进行测试和抓取会更耗费内存,速度也更慢。
自动浏览网页
Selenium可以实现网页浏览的自动化,但为什么你首先要这样做呢? 浏览器自动化有三个很好的理由,那就是测试、网络机器人和网络搜刮。
网络应用程序测试
网站已经发展成为网络应用程序,像其他任何软件一样,它们必须被测试以确保行为正确。 自动化测试减少了成本和时间,同时也提供了一个全天候的测试手段。它也使跨浏览器打样更容易。 测试能使调试后或进一步开发软件时可能需要的回归测试更快。它很容易扩展到各种设备和环境,从而可以轻松进行跨浏览器和跨设备测试。
网络机器人
任何你可以使用网络浏览器手动做的事情都可以使用Selenium和Python自动化。 这就是所谓的网络机器人。 它是一个执行命令或执行常规任务的软件,不需要用户的干预。这可以应用于任何在线的重复性任务。例如,假设你每天都从一个网站上订购同样的卷饼。 那么,与其每次都手动填写表格,不如对整个过程进行编程。 任何重复性的在线任务现在都可以通过创建一个Python脚本来进行优化。
网络驱动
为了使Python能够控制网络浏览器,需要一个叫做网络驱动程序的软件。 使用Selenium的两个非常流行的驱动是Firefox驱动和Chrome驱动。 我们将看一下这两个。 这些驱动程序中的每一个都是一个可执行文件。 Firefox使用geckodriver.exe,而Chrome使用chromedriver.exe。 一旦你下载了这些文件,你需要将它们手动添加到你的路径中,或者以编程方式指定路径。 我们将采取后一种方法。 对于Firefox gecko,我们使用的是[Win64版本]。 对于Chrome驱动,我们使用的是[32位版本]。
启动一个由Selenium控制的浏览器
我们已经准备好使用Selenium从Python中控制一个浏览器了! 下面是如何使用Selenium启动Firefox。 注意,我们把下载的geckodriver.exe文件作为executable_path指向了它。 如果你不采取这一步骤,浏览器将不能正确启动。 当这段代码运行时,它会以你在下面看到的风格启动Firefox,在URL区域有一个橙色条纹的主题,表明浏览器是通过Selenium控制的。
from selenium import webdriver
from shutil import which
driver = which('geckodriver.exe')
browser = webdriver.Firefox(executable_path=driver)
用Selenium启动Chrome浏览器
要启动Chrome浏览器,我们可以简单地改变使用中的驱动程序,像这样。 当Chrome浏览器通过Selenium启动时,它会显示一个信息,即Chrome浏览器正被自动化测试软件控制。
from selenium import webdriver
from shutil import which
driver = which('chromedriver.exe')
browser = webdriver.Chrome(executable_path=driver)
关闭浏览器
你可以像平时一样通过点击X来手动关闭Selenium控制的浏览器。 一个更好的选择是,当你的脚本完成了你编程的工作,你应该在你的代码中使用**.quit()**方法明确地关闭浏览器。
from selenium import webdriver
from shutil import which
driver = which('geckodriver.exe')
browser = webdriver.Firefox(executable_path=driver)
browser.quit()
在Chrome或Firefox中进行无头浏览
如果你不愿意,你不必启动浏览器来运行你的Selenium应用程序。 这就是所谓的无头模式。 要在这两个浏览器中使用无头模式,只需根据需要设置Options()即可。
火狐浏览器
from selenium import webdriver
from shutil import which
from selenium.webdriver.firefox.options import Options
options = Options()
options.headless = True
driver = which('geckodriver.exe')
browser = webdriver.Firefox(options=options, executable_path=driver)
browser.quit()
浏览器
from selenium import webdriver
from shutil import which
from selenium.webdriver.chrome.options import Options
options = Options()
options.headless = True
driver = which('chromedriver.exe')
browser = webdriver.Chrome(options=options, executable_path=driver)
browser.quit()
获取特定页面
要指示Selenium控制的浏览器从特定页面获取内容,你可以使用**.get()**方法。 下面是一个访问互联网上一个流行的搜索引擎网页的例子。
from selenium import webdriver
from shutil import which
driver = which('geckodriver.exe')
browser = webdriver.Firefox(executable_path=driver)
browser.get('https://duckduckgo.com/')

寻找页面上的元素
一旦浏览器访问了一个特定的页面,Selenium可以用各种方法找到页面上的元素。 这些是你可以用来寻找页面元素的方法。 正如你所看到的,它们有很多。 在大多数情况下,你只需要两到三个就可以完成你需要做的事情。 .find_elements_by_css_selector()和.find_element_by_xpath()方法似乎非常流行。
方法名称 | 返回的Web元素对象/列表 |
| browser.find_element_by_class_name(name) browser.find_elements_by_class_name(name ) | 使用该CSS类名称的元素 |
| browser. find_element_by_css_selector(selector) browser.find_elements_by_css_selector(selector ) | 匹配CSS选择器的元素 |
| browser.find_element_by_id(id) browser.find_elements_by_id(id ) | 具有匹配的id属性值的元素 |
| browser.find_element_by_link_text(text) browser.find_elements_by_link_text(text ) | 与所提供的文本完全匹配的<a>元素 |
| browser. find_element_by_partial_link_text(text) browser.find_elements_by_partial_link_text ( text ) | 包含所提供文字的<a>元素 |
| browser.find_element_by_name(name) browser.find_elements_by_name( name ) | 具有匹配的name属性值的元素 |
| browser.find_element_by_tag_name(name) browser.find_elements_by_tag_name( name ) | 具有匹配的标签名称的元素(不区分大小写;<a>元素由'a'和'A'来匹配 |
| browser.find_element_by_xpath((xpath) browser.find_elements_by_xpath((xpath) | 具有指定xpath的元素。 |
定位一个文本输入
我们已经知道如何启动一个网络浏览器并访问一个搜索引擎网站。 现在我们来看看如何选择页面上的文本输入。 有很多方法来选择页面上的元素,也许最简单和最准确的方法是使用XPath。 首先,你需要使用浏览器中的开发工具来找到要使用的Xpath。
当选择复制Xpath时,我们得到这个值。
//*[@id="search_form_input_homepage"]
我们现在可以在我们的程序中使用它,当我们运行程序时,我们看到打印出来的元素显示它是一个FirefoxWebElement,所以定位页面上的文本输入是成功的。
from selenium import webdriver
from shutil import which
driver = which('geckodriver.exe')
browser = webdriver.Firefox(executable_path=driver)
browser.get('https://duckduckgo.com/')
element = browser.find_element_by_xpath('//*[@id="search_form_input_homepage"]')
print(element)
<selenium.webdriver.firefox.webelement.FirefoxWebElement (session="1302c443-53b9-4b4d-9354-bc93c9d5d7ba", element="bb944d54-6f29-479a-98af-69a70b0a41a1")>
输入一个文本输入框
一旦找到了一个文本输入,程序就可以向该输入输入文本。 要做到这一点,需要使用**.send_keys()**方法。
from selenium import webdriver
from shutil import which
driver = which('geckodriver.exe')
browser = webdriver.Firefox(executable_path=driver)
browser.get('https://duckduckgo.com/')
element = browser.find_element_by_xpath('//*[@id="search_form_input_homepage"]')
element.send_keys('How do you automate a web browser?')
如何按回车键
一旦你找到了一个文本输入,并向其中输入了一些文本,下一步通常是什么? 没错,你需要按下回车键,以便发生任何事情。 这也可以用**.send_keys()**方法来完成,但你必须在Selenium中导入Keys模块。 下面是我们如何做的。 注意,一旦按下回车键,网站就会返回一个结果列表,这些结果都来自我们的Python脚本
from selenium import webdriver
from shutil import which
from selenium.webdriver.common.keys import Keys
driver = which('geckodriver.exe')
browser = webdriver.Firefox(executable_path=driver)
browser.get('https://duckduckgo.com/')
element = browser.find_element_by_xpath('//*[@id="search_form_input_homepage"]')
element.send_keys('How do you automate a web browser?')
element.send_keys(Keys.RETURN)
Selenium Easy实践案例
Selenium Easy[网站]有一个测试操场,我们可以用来尝试一些更常见的Selenium任务。 下面是一个带有相关按钮的文本输入的例子。 我们可以在文本字段中输入,然后点击按钮来显示一条信息。 我们将使用selenium编写一个Python脚本来完成这项任务。
下面是这个测试的代码。 我们将使用**.find_element_by_id()方法来定位文本输入,使用.find_element_by_xpath()方法来定位按钮。 我们还可以使用.send_keys()来填写文本输入,使用.click()**方法来点击按钮。
from selenium import webdriver
from shutil import which
from selenium.webdriver.common.keys import Keys
driver = which('geckodriver.exe')
browser = webdriver.Firefox(executable_path=driver)
browser.get('https://www.seleniumeasy.com/test/basic-first-form-demo.html')
input_element = browser.find_element_by_id('user-message')
input_element.send_keys('Check out this great message!')
show_message_button = browser.find_element_by_xpath('//*[@id="get-input"]/button')
show_message_button.click()
运行测试后,我们看到浏览器已经成功地进行了我们编程的动作。 文本被输入,按钮被点击,信息被显示。
网络元素的属性和方法
这使我们开始讨论网络元素的属性和方法。 一旦通过Selenium选择了一个元素并分配给一个变量,这个变量现在就有了属性和方法,我们可以用它来进行编程操作。 这就是我们如何能够使用诸如.send_keys()和.click()的原因。 下面是一些常用的WebElements的列表。
element.send_keys()
模拟在元素中打字。
Args
- value - 用于输入的字符串,或设置表格字段。 对于设置文件输入,这可能是一个本地文件路径。
用它来发送简单的按键事件或填写表格字段
form_textfield = browser.find_element_by_name('username')
form_textfield.send_keys("admin")
这也可以用来设置文件输入。
file_input = browser.find_element_by_name('profilePic')
file_input.send_keys("path/to/profilepic.gif")
element.click()
点击选中的元素。
element.submit()
提交一个表单。
element.get_attribute()
获取元素的给定属性。
这个方法将首先尝试返回具有给定名称的属性的值。如果一个具有该名称的属性不存在,它会返回具有相同名称的属性的值。如果没有这个名字的属性,则返回None。
被认为是真理的值,即等于 "真 "或 "假",将被返回为布尔值。 所有其他非 "无 "的值都以字符串的形式返回。 对于不存在的属性,将返回None。
Args
- name - 要检索的属性/属性的名称。
例如
# Check if the "active" CSS class is applied to an element.
is_active = "active" in target_element.get_attribute("class")
element.clear()
如果它是一个文本输入元素,则清除文本。
element.get_property()
获取该元素的给定属性。
Args
- name - 要检索的属性的名称。
例子
text_length = target_element.get_property("text_length")
element.is_displayed()
该元素是否对用户可见。
element.is_enabled()
返回该元素是否被启用。
element.is_selected()
返回该元素是否被选中。 可以用来检查一个复选框或单选按钮是否被选中。
element.text
元素中的文本,例如hello中的'hello'。
element.id
标签的id。
element.tag_name
标签的名称,如
两个输入和一个点击按钮
这里是来自selenium easy网站的另一个例子。 在这个练习中,我们要创建一个python脚本,使用selenium为两个不同的输入字段输入一个值,然后点击页面上的一个按钮,对输入到这两个输入字段的值进行操作。
对于这个测试的解决方案,我们将在无头模式下运行Firefox。 我们将使用selenium在输入一和二中输入一个数字,然后点击一个按钮将两者相加。 最后,我们将使用selenium在页面上找到结果并在Python脚本中打印出来。 如果数字相加与我们预期的一样,那么我们就知道测试成功了,不需要启动浏览器。 当脚本运行时,我们看到输出为17,所以我们知道它成功了,因为我们期望10+7=17。
from selenium import webdriver
from shutil import which
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.firefox.options import Options
options = Options()
options.headless = True
driver = which('geckodriver.exe')
browser = webdriver.Firefox(options=options, executable_path=driver)
browser.get('https://www.seleniumeasy.com/test/basic-first-form-demo.html')
input_element_one = browser.find_element_by_id('sum1')
input_element_one.send_keys('10')
input_element_two = browser.find_element_by_id('sum2')
input_element_two.send_keys('7')
get_total_element = browser.find_element_by_xpath('//*[@id="gettotal"]/button')
get_total_element.click()
result_element = browser.find_element_by_id('displayvalue')
print(result_element.text)
17
用动作链拖放
使用Selenium,很多事情都可以用一个函数来完成。 因此,我们将看一下Selenium中拖放操作的一个稍具挑战性的例子。 拖放操作有三个基本步骤。首先,必须选择一个对象或文本。然后,必须把它拖到所需的区域,最后放到合适的位置。 为了在Python中演示这一点,我们将使用这个dhtmlgoodies网页,它将作为我们脚本的练习场。 我们要做的标记看起来像这样。
为了在Selenium中实现拖放,我们必须添加ActionChains库。动作链扩展了Selenium,允许网络驱动器执行更复杂的任务,如拖放。 当ActionChains对象上的操作方法被调用时,这些操作被存储在一个队列中。然后我们调用**.drag_and_drop()**方法,传入源和目的地。 最后,作为一个方法链调用.perform()方法来执行动作。 让我们来看看这个动作。
from selenium import webdriver
from shutil import which
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
driver = which('geckodriver.exe')
browser = webdriver.Firefox(executable_path=driver)
browser.get('http://www.dhtmlgoodies.com/scripts/drag-drop-custom/demo-drag-drop-3.html')
source_element = browser.find_element_by_xpath('//*[@id="box7"]')
destination_element = browser.find_element_by_xpath('//*[@id="box107"]')
actions = ActionChains(browser)
actions.drag_and_drop(source_element, destination_element).perform()
点击浏览器按钮
Selenium也可以通过以下方法模拟对各种浏览器按钮的点击。
- browser.back() 点击后退按钮。
- browser.forward() 点击 "前进 "按钮。
- browser.refresh() 点击Refresh/Reload按钮。
- browser.quit() 点击关闭窗口按钮。
应用实例。股票报价检查器
现在我们可以把我们所学到的关于Selenium和Python的所有知识结合起来,创建一个简单的应用程序,允许你在程序中输入一个股票符号,它将获取并返回当前的报价给你。 这个过程被置于一个循环中,允许用户继续输入股票符号并获得报价。 要结束这个程序,用户可以简单地输入字母 "q "来退出这个程序。 下面是代码和一些查找一些股票的样本输出,如spy, aapl, 和tsla。 还要注意的是,我们使用时间模块来添加一些等待时间,否则如果远程网页没有及时加载,程序可能会失败。
import time
from selenium import webdriver
from shutil import which
from selenium.webdriver.common.keys import Keys
driver = which('geckodriver.exe')
browser = webdriver.Firefox(executable_path=driver)
browser.get('https://finance.yahoo.com')
ticker_to_lookup = True
while (ticker_to_lookup != "q"):
ticker_to_lookup = input('What ticker to you want to look up? (q to quit) ')
if ticker_to_lookup == 'q':
browser.quit()
break
quote_lookup_text_input = browser.find_element_by_xpath('//*[@id="Col2-0-SymbolLookup-Proxy"]/div/div/div/fieldset/input')
quote_lookup_text_input.send_keys(ticker_to_lookup, Keys.RETURN)
time.sleep(10)
quote_span = browser.find_element_by_xpath(
'/html/body/div[1]/div/div/div[1]/div/div[2]/div/div/div[4]/div/div[3]/div[1]/div/span[1]')
print(ticker_to_lookup + ' is currently ' + quote_span.text)
browser.back()
time.sleep(5)
What ticker to you want to look up? (q to quit) spy
spy is currently 283.71
What ticker to you want to look up? (q to quit) aapl
aapl is currently 287.26
What ticker to you want to look up? (q to quit) tsla
tsla is currently 736.51
What ticker to you want to look up? (q to quit) q
Process finished with exit code 0
Selenium等待功能
Selenium有一些被称为等待函数的东西。 等待函数的存在是因为现代网站经常使用异步技术,如AJAX,在不重新加载的情况下更新网页的部分内容。 这提供了一个很好的用户体验,但有时Selenium驱动程序可能会遇到问题,如果它试图在页面上找到一个元素,然后才加载。 这将在脚本中引发一个异常,我们的程序将无法正常工作。 等待函数通过在执行的动作之间添加时间间隔来帮助解决这个问题,从而使网络驱动器在与元素进行交互之前等待其加载。Selenium提供两种类型的等待,显式和隐式。显式等待,当与一个条件配对时,将等待该条件得到满足后再执行。隐式等待将尝试在一定时间内轮询DOM,直到该元素可用。
一个使用等待函数的例子
为了在Selenium中开始使用等待,我们需要导入一些必要的模块。当然,我们需要webdriver模块来开始使用。 然后我们导入三个新的模块,它们是By,WebDriverWait和expected_conditions。 我们使用别名来引用expected_conditions作为EC,以使编写代码更容易。
from selenium import webdriver
from shutil import which
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
我们要演示的使用Selenium等待的页面是在Google Earth。 如果你访问Google Earth,你可以看到上面的导航条实际上比页面的其他部分加载得稍晚。 如果Selenium试图在导航栏中找到一个链接并立即点击,它就会失败。 这是一个很好的例子,说明我们可以使用Selenium的等待,这样脚本就能正常工作,即使页面的某个片段加载稍有延迟。

from selenium import webdriver
from shutil import which
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = which('geckodriver.exe')
browser = webdriver.Firefox(executable_path=driver)
browser.get('https://www.google.com/earth/')
wait = WebDriverWait(browser, 10)
launchButton = wait.until(EC.element_to_be_clickable((By.XPATH, '/html/body/header/div/nav[1]/ul[2]/li[2]/a')))
launchButton.click()
上面的代码使用了WebDriverWait函数的显式等待。如果我们制定的条件没有得到满足,这个函数将在10秒后抛出一个异常(指定为参数2的数字)。接下来,我们为显式等待创建一个条件。为了实现这一点,我们将其与预期条件模块进行比较,使程序等待,直到一个特定的动作可以完成。 上面的代码是告诉程序等待,直到发射地球的按钮在浏览器中变得可以点击。我们简单地使用按钮的XPath并实现这个想法。继续检查该按钮。 就在点击之前的那行代码是说要等待,直到该按钮可被点击,然后才真正推进点击。 在本教程的另一个例子中,我们使用Python的sleep()函数来做类似的事情。 使用Selenium等待函数在代码中会比较冗长,但你的脚本使用它们会运行得更快,因为一旦项目准备好了,它们就会立即行动,而sleep()函数无论如何都会等待一个指定的时间。
Selenium Python教程总结
在本教程中,我们看到了如何通过Selenium库的Python代码直接控制网络浏览器,从而使基于网络的任务完全自动化。 Selenium的功能相当强大,可以让你完成任何你在网络浏览器中手动完成的任务,如访问各种URL、填写表格、点击页面元素、使用拖放等。 网络浏览器也许是互联网时代最常用的软件,能够在代码中实现自动化并利用它是一项伟大的技能。