视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
Selenium+PhantomJs解析渲染Js的基本操作
2020-11-27 14:09:24 责编:小采
文档
有人说Selenium库和PhantomJ,说他们结合使用是万能的利器。那么,他们真的那么厉害吗,我们一起来看看Selenium库的用法吧。通过这篇文章让我们来看一下Selenium库结合PhantomJs,Chrome等一些浏览器的操作吧。

什么是Selenium

Selenium是一个自动化测试工具,支持包括Chrome,Firefox,Safari,PhantomJs等一些浏览器。如果用于爬虫中,我们主要用来解决一些JavaScript渲染的问题。

我们在使用Requests库去请求一些网页的时候,比如 163music,我们获得的响应数据呢,并不全是我们在浏览器中看到的信息。他可能是通过js渲染出来的。那么,我们如果使用Selenium库,就不会再去关心如何去解决这种问题了。

因为我们的浏览器,比如PhantomJs,他就是一个无界面的浏览器,他用来渲染解析js,而Selenium库就负责给浏览器发送一些命令,模拟一些比如下拉,拖拽,翻页,输入表单等动作。这样他们两个结合,对于那些 JS 的渲染问题是不是完美解决了。

注意

虽然Selenium库加上PhantomJs很好用,但是他毕竟是驱动一个浏览器,然后获取数据。所以在我们使用中,会发现他并没有我们使用一些解析库速度快。这其实就是他的弊端,所以我还是建议大家,不到实在找不到解决办法的时候,不去使用他们。

安装准备

pip直接安装Selenium库:

pip install selenium

浏览器驱动的安装:

Chrome浏览器驱动

PhantomJs浏览器驱动

我们需要把安装好的浏览器驱动配置到我们的环境变量。对于Windows用户,配置环境变量比较麻烦。我们需要找到下载好的驱动位置,然后复制他的文件位置,见他粘贴到环境变量即可。

配置完成,命令行输入:

phantomjs -v

查看是否成功。

使用样例

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
 
 
browser = webdriver.Chrome()
 
try:
 browser.get('http://www.yukunweb.com')
 input = browser.find_element_by_id('s')
 input.send_keys('Python')
 input.send_keys(Keys.ENTER)
 wait = WebDriverWait(browser, 10)
 wait.until(EC.presence_of_element_located((By.ID, 'main')))
 print(browser.current_url)
 print(browser.page_source)
finally:
 browser.close()

如果我们运行上面的代码,会看到本地打开了一个Chrome浏览器,然后在浏览器地址栏输入了我的博客网址,然后他会自动的在搜索栏输入‘Python’,并且点击了回车搜索。并且将结果页的url和源代码打印出来。

我们的例子都是使用Chrome浏览器来操作,因为PhantomJs是无界面的,不方便查看到效果。如果大家运行错误的话,一般情况是浏览器并没有打开,那么应该是大家没有安装好Chrome浏览器,或者没有将驱动配置环境变量。

那么这几行代码究竟是什么意思呢,我们究竟赋予了什么指令呢?

声明浏览器对象

from selenium import webdriver
 
browser = webdriver.Chrome()
# 声明其他浏览器
browser = webdriver.PhantomJs()
browser = webdriver.Firefox()

这就相当于我们调用了Selenium库的webdriver方法,实例化一个Chrome浏览器给我们调用。

访问页面

from selenium import webdriver
 
browser = webdriver.Chrome()
browser.get('http://www.yukunweb.com')

我们将要访问的url传给get方法。调用浏览器访问url。

查找元素

input = browser.find_element_by_id('s')

这句代码调用find_element_by_id方法,顾名思义,就是查找id为‘s’的标签,那么如果是操作class为‘s’的话,就是find_element_by_class('s')。

当然,我们还可以使用 CSS选择器和xpath选择器查找元素:

input = browser.find_element_by_css_selector("#s")
print(input)
input = browser.find_element_by_xpath('//*[@id="s"]')
print(input)

通过打印结果,可以看到不管使用什么选择器,查找结果都是一样的。下面是一些查找api:

find_element_by_namefind_element_by_xpathfind_element_by_link_textfind_element_by_partial_link_textfind_element_by_tag_namefind_element_by_class_namefind_element_by_css_selector

查找多个元素

如果我们查找的元素是网页中的li标签,是很多的元素。那么我们的查找方式和单个元素是相同的,只是对于查找的api我们需要在element后面加个复数形式 s。即是:

find_elements_by_namefind_elements_by_xpathfind_elements_by_link_textfind_elements_by_partial_link_textfind_elements_by_tag_namefind_elements_by_class_namefind_elements_by_css_selector

元素交互操作

即是对于我们获取的元素下达指令,调用交互的方法。

browser.get('http://www.yukunweb.com')
input = browser.find_element_by_id('s')
input.send_keys('Python')
input.send_keys(Keys.ENTER)


这段代码中,我们首先查找到了id为‘s’的元素,然后传给他‘Python’值,然后调用交互方法,敲了回车。

当然,在大多是情况下,我们不能直接使用敲击回车的方法,因为我们不确定是不是敲了回车,表单就提交了。我们需要使用查找器查找到提交按钮元素,然后模拟点击:

button = browser.find_element_by_class_name('xxxx')
button.click()
# 清除表单信息
button.clear()

那么,我们可以看到在模拟登陆时候,直接让我们手动的输入账号,密码,如果有验证码的话直接给一个input方法,我们手动输入验证码传给表单,是不是很简单的就模拟登录了了。

交互动作

