欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

(廿七)Python爬虫:Selenium使用

程序员文章站 2022-07-14 08:54:04
...

      Selenium是一个自动化测试工具,使用它可以驱动浏览器完成特定的动作(点击,滚动等),同时它可以获取网页源代码,做到可见及可爬。对于一些由AJAX加载的加密数据它也能很好的完成。


相关安装

  • Selenium的安装
          推荐使用pip3 install selenium 安装。

  • ChromeDriver的安装
          Selenium是一个自动化测试工具,它需要浏览器配合使用,首先我们需要安装Chrome浏览器,这个简单,不再赘述。
          同时,我们需要配置ChromeDriver。只有配置了驱动Selenium才能驱动Chrome浏览器进行操作。驱动下载地址:http://chromedriver.chromium.org/。一定要下载和Chrome浏览器版本对应的驱动。
          下载完对应的驱动后我们需要进行环境变量的配置:

    • Windows下建议直接将chromedriver.exe放在Python安装目录下的Script目录中。
    • Linux和Mac下将chromedrive配置到$PATH中。假设目录为:/usr/bin/chromedriver。修改~/.profile文件,添加export PATH = "$PATH:/usr/bin/chromedriver" 。保存后执行source ~/.profile 使设置生效。

验证安装:
(廿七)Python爬虫:Selenium使用

  • GeckoDriver的安装
          Selenium同样也可以和Firefox进行对接,这需要我们安装GeckoDriver。下载地址:https://github.com/mozilla/geckodriver/releases。请根据自身电脑下载对应版本。下载后需要进行环境变量的配置,方法和前面ChromeDriver的大同小异,这里不赘述。
    验证安装:
    (廿七)Python爬虫:Selenium使用

访问百度

      首先我们需要创建浏览器对象,Selenium支持非常多的浏览器,以Chrome为例声明浏览器对象:

from selenium import webdriver

brower = webdriver.Chrome()
#selenium还支持以下浏览器
# webdriver.Firefox()
# webdriver.PhantomJS()
# webdriver.Safari()
# webdriver.Edge()

使用webdriver完成了浏览器对象的创建,后续的一切操作都是基于此对象进行了。
创建好浏览器对象后可以调用get() 方法来请求网页,现在访问百度。

from selenium import webdriver

brower = webdriver.Chrome()
brower.get('https://www.baidu.com')#访问百度
print(brower.page_source)#打印网页源码
brower.close()

运行代码我们可以看见自动打开浏览器访问百度,再自动关闭。控制台输出了网页源码。

节点查找

      我们使用Selenium可以进行表单填充,点击操作,这些操作的前提是我们需要获取相应的节点(输入框,点击按钮等)。

单节点选择

      现在我需要打开百度首页并获取两个节点:输入框和搜索按钮

from selenium import webdriver

brower = webdriver.Chrome()
brower.get('http://www.baidu.com')#访问百度
input_kw = brower.find_element_by_id("kw")#根据id查找输入框
# input_kw2 = brower.find_element_by_css_selector("#kw")使用css选择器查找输入框
search_btn = brower.find_element_by_xpath('//*[@id="su"]')#使用xpath查找搜索按钮
print(input_kw,search_btn)
brower.close()

(廿七)Python爬虫:Selenium使用
可以发现查找到的节点类型为WebElement 类型。
获取单个节点的方法还有以下几个:

find_element_by_name():根据name属性值查找;
find_element_by_link_text():根据a标签的文本内容查找,返回第一个匹配的节点;
find_element_by_partial_link_text():根据a标签的局部文本内容查找,返回第一个匹配的节点;
find_element_by_tag_name():根据标签名查找,返回第一个匹配的节点;
find_element_by_class_name():根据class属性值查找;

除了以上几种特点的方法用于查找节点,Selenium提供了一个通用方法find_element(by=By.ID, value=None) 查找方式by和值,默认根据ID查找。

from selenium import webdriver
from selenium.webdriver.common.by import By

brower = webdriver.Chrome()
brower.get('http://www.baidu.com')#访问百度
input_kw = brower.find_element(By.ID,"kw")#根据id查找输入框
# input_kw2 = brower.find_element(By.CSS_SELECTOR,"#kw")使用css选择器查找输入框
search_btn = brower.find_element(By.XPATH,'//*[@id="su"]')#使用xpath查找搜索按钮
print(input_kw,search_btn)
brower.close()

多节点选择

以上所有方法只能查找单个节点,如果需要查找多个节点使用find_elements(by=By.ID, value=None)
(廿七)Python爬虫:Selenium使用
查找淘宝网首页左侧导航条的所有信息:

from selenium import webdriver
from selenium.webdriver.common.by import By

brower = webdriver.Chrome()
brower.get('https://www.taobao.com/')
lis = brower.find_elements(By.CSS_SELECTOR,'.service-bd > li')
print(lis)
brower.close()

(廿七)Python爬虫:Selenium使用

节点交互

获取到指定节点后我们进行模拟操作,一般为输入文本内容和点击按钮。现在我们打开百度首页搜索“python”相关内容。

这里写代码片

执行代码后浏览器自动打开访问百度并搜索Python。
其他交互操作(例如滚动)查看官方文档:https://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.remote.webelement

动作链

ActionChains是一种自动执行低级别交互的方法,例如鼠标移动,鼠标按钮操作,按键和上下文菜单交互。 这对于执行更复杂的操作非常有用,例如悬停和拖放。
示例实现一个节点的拖曳动作:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
import time

