netmiko,selenium,requests,pexpect实现自动化交互

Netmiko

此模块用于简化paramiko与网络设备之间的ssh连接,可在windows与Unix平台使用

一.安装模块

#前提准备模块:
Paramiko >= 2.4.1
scp >= 0.10.0
pyyaml
pyserial
textfsm
#安装netmiko
pip install netmiko

from netmiko import ConnectHandler
'''
关于netmiko的使用,建议查看官网的说明,
 
简单的show命令的话,用以下代码即可,注意的是device_type
 
内置常用的有有以下 请留意左侧的key值,是支持的设备系列。
 
CLASS_MAPPER_BASE = {
    'a10': A10SSH,
    'accedian': AccedianSSH,
    'alcatel_aos': AlcatelAosSSH,
    'alcatel_sros': AlcatelSrosSSH,
    'apresia_aeos': ApresiaAeosSSH,
    'arista_eos': AristaSSH,
    'aruba_os': ArubaSSH,
    'avaya_ers': AvayaErsSSH,
    'avaya_vsp': AvayaVspSSH,
    'brocade_fastiron': RuckusFastironSSH,
    'brocade_netiron': BrocadeNetironSSH,
    'brocade_nos': BrocadeNosSSH,
    'brocade_vdx': BrocadeNosSSH,
    'brocade_vyos': VyOSSSH,
    'checkpoint_gaia': CheckPointGaiaSSH,
    'calix_b6': CalixB6SSH,
    'ciena_saos': CienaSaosSSH,
    'cisco_asa': CiscoAsaSSH,
    'cisco_ios': CiscoIosSSH,
    'cisco_nxos': CiscoNxosSSH,
    'cisco_s300': CiscoS300SSH,
    'cisco_tp': CiscoTpTcCeSSH,
    'cisco_wlc': CiscoWlcSSH,
    'cisco_xe': CiscoIosSSH,
    'cisco_xr': CiscoXrSSH,
    'coriant': CoriantSSH,
    'dell_force10': DellForce10SSH,
    'dell_os10': DellOS10SSH,
    'dell_powerconnect': DellPowerConnectSSH,
    'dell_isilon': DellIsilonSSH,
    'eltex': EltexSSH,
    'enterasys': EnterasysSSH,
    'extreme': ExtremeSSH,
    'extreme_wing': ExtremeWingSSH,
    'f5_ltm': F5LtmSSH,
    'fortinet': FortinetSSH,
    'generic_termserver': TerminalServerSSH,
    'hp_comware': HPComwareSSH,
    'hp_procurve': HPProcurveSSH,
    'huawei': HuaweiSSH,
    'huawei_vrpv8': HuaweiVrpv8SSH,
    'juniper': JuniperSSH,
    'juniper_junos': JuniperSSH,
    'linux': LinuxSSH,
    'mellanox': MellanoxSSH,
    'mrv_optiswitch': MrvOptiswitchSSH,
    'netapp_cdot': NetAppcDotSSH,
    'netscaler': NetscalerSSH,
    'ovs_linux': OvsLinuxSSH,
    'paloalto_panos': PaloAltoPanosSSH,
    'pluribus': PluribusSSH,
    'quanta_mesh': QuantaMeshSSH,
    'ruckus_fastiron': RuckusFastironSSH,
    'ubiquiti_edge': UbiquitiEdgeSSH,
    'ubiquiti_edgeswitch': UbiquitiEdgeSSH,
    'vyatta_vyos': VyOSSSH,
    'vyos': VyOSSSH,
}

二.执行查看命令:show ip int brief

from netmiko import ConnectHandler

cisco = {
    'device_type':'cisco_ios',
    'host':'ip地址',
    'username':'用户名',
    'password':'密码'
}
net_connect = ConnectHandler(**cisco)
##或者
# net_connect = ConnectHandler(device_type='cisco_ios',host='IP地址',username='用户名',password='密码')

#找到目前所在视图
current_view = net_connect.find_prompt()print(current_view)
#执行命令,返回结果为字符串,赋值给output
output = net_connect.send_command('show ip int brief')
print(output)

# 此为在windows里如果\n不能显示回车,则进行如下语句格式化
# o_list = output.split("\n")
# for line in o_list:
#     print(line)

----------------------------------
当然你可能不知道类型,也可以试试自动匹配,但不推荐:
from netmiko import SSHDetect, Netmiko
 
device = {'device_type': 'autodetect',
          'host': 'XXX',
          'port': 'XXX',
          'username': 'root',
          'password': 'XXX', }
guesser = SSHDetect(**device)
 
best_match = guesser.autodetect()
 
print('best_match is:{}'.format(best_match))
print('all guessers  is:{}'.format(guesser.potential_matches))
 
device['device_type'] = best_match
connection = Netmiko(**device)
# 获取回显的前缀,提示符,prompt。
print('prompt is :{}'.format(connection.find_prompt())

三.执行配置命令:手动关闭接口G1/0/22

from netmiko import ConnectHandler

cisco = {
    'device_type':'cisco_ios',
    'host':'ip地址',
    'username':'用户名',
    'password':'密码'
}
net_connect = ConnectHandler(**cisco)
#或者
# net_connect = ConnectHandler(device_type='cisco_ios',host='IP地址',username='用户名',password='密码')


#要配置的命令
config_commands = ['interface GigabitEthernet1/0/22','shutdown']
#提交要配置的命令,input为提交的真实内容
input = net_connect.send_config_set(config_commands)

#验证shutdown是否执行成功
output = net_connect.send_command('show run inter gi1/0/22')
print(output)

# 此为在windows里如果\n不能显示回车,则进行如下语句格式化
# o_list = output.split("\n")
# for line in o_list:
#     print(line)

四.常用方法

  • net_connect.send_command()        # 向下发送命令,返回输出(基于模式)
  • net_connect.send_command_timing() # 沿通道发送命令,返回输出(基于时序)
  • net_connect.send_config_set() # 将配置命令发送到远程设备
  • net_connect.send_config_from_file() # 发送从文件加载的配置命令
  • net_connect.save_config() # 将running#config保存到startup#config
  • net_connect.enable() # 输入启用模式
  • net_connect.find_prompt() # 返回当前路由器提示符
  • net_connect.commit() # 在Juniper和IOS#XR上执行提交操作
  • net_connect.disconnect() # 关闭连接
  • net_connect.write_channel() # 通道的低级写入
  • net_connect.read_channel() # 通道的低级写入

---------------------------------------------------------------------------------------------------------------------

Pexpect

此模块可以用来和像 ssh、ftp、passwd、telnet 等命令行程序进行自动交互。是 Expect 语言的一个 Python 实现,用来启动子程序,并使用正则表达式对程序输出做出特定响应。

整体来说大致的流程包括:

  1. 运行程序
  2. 程序要求人的判断和输入
  3. Expect 通过关键字匹配
  4. 根据关键字向程序发送符合的字符



基本使用流程

pexpect 的使用说来说去,就是围绕3个关键命令做操作:

  1. 首先用 spawn 来执行一个程序
  2. 然后用 expect 来等待指定的关键字,这个关键字是被执行的程序打印到标准输出上面的
  3. 最后当发现这个关键字以后,根据关键字用 send 方法来发送字符串给这个程序

第一步只需要做一次,但在程序中会不停的循环第二、三步来一步一步的完成整个工作。掌握这个概念之后 pexpect 的使用就很容易了。

spawn() - 执行程序

process = pexpect.spawn('ftp sw-tftp' , timeout=60)

注意: spawn() ,或者说 pexpect 并不会转译任何特殊字符 比如 | * 字符在Linux的shell中有特殊含义,如果在 linux 系统中想使用这些符号的正确含义就必须加上 shell 来运行,这是很容易犯的一个错误。

正确的方式:process = pexpect.spawn('/bin/bash –c "ls –l | grep LOG > log_list.txt"')

expect() - 关键字匹配

返回 0 表示匹配到了所需的关键字,如果后面的匹配关键字是一个列表的话,会返回列表中第几个关键字,从 0 开始计算。

send() - 发送关键字

用来向程序发送指定的字符串,比如:

process.expect("ftp>")
process.send("by\n")

sendline() - 发送带回车符的字符串

sendline() 和 send() 唯一的区别就是在发送的字符串后面加上了回车换行符。

sendcontrol() - 发送控制信号

sendcontrol() 向子程序发送控制字符,比如你要向子程序发送 ctrl+G,那么就这样写:process.sendcontrol('g')

--------------------------------------------------------------------------------------------------------------------

selenium

可以用来完成浏览器自动化相关的操作(行为动作),浏览器就会自动触发相关的事件

浏览器的驱动程序(谷歌浏览器)

http://chromedriver.storage.googleapis.com/index.html

基本使用流程

实例化一个浏览器对象
    - 编写基于浏览器自动化的操作代码
        - 发起请求:get(url)
        - 标签定位:find系列的方法
        - 标签交互:send_keys('xxx')
        - 执行js程序:excute_script('jsCode')
        - 前进,后退:back(),forward()
        - 关闭浏览器:quit()

    - selenium处理iframe
        - 如果定位的标签存在于iframe标签之中,则必须使用switch_to.frame(id)
        - 动作链(拖动):from selenium.webdriver import ActionChains
            - 实例化一个动作链对象:action = ActionChains(bro)
            - click_and_hold(div):长按且点击操作
            - move_by_offset(x,y)
            - perform()让动作链立即执行
            - action.release()释放动作链对象

  • 导入模块:from selenium import webdriver

  • 实例化一个浏览器对象:webdriver.Chrome(executable_path='./chromedriver.exe') ,参数为浏览器驱动路径;
  • 写上要访问的网址:bro.get("https://baidu.com/")

一.安装

pip install selenium

下载对应浏览器的驱动程序

https://npm.taobao.org/

https://chromedriver.storage.googleapis.com/index.html

二.浏览操作

执行js实现滚轮向下

    //移动到页面最底部(如果是动态加载的数据及第一次加载完成的地方):
    js = "window.scrollTo(0,document.body.scrollHeight)"

定位标签,向标签里写参数 

tag_input = bro.find_element_by_id('kw')
tag_input.send_keys('人民币')

截屏

  bro.save_screenshot('1.png')

网页的前进和后退

bro.back()      后退
bro.forward()   前进

三. 无头浏览器

#谷歌无头浏览器
from selenium import webdriver
from time import sleep
from selenium.webdriver.chrome.options import Options
# 创建一个参数对象,用来控制chrome以无界面模式打开
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')

bro = webdriver.Chrome(executable_path='./chromedriver.exe',options=chrome_options)
bro.get('https://www.baidu.com')
sleep(2)
bro.save_screenshot('1.png')
#标签定位
tag_input = bro.find_element_by_id('kw')
tag_input.send_keys('人民币')
sleep(2)

btn = bro.find_element_by_id('su')
btn.click()
sleep(2)

print(bro.page_source)
bro.quit()

四. 动作链

#动作链
from selenium import webdriver
from time import sleep
from selenium.webdriver import ChromeOptions
from selenium.webdriver import ActionChains  

option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])

bro = webdriver.Chrome(executable_path='./chromedriver.exe',options=option)
url = 'https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
bro.get(url=url)
#如果定位的标签存在于iframe标签之中,则必须经过switch_to操作在进行标签定位
bro.switch_to.frame('iframeResult')
source_tag = bro.find_element_by_id('draggable')
taget_tag = bro.find_element_by_id('droppable')
#创建一个动作连的对象
action = ActionChains(bro)
action.drag_and_drop(source_tag,taget_tag)
action.perform()
sleep(3)
# bro.quit()

附:

#selenium有以下定位方式
driver.find_element_by_id(‘id’)
driver.find_element_by_xpath('xpath')
driver.find_element_by_link_text('link_text')
driver.find_element_by_partial_link_text('partial_link_text')
driver.find_element_by_name('name')
driver.find_element_by_tag_name('tag_name')
driver.find_element_by_class_name('class_name')
driver.find_element_by_css_selector('css_selector')

实例代码:

from selenium import webdriver
#from selenium.webdriver.common.by import By
from lxml import etree
from time import sleep

#后面是你的浏览器驱动位置,记得前面加r'','r'是防止字符转义的,发起请求
bro = webdriver.Chrome(r'./chromedriver')
bro.get("http://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")

#满屏
bro.maximize_window()

#登录操作
userName_tag = bro.find_element_by_name('j_username')
password_tag = bro.find_element_by_name('j_password')
sleep(1)
userName_tag.send_keys('XXXXXXXXXXXXXXXXXXXXXXXX')
sleep(1)
password_tag.send_keys('XXXXXXXXXXXXXXXXXXXXXXXX')
sleep(1)
btn = bro.find_element_by_name('提交')
btn.click()
sleep(5)

#点击链接
bro.find_elements_by_link_text("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")[0].click()
sleep(5)

#浏览器跳转页获取当前浏览器的所有标签页
handles = bro.window_handles
#print(handles)
#定位到第二个标签页
bro.switch_to_window(handles[1])

#定位第5个iframe
iframe = bro.find_elements_by_tag_name('iframe')[4]
bro.switch_to.frame(iframe)

#表格内容输出,进一步定位到表格内容所在的td节点,存储为list
td_content = bro.find_elements_by_tag_name("td")
lst = []
for td in td_content:
	lst.append(td.text)
con = 0
conut = 0
while (con<5):
	print('源:'+lst[5+conut]+'  目的:'+lst[6+conut]+'  应用:'+lst[7+conut]+'   流量:'+lst[8+conut])
	con = con+1
	conut = conut+4

#单独取某元素的内容
Test_1 = bro.find_elements_by_xpath('/html/body/table[2]/tbody/tr[2]/td[1]')[0]
print('头号:'+Test_1.get_attribute('textContent'))

sleep(3)

#关闭实例
bro.quit()

注:

1. driver对象的常用属性和方法
在使用selenium过程中,实例化driver对象后,driver对象有一些常用的属性和方法
driver.page_source 当前标签页浏览器渲染之后的网页源代码
driver.current_url 当前标签页的url
driver.close() 关闭当前标签页,如果只有一个标签页则关闭整个浏览器
driver.quit() 关闭浏览器
driver.forward() 页面前进
driver.back() 页面后退
driver.screen_shot(img_name) 页面截图

2. driver对象定位标签元素获取标签对象的方法
在selenium中可以通过多种方式来定位标签,返回标签元素对象
find_element_by_id                                (返回一个元素)
find_element(s)_by_class_name           (根据类名获取元素列表)
find_element(s)_by_name                 (根据标签的name属性值返回包含标签对象元素的列表)
find_element(s)_by_xpath                (返回一个包含元素的列表)
find_element(s)_by_link_text            (根据连接文本获取元素列表)
find_element(s)_by_partial_link_text    (根据链接包含的文本获取元素列表)
find_element(s)_by_tag_name             (根据标签名获取元素列表)
find_element(s)_by_css_selector         (根据css选择器来获取元素列表)

---------------------------------------------------------------------------------------------------------------------------

requests

Request支持HTTP连接保持和连接池,支持使用cookie保持会话,支持文件上传,支持自动响应内容的编码,支持国际化的URL和POST数据自动编码,会自动实现持久连接keep-alive。

  • 1.requests模块的安装
pip install requests
  • 2.requests模块发送get请求

requests.get(url=url, headers=headers, params=params)

# coding:utf-8

import requests

# 请求url
url = "http://httpbin.org/get"

# 请求头
headers = {
    "Accept": "*/*",
    "Accept-Encoding": "gzip, deflate",
    "User-Agent": "python-requests/2.9.1",
}

# 查询字符串
params = {'name': 'Jack', 'age': '24'}

r = requests.get(url=url, headers=headers, params=params)

print r.status_code  # 获取响应状态码
print r.content  # 获取响应消息

if __name__ == "__main__":
    pass
  • 3.requests模块发送post请求

requests.post(url=url, headers=headers, data=params)

# coding:utf-8

import requests

# 请求url
url = "http://httpbin.org/post"

# 请求头
headers = {
    "Accept": "*/*",
    "Accept-Encoding": "gzip, deflate",
    "User-Agent": "python-requests/2.9.1",
}

# 查询字符串
params = {'name': 'Jack', 'age': '24'}

r = requests.post(url=url, headers=headers, data=params)

print r.status_code  # 获取响应状态码
print r.content  # 获取响应消息

if __name__ == "__main__":
    pass
  • 4.requests模块上传文件

requests.post(url=url, headers=headers, data=params, files=files)

# coding:utf-8

import requests

# 请求url
url = "http://httpbin.org/post"

# 请求头
headers = {
    "Accept": "*/*",
    "Accept-Encoding": "gzip, deflate",
    "User-Agent": "python/2.9.1",
}

# 查询字符串
params = {'name': 'Jack', 'age': '24'}

# 文件
files = {'upload_img': ('report.xlsx', open('report.xlsx', 'rb'), 'image/png')}
r = requests.post(url=url, data=params, headers=headers, files=files)

print r.status_code  # 获取响应状态码
print r.content  # 获取响应消息

if __name__ == "__main__":
    pass

总结:

# HTTP请求类型
# get类型
r = requests.get('https://github.com/timeline.json')
# post类型
r = requests.post("http://m.ctrip.com/post")
# put类型
r = requests.put("http://m.ctrip.com/put")
# delete类型
r = requests.delete("http://m.ctrip.com/delete")
# head类型
r = requests.head("http://m.ctrip.com/head")
# options类型
r = requests.options("http://m.ctrip.com/get")

# 获取响应内容
print(r.content) #以字节的方式去显示,中文显示为字符
print(r.text) #以文本的方式去显示

#URL传递参数
payload = {'keyword': '香港', 'salecityid': '2'}
r = requests.get("http://m.ctrip.com/webapp/tourvisa/visa_list", params=payload) 
print(r.url) #示例为http://m.ctrip.com/webapp/tourvisa/visa_list?salecityid=2&keyword=香港

#获取/修改网页编码
r = requests.get('https://github.com/timeline.json')
print (r.encoding)


#json处理
r = requests.get('https://github.com/timeline.json')
print(r.json()) # 需要先import json    

# 定制请求头
url = 'http://m.ctrip.com'
headers = {'User-Agent' : 'Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 4 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19'}
r = requests.post(url, headers=headers)
print (r.request.headers)

#复杂post请求
url = 'http://m.ctrip.com'
payload = {'some': 'data'}
r = requests.post(url, data=json.dumps(payload)) #如果传递的payload是string而不是dict,需要先调用dumps方法格式化一下

# post多部分编码文件
url = 'http://m.ctrip.com'
files = {'file': open('report.xls', 'rb')}
r = requests.post(url, files=files)

# 响应状态码
r = requests.get('http://m.ctrip.com')
print(r.status_code)
    
# 响应头
r = requests.get('http://m.ctrip.com')
print (r.headers)
print (r.headers['Content-Type'])
print (r.headers.get('content-type')) #访问响应头部分内容的两种方式
    
# Cookies
url = 'http://example.com/some/cookie/setting/url'
r = requests.get(url)
r.cookies['example_cookie_name']    #读取cookies
    
url = 'http://m.ctrip.com/cookies'
cookies = dict(cookies_are='working')
r = requests.get(url, cookies=cookies) #发送cookies

#设置超时时间
r = requests.get('http://m.ctrip.com', timeout=0.001)

#设置访问代理
proxies = {
           "http": "http://10.10.1.10:3128",
           "https": "http://10.10.1.100:4444",
          }
r = requests.get('http://m.ctrip.com', proxies=proxies)


#如果代理需要用户名和密码,则需要这样:
proxies = {
    "http": "http://user:[email protected]:3128/",
}

参考:

Python—requests模块详解 - 小L小 - 博客园

你可能感兴趣的:(python,运维,python,运维,运维开发)