译者的话
有许多网页使用Ajax获取数据的,但Ajax接口有许多加密参数,因此我们难以直接找出其规律,也很难直接分析Ajax来抓取。
为了解决这个问题,我们可以使用模拟浏览器运行的方式,来做到在浏览器看到什么,抓取的源码就是什么,做到可见可爬。
而Seleniums是实现上述效果的理想工具,怎么理想?Selenium提供了很多交互方法,比如下拉,这个可以被应用在比如京东商品网页的抓取,当点击进去时,我们只能接收到30个商品的信息,如果你使用下拉按钮,你就可以获取到全部60个商品的信息,然后我们再抓取。
(一)简单的使用方法
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Firefox()
driver.get("http://www.python.org")
assert "Python" in driver.title
elem = driver.find_element_by_name("q")
elem.clear()
elem.send_keys("pycon")
elem.send_keys(Keys.RETURN)
assert "No results found." not in driver.page_source
driver.close()
将上面的Python语言脚本以名称为python_org_search的Python文件存储起来,然后在命令行运行(注:在我这里,因为Python是安装在anconda环境下的,所以用的是anconda的命令行界面)。
(二)解释上面的例子
selenium.webdriver模块提供所有网页驱动程序操作,目前支持的网页驱动程序是火狐浏览器,谷歌浏览器,IE浏览器,微软的远程驱动程序。
Keys类提供一些和键盘相同的功能,如RETURN,F1,ALT等等。
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
接下来我们创造一个谷歌浏览器的实例
driver = webdriver.Chrome()
driver.get方法以URL作为参数,将导航到这个URL所定位的网页。WebDriver将等待网页所有的元素加载完毕才执行后面的操作(这是因为WebDriver内置一个“onload”功能),这些操作比如去定位一个元素。但值得注意的是,如果你想登陆的网页使用异步加载的方式,WebDriver并不知道何时将此网页的所有元素完全加载出来了。
driver.get("http://www.python.org")
j接下来的操作是:用一个断言来确认返回网页的名称中有Python这个单词。
assert "Python" in driver.title
WebDriver提供多种方法去在网页中找到元素,这些方法统一的表达式为:find_element_by_*。比如,你想找到网页中表输入文本的元素,你可以找到这个这个元素的name值,使用find_element_by_name方法。如果你想了解关于寻找元素的更多细节,你可以参考下面这个链接,或者你也可以关注我,后面我会以网络爬虫实战为载体,介绍更多寻找元素的方法。
elem = driver.find_element_by_name("q")
接下来,我们将向这个表输入文本的元素发送文本,这类似与我们使用键盘输入文本,然后摁确认键。但对于Python的selenium接口来说,可以使用从selenium.webdriver.common.keys导入的Keys类发送特殊文本。不过,为了不影响我们的输入结果,我们得先把这个元素的文本清空。
elem.clear()
elem.send_keys("pycon")
elem.send_keys(Keys.RETURN)
提交了搜索文本之后,如果有的话,我们是可以得到搜索结果的。但为了确保得到我们想要的搜索结果,我们可以使用下列断言:
assert "No results found." not in driver.page_source
最后,关闭浏览器的网页。你可以调用quit方法而不是close方法。quit方法将把所有的页面关闭,而close只关闭当前浏览页面。但如果浏览器只有一个网页被打开,那么两者就没有区别了。
driver.close()
(三)用Selenium去写测试脚本
Selenium主要用于编写测试用例。 Selenium包本身不提供测试工具/框架。 你可以使用Python的unittest模块编写测试用例。 工具/框架的其他选项是py.test等。
在本章,我们将使用unittest作为选择的框架。这是使用unittest模块修改后的示例。这是对http://python.org搜索功能的测试。
import unittest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
class PythonOrgSearch(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Chrome()
def test_search_in_python_org(self):
driver = self.driver
driver.get("http://www.python.org")
self.assertIn("Python", driver.title)
elem = driver.find_element_by_name("q")
elem.send_keys("pycon")
elem.send_keys(Keys.RETURN)
assert "No results found." not in driver.page_source
def tearDown(self):
self.driver.close()
if __name__ == "__main__":
unittest.main()
你可以再次使用命令行界面去运行这个测试程序,将返回以下结果:
python test_python_org_search.py
.
----------------------------------------------------------------------
Ran 1 test in 15.566s
OK
这个结果表示这个测试程序被成功执行了。
(四)解释上面的示例
最初,所有必需的基本模块都已导入。 unittest模块是基于Java的JUnit的内置Python。 该模块提供了组织测试用例的框架。 selenium.webdriver模块提供所有WebDriver实现。 当前支持的WebDriver实现是Firefox,Chrome,IE和Remote。 Keys类提供键盘中的键,如RETURN,F1,ALT等。
import unittest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
测试用例类继承自unittest.TestCae类。继承自TestCase类旨在告诉uniitest模块这是一个测试用例。
class PythonOrgSearch(unittest.TestCase):
setUp方法是初始化的一部分,此方法将要在此测试用例类中编写的每个测试函数之前调用。 在这里,你将创建Chrome WebDriver的实例。
def setUp(self):
self.driver = webdriver.Firefox()
接下来是测试用例方法。测试用例方法应始终以字符测试开始。 此方法内的第一行创建对在setUp方法中创建的驱动程序对象进行本地引用。
def test_search_in_python_org(self):
driver = self.driver
driver.get方法将导航到URL给定的页面。 WebDriver将等待页面完全加载(即,已触发“ onload”事件),然后再将控制权返回给测试或脚本。 值得注意的是,如果您的页面在加载时使用了大量的异步加载方式,则WebDriver可能不知道何时完全加载。
driver.get("http://www.python.org")
下一行是一个断言操作,以确认网页标题中包含“ Python”一词:
self.assertIn("Python", driver.title)
WebDriver提供多种方法去在网页中找到元素,这些方法统一的表达式为:find_element_by_*。比如,你想找到网页中表输入文本的元素,你可以找到这个这个元素的name值,使用find_element_by_name方法。如果你想了解关于寻找元素的更多细节,你可以参考下面这个链接,或者你也可以关注我,后面我会以网络爬虫实战为载体,介绍更多寻找元素的方法。
elem = driver.find_element_by_name("q")
接下来,我们将向这个表输入文本的元素发送文本,这类似与我们使用键盘输入文本,然后摁确认键。对于Python的selenium接口来说,可以使用从selenium.webdriver.common.keys导入的Keys类发送特殊文本。
elem.send_keys("pycon")
elem.send_keys(Keys.RETURN)
提交了搜索文本之后,如果有的话,我们是可以得到搜索结果的。但为了确保得到我们想要的搜索结果,我们可以使用下列断言:
assert "No results found." not in driver.page_source
在用尽每个测试方法后,我们将调用tearDown方法,以用来关闭在浏览器打开的页面。你可以调用quit方法而不是close方法。quit方法将把所有的页面关闭,而close只关闭当前浏览页面。但如果浏览器只有一个网页被打开,那么两者就没有区别了。
def tearDown(self):
self.driver.close()
这个脚本中的最后两行是程序的入口。
if __name__ == "__main__":
unittest.main()
(五)使用remote浏览器程序
要使用远程WebDriver,你应该先运行Selenium服务器。 而要运行服务器,请使用以下命令:
java -jar selenium-server-standalone-2.x.x.jar
当运行Selenium服务器时,此服务器将返回下列信息。
15:43:07.541 INFO - RemoteWebDriver instances should connect to: http://127.0.0.1:4444/wd/hub
上一行显示:可以使用此URL连接到远程WebDriver。 这里有些例子:
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
driver = webdriver.Remote(
command_executor='http://127.0.0.1:4444/wd/hub',
desired_capabilities=DesiredCapabilities.CHROME)
driver = webdriver.Remote(
command_executor='http://127.0.0.1:4444/wd/hub',
desired_capabilities=DesiredCapabilities.OPERA)
driver = webdriver.Remote(
command_executor='http://127.0.0.1:4444/wd/hub',
desired_capabilities=DesiredCapabilities.HTMLUNITWITHJS)
desired_capabilities的数据结果是字典:
driver = webdriver.Remote(
command_executor='http://127.0.0.1:4444/wd/hub',
desired_capabilities={'browserName': 'htmlunit',
'version': '2',
'javascriptEnabled': True})
转载请注明出处!!!
码字不易,你的点赞将是我继续翻译Python库的动力!!!