元素交互动作与上面的操作是不同的。上面的操作需要获得一个特定的元素。然后对这个特定的元素调用一些指令,才可以完成交互。而这个交互是将这些动作附加到动作链中串行执行。

我们以拖拽元素为例(我们需要导入ACtionChains方法):

from selenium import webdriver
from selenium.webdriver import ActionChains
 
browser = webdriver.Chrome()
 
browser.get(url)
source = browser.find_element_by_name("source")
target = browser.find_element_by_name("target")
actions = ActionChains(browser)
actions.drag_and_drop(source, target).perform()

这里的sourcs是我们要拖拽的元素,我们使用查找器找到他,target就是我们要拖拽到的位置元素。然后调用ActionChains方法,实现拖拽操作。

执行JavaScript

有些动作呢,Selenium库并没有为我们提供特定的api,比如说将浏览器进度条下拉,这个实现起来是很难的。那么我们就可以通过让Selenium执行JS来实现进度条的下拉,这个得需要一些js的知识,不过还是很简单的。

from selenium import webdriver
 
browser = webdriver.Chrome()
browser.get('http://www.yukunweb.com')
browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')
browser.execute_script('alert("到达底部")')

这就相当于我们将一些JS命令传给Selenium的execute_script这个api,我们运行就可以看到浏览器下拉到底部,然后弹出会话框。

获取元素文本值

如果我们查找得到一个元素,我们要怎样获得元素的一些属性和文本信息呢?

from selenium import webdriver
 
browser = webdriver.Chrome()
 
browser.get('http://www.yukunweb.com')
name = browser.find_element_by_css_selector('#kratos-logo > a')
print(name.text)
print(name.get_attribute('href'))

运行结果可以看到,他打印出了‘意外’和他的url。

Frame框架

有些网页在我们直接使用Selenium驱动浏览器打印源码的时候,并没有如期获得想要的数据,那在我们查看网页源码的时候,可以看到网页的iframe标签包裹的一个一个的框架。那么这就需要我们请求对应框架,拿到源码了。

我们以网易云音乐的歌手栏为例。

from selenium import webdriver
 
browser = webdriver.Chrome()
browser.get('https://music.163.com/#/discover/artist/signed/')
 
print(browser.page_source)

可以查看结果,并没有我们想要的信息。

from selenium import webdriver
 
browser = webdriver.Chrome()
browser.get('https://music.163.com/#/discover/artist/signed/')
browser.switch_to.frame('contentFrame')
 
print(browser.page_source)

这次打印,我们就可以看到我们需要的信息了,是不是很简单。

显示等待

在文章开始的时候,我们运行的那段代码中有一段代码是不是还没有说。那就是我们命令浏览器等待的操作。

等待有两种方式,一种是隐士等待,一种是显示等待。当使用了隐士等待执行时,如果浏览器没有找到指定元素,将继续等待,如果超出设定时间就会抛出找不到元素的异常。而大多数情况我们建议使用显示等待。

显示等待是你指定一个等待的条件,还指定一个最长等待时间。那么程序会在最长等待时间内,判断条件是否成立,如果成立,立即返回。如果不成立,他会一直等待,直到最长等待时间结束,如果条件仍然不满足,就返回异常。

wait = WebDriverWait(browser, 10)
wait.until(EC.presence_of_element_located((By.ID, 'main')))

这里的By.ID方法实际上就是一个查找的万能方法,而我们直接查找或者使用CSS、xpath查找足够满足,我也不过多介绍,想要了解可以查看官方文档。

这里是知道查找到id为‘main’就返回。

显示等待的一些条件还有:

title_is 标题是某内容

title_contains 标题包含某内容

presence_of_element_located 元素加载出,传入定位元组,如(By.ID, ‘p’)

visibility_of_element_located 元素可见,传入定位元组

visibility_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 frame加载并切换

invisibility_of_element_located 元素不可见

element_to_be_clickable 元素可点击

staleness_of 判断一个元素是否仍在DOM,可判断页面是否已经刷新

element_to_be_selected 元素可选择,传元素对象

element_located_to_be_selected 元素可选择,传入定位元组

element_selection_state_to_be 传入元素对象以及状态,相等返回True,否则返回False

element_located_selection_state_to_be 传入定位元组以及状态,相等返回True,否则返回False

alert_is_present 是否出现Alert

窗口选择

如果我们在表单输入关键词,提交表单后浏览器新打开了一个窗口,那么我们要怎么去操作新的窗口呢?索性Selenium为我们提供了对应的api.

import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
 
browser = webdriver.Chrome()
browser.get('http://www.23us.cc/')
input = browser.find_element_by_id('bdcs-search-form-input')
input.send_keys('斗破苍穹')
input.send_keys(Keys.ENTER)
browser.switch_to_window(browser.window_handles[1])
print(browser.current_url)
time.sleep(1)
browser.switch_to_window(browser.window_handles[0])
print(browser.current_url)

通过打印结果,不难看出先打印了搜索结果窗口url,然后打印了索引页url。要注意窗口的索引是从 0 开始的哦,这个大家都明白。

异常处理

异常处理和普通的异常处理一样,没有什么要说的,大家自己查看官方异常 api.地址

最后

好了,通过本篇文章希望大家可以基本上了解Selenium库结合浏览器驱动的一些使用方法。我们例子里使用的是Chrome,但是大家在实际的代码里最好是使用PhantomJs,因为他是无界面的,运行起来相对好一点。

文章开始说过一般情况下不建议大家使用Selenium,因为他很慢。但是即使是慢,也很爽啊,是不是。

下载本文
显示全文
专题