brower = webdriver.Chrome()
brower.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
brower.switch_to.frame('iframeResult')
source = brower.find_element(By.ID,'draggable')
target = brower.find_element(By.ID,'droppable')
actions = ActionChains(brower)#创建ActionChains对象
actions.drag_and_drop(source,target)#按住源元素上的鼠标左键,然后移动到目标元素并释放鼠标按钮。模拟拖曳操作
actions.perform()#执行调用的操作,如果有多个按照调用顺序执行。
time.sleep(5)
brower.close()

(廿七)Python爬虫:Selenium使用

执行JS

Selenium可以使用execute_script() 方法执行JS代码。Selenium并没有提供下拉进度条的操作,这时候就需要我们执行JS代码来完成下拉操作了。

from selenium import webdriver
import time

brower = webdriver.Chrome()
brower.get('https://www.baidu.com/s?wd=Python')
time.sleep(2)
brower.execute_script('window.scrollTo(0,document.body.scrollHeight)')#下拉到最底部
time.sleep(2)
brower.execute_script('alert("To Bottom")')
time.sleep(2)
brower.close()

获取节点相关信息

      虽然我们通过调用page_source获取网页源码再通过解析库获取节点信息,但是Selenium提供了获取节点的方法,并且返回WebElement对象,此对象有对应的方法和属性获取节点信息。

获取属性

使用get_attribute() 方法来获取节点属性。

from selenium import webdriver
from selenium.webdriver.common.by import By

brower = webdriver.Chrome()
brower.get('https://www.baidu.com')
input_kw = brower.find_element(By.ID,'kw')
print(input_kw.get_attribute('class'))
print(input_kw.get_attribute('name'))
brower.close()

(廿七)Python爬虫:Selenium使用

获取文本内容

每个WebElement节点都有text属性,调用此属性可以得到节点的文本内容。

from selenium import webdriver
from selenium.webdriver.common.by import By

brower = webdriver.Chrome()
brower.get('https://www.baidu.com')
node = brower.find_element(By.CSS_SELECTOR,'#u1 > a:nth-child(1)')
print(node.text)
brower.close()

(廿七)Python爬虫:Selenium使用

延时等待

      在爬取过程中由于网络等因素导致网页还没加载出来,如果这时候我们获取节点当然是无法实现的,所以我们需要等待一段时间确保节点已经加载出来。等待方式有两种:隐式等待和显示等待

隐式等待

      调用implicitly_wait() 使用隐式等待。使用隐式等待时,如果Selenium无法再DOM树中找到节点则等待,超出等待时间后抛出异常信息。

from selenium import webdriver
from selenium.webdriver.common.by import By

brower = webdriver.Chrome()
brower.implicitly_wait(10)#等待10秒,默认0
brower.get('https://www.baidu.com')
input_kw = brower.find_element(By.ID,'kw')
input_kw.send_keys('阿里巴巴')
brower.close()

显式等待

      隐式等待需要等待页面加载完成,但是我们其实只需要某几个节点而已,这未免太浪费时间了,并且由于网络的影响我们很难把控应该等待多长时间是合理的。
      显示等待可以指定等待目标节点的最长时间,如果在规定时间内加载出来了这个节点就返回,否则抛异常。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC#等待条件
from selenium.webdriver.support.ui import WebDriverWait

brower = webdriver.Chrome()
brower.get('https://www.baidu.com')
wait = WebDriverWait(brower,10)#设置最长等待时间
input_kw = wait.until(EC.presence_of_element_located((By.ID,'kw')))#传入元组,等待id为kw的节点加载出来
print(input_kw)
brower.close()

如果是等待一个按钮我们不应该简简单单的等待节点出现,而应该等待至节点可点击才行,对应的条件为element_to_be_clickable

btn = wait.until(EC.element_to_be_clickable((By.ID,'su')))

      关于等待条件根据官网我们总结出以下几个常用的条件:

等待条件 描述
title_is 标题是某内容
title_contains 标题包含某内容
presence_of_element_located 节点加载出来,传入定位元组
visibility_of_element_located 节点可见,传入定位元组
presence_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 节点可选择,传入定位元组

前进和后退

使用forward()back()可以实现页面前进和后退功能。

from selenium import webdriver
import time

brower = webdriver.Chrome()
brower.get('https://www.taobao.com')
brower.get('https://blog.csdn.net/qq_25343557')
time.sleep(2)
brower.back()
time.sleep(2)
brower.forward()
time.sleep(2)
brower.close()

Cookie操作

使用get_cookies() 获取cookie,delete_all_cookies() 删除所有cookie,add_cookie() 添加cookie。

from selenium import webdriver

brower = webdriver.Chrome()
brower.get('https://blog.csdn.net/qq_25343557')
print(brower.get_cookies())#获取cookies
brower.delete_all_cookies()#删除cookies
print(brower.get_cookies())
brower.add_cookie({'name' : 'foo', 'value' : 'bar', 'path' : '/', 'secure':True})#添加cookie,必须包含name和value
print(brower.get_cookies())
brower.close()

(廿七)Python爬虫:Selenium使用

选项卡切换

使用switch_to.window() 切换到指定的选项卡,参数为选项卡代号。使用window_handles获取当前开启的所有选项卡。
示例:

from selenium import webdriver
import time

brower = webdriver.Chrome()
brower.get('https://www.baidu.com')
time.sleep(1)
brower.execute_script('window.open()')#执行js开启新的选项卡
handle = brower.window_handles
brower.switch_to.window(handle[1])#切换到新的选项卡
brower.get('https://www.taobao.com')
time.sleep(1)
brower.switch_to.window(handle[0])
time.sleep(1)
brower.switch_to.window(handle[1])
time.sleep(1)
brower.close()

练习

请爬取卡推漫画中任意一部漫画?尝试使用多种方法爬取哦!交流请评论