崔庆才老师爬虫的学习笔记。

一、Selenium库详解

1、什么是Selenium

Selenium是一个自动化测试工具,利用它可以驱动浏览器执行特定的动作,如点击、下拉等操作,同时还可以获取浏览器当前呈现的页面的源代码,做到可见即可爬。对于一些JavaScript动态渲染的页面来说,此种抓取方式非常有效。

2、安装

pip install selenium

3、基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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('https://www.baidu.com')
input = browser.find_element_by_id('kw')
input.send_keys('python')
input.send_keys(Keys.ENTER)
wait = WebDriverWait(browser,10)
wait.until(EC.presence_of_element_located((By.ID,'content_left')))
print(browser.current_url)
print(browser.get_cookies())
print(browser.page_source)
finally:
browser.close()

4、声明浏览器对象

Selenium支持非常多的浏览器,如Chrome、Firefox、Edge等,还有Android、BlackBerry等手机端的浏览器。另外,也支持无界面浏览器PhantomJS。

1
2
3
4
5
6
7
from selenium import webdriver

browser = webdriver.Chrome()
browser = webdriver.Firefox()
browser = webdriver.Edge()
browser = webdriver.PhantomJS()
browser = webdriver.Safari()

5、访问页面

1
2
3
4
5
6
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
print(browser.page_source)
browser.close()

6、查找节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#单个节点
from selenium import webdriver
from selenium.webdriver.common.by import By

browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
input1 = browser.find_element_by_id('q')
input2 = browser.find_element_by_css_selector('#q')
input3 = browser.find_element_by_xpath('//*[@id="q"]')
print(input1,input2,input3)

#Selenium还提供了查找元素通用方法find_element(),它需要传入两个参数:查找方式By和值。
#这种查找方式的功能和上面列举的查找函数完全一致,不过参数更加灵活。
input1_same = browser.find_element(By.ID,'q') #等价于find_element_by_id('q')
print(input1_same)

browser.close()

所有获取单个节点的方法:

  • 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
1
2
3
4
5
6
7
8
9
10
11
12
13
#多个节点
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
lis = browser.find_elements_by_css_selector('.service-bd li')
print(lis)

#也可以直接用find_elements()方法来选择
lis_same = browser.find_elements(By.CSS_SELECTOR,'.service-bd li') #等价于find_elements_by_css_selector('.service-bd li')
print(lis_same)

browser.close()

所有获取多个节点的方法:

  • find_elements_by_id
  • 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

7、元素交互

官方文档:http://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.remote.webelement

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from selenium import webdriver
import time

browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
input = browser.find_element_by_id('q')
input.send_keys('iphone')
time.sleep(1)
input.clear()
input.send_keys('ipad')
button = browser.find_element_by_class_name('btn-search')
button.click()
time.sleep(3)
browser.close()

8、交互动作(动作链)

还有一些操作,它们没有特定的执行对象,比如鼠标拖曳、键盘按键等,这些动作用另一种方式来执行,那就是动作链。

将动作附加到动作链中串行执行。

官方文档:http://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.common.action_chains

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from selenium import webdriver
from selenium.webdriver import ActionChains
import time

browser = webdriver.Chrome()
browser.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
time.sleep(5)
browser.switch_to.frame('iframeResult')
source = browser.find_element_by_css_selector('#draggable')
target = browser.find_element_by_css_selector('#droppable')
actions = ActionChains(browser) #声明动作链对象
actions.drag_and_drop(source,target) #定义拖放动作
actions.perform() #执行动作链
time.sleep(3)
browser.close()

9、执行JavaScript

对于某些操作,Selenium API并没有提供。比如,下拉进度条,它可以直接模拟运行JavaScript,此时使用execute_script()方法即可实现。

1
2
3
4
5
6
7
8
9
from selenium import webdriver
import time

browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
browser.execute_script('window.scrollTo(0,document.body.scrollHeight)')
browser.execute_script('alert("To Bottom")')
time.sleep(3)
browser.close()

10、获取元素信息

Selenium已经提供了选择节点的方法,返回的是WebElement类型,那么它也有相关的方法和属性来直接提取节点信息,如属性、文本等。这样的话,我们就可以不用通过解析源代码来提取信息了,非常方便。

1
2
3
4
5
6
7
8
9
10
11
12
#获取属性
from selenium import webdriver
import time

browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
logo = browser.find_element_by_id('zh-top-link-logo')
print(logo)
print(logo.get_attribute('class')) #获取class属性

time.sleep(3)
browser.close()
1
2
3
4
5
6
7
8
9
10
11
12
#获取文本值
from selenium import webdriver
import time

browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
input = browser.find_element_by_class_name('zu-top-add-question')
print(input)
print(input.text) #获取文本值

time.sleep(3)
browser.close()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#获取id、位置、标签名和大小
from selenium import webdriver
import time

browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
input = browser.find_element_by_class_name('zu-top-add-question')
print(input)
print(input.id) #获取节点id
print(input.location) #获取该节点在页面中的相对位置
print(input.tag_name) #获取标签名称
print(input.size) #获取节点的大小,也就是宽高

time.sleep(3)
browser.close()

11、切换Frame

网页中有一种节点叫作iframe,也就是子Frame,相当于页面的子页面,它的结构和外部网页的结构完全一致。Selenium打开页面后,它默认是在父级Frame里面操作,而此时如果页面中还有子Frame,它是不能获取到子Frame里面的节点的。这时就需要使用switch_to.frame()方法来切换Frame。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
import time

browser = webdriver.Chrome()
browser.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
browser.switch_to.frame('iframeResult') #切换到子frame
try:
logo = browser.find_element_by_class_name('logo')
except NoSuchElementException:
print('NO LOGO')
browser.switch_to.parent_frame() #切换回父frame
logo = browser.find_element_by_class_name('logo')
print(logo)
print(logo.text)

time.sleep(3)
browser.close()

12、延时等待

这里等待的方式有两种:一种是隐式等待,一种是显式等待。

隐式等待,如果Selenium没有在DOM中找到节点,将继续等待,超出设定时间后,则抛出找不到节点的异常。隐式等待的效果其实并没有那么好,因为我们只规定了一个固定时间,而页面的加载时间会受到网络条件的影响。

显式等待,它指定要查找的节点,然后指定一个最长等待时间。如果在规定时间内加载出来了这个节点,就返回查找的节点;如果到了规定时间依然没有加载出该节点,则抛出超时异常。

1
2
3
4
5
6
7
8
9
10
#隐式等待
from selenium import webdriver

browser = webdriver.Chrome()
browser.implicitly_wait(10) #隐式等待10秒
browser.get('https://www.zhihu.com/explore')
input = browser.find_element_by_class_name('zu-top-add-question')
print(input)

browser.close()
1
2
3
4
5
6
7
8
9
10
11
12
13
#显示等待
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

browser = webdriver.Chrome()
browser.get('https://www.taobao.com/')
wait = WebDriverWait(browser,10) #声明WebDriverWait对象,指定最长等待时间
input = wait.until(EC.presence_of_element_located((By.ID,'q'))) #调用它的until()方法,传入要等待条件
button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'.btn-search')))
print(input,button)
browser.close()

等待条件及其含义:

  • title_is:标题是某内容
  • title_contains:标题包含某内容
  • presence_of_element_located:节点加载出来,传入定位元组,如(By.ID, ‘p’)
  • 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:判断一个节点是否仍在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:是否出现警告

等待条件的参数及用法参考官方文档:http://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.support.expected_conditions

13、前进后退

1
2
3
4
5
6
7
8
9
10
11
12
13
from selenium import webdriver
import time

browser = webdriver.Chrome()
browser.get('https://www.baidu.com/')
browser.get('https://www.taobao.com/')
browser.get('https://www.python.org/')

browser.back() #后退
time.sleep(2)
browser.forward() #前进
time.sleep(2)
browser.close()

14、Cookies

Selenium可以方便地对Cookies进行操作,例如获取、添加、删除Cookies等

1
2
3
4
5
6
7
8
9
10
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
print(browser.get_cookies()) #获取cookies
browser.add_cookie({'name': 'name', 'domain': 'www.zhihu.com', 'value': 'germey'}) #添加cookie
print(browser.get_cookies())
browser.delete_all_cookies() #删除全部cookies
print(browser.get_cookies())
browser.close()

15、选项卡管理

在访问网页的时候,会开启一个个选项卡。Selenium也可以对选项卡进行操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from selenium import webdriver
import time

browser = webdriver.Chrome()
browser.get('https://www.baidu.com')
browser.execute_script('window.open()') #借助javascript开启新的选项卡
print(browser.window_handles) #window_handles获取当前所有选项卡句柄
browser.switch_to_window(browser.window_handles[1]) #切换到第二个选项卡
browser.get('https://www.taobao.com')
time.sleep(2)
browser.switch_to_window(browser.window_handles[0]) #切换回第一个选项卡
browser.get('https://python.org')
time.sleep(2)
browser.close()

16、异常处理

官方文档:http://selenium-python.readthedocs.io/api.html#module-selenium.common.exceptions

1
2
3
4
5
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.baidu.com')
browser.find_element_by_id('hello') #选择一个并不存在的节点,此时就会遇到异常。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
from selenium import webdriver
from selenium.common.exceptions import TimeoutException,NoSuchElementException

browser = webdriver.Chrome()
try:
browser.get('https://www.baidu.com')
except TimeoutException:
print('Time Out')
try:
browser.find_element_by_id('hello')
except NoSuchElementException:
print('No Element')
finally:
browser.close()

持续更新…

最后更新: 2018年08月14日 17:52

原始链接: http://pythonfood.github.io/2018/07/02/爬虫-selenium库/

× 多少都行~
打赏二维码