一、 HTTP客户端
1.1 HTTP消息详解
请求和相应:客户端向服务器发送获取文档的请求(request),一旦发送完请求,客户端就会进行等待,直到从服务器接收到完整的相应reponse为止。
第一行包含一个方法名和要请求的文档名;在响应消息中,第一行包含了返回码和描述信息。无论是在请求和响应消息中,第一行都以回车和换行(CR-LF)结尾。
第二部分包含或多个头信息,每个信息由一个名称,一个冒号以及一个值组成。HTTP头的名称区分大小写。头信息之后再跟着一个空行。
第三部是一个可选的消息体。消息体紧跟着头信息后面的空行。
HTTP方法:
读:GET ——请求获取Request-URL所标识的资源;
写:POST——在Request-URL所标识的资源后附加新的数据
OPTIONS : 请求与给定路径匹配的HTTP头的值;
HEAD:请求服务器做好一切发送资源的准备,但是只发送头部信息。
DELETE:请求服务器删除Request-URL所标识的资源。
PUT:请求服务器存储一个资源,并用Request-URL作为其标识
TRACE:请求服务器回送收到的请求信息,主要用于测试或诊断
CONNECT:保留将来使用。

1.2 GET请求
http ?/ www.tedu.cn /
协议部分 分隔符 目标域名 请求的资源
常用的请求报头:
METHOD:请求资源的方法,必须有
HOST:被请求的资源的名字,必须有
Accept :请求报头域用于指定客户端接受哪些类型的信息
Accept-Encoding :用于指定可接受的内容编码
User-Agent 客户端信息
Connection :是否关闭连接。

1.3 GET响应消息
HTTP/1.1 200 协议、版本和状态
Date 日期时间
Server 服务器消息
Conntent-Type 响应内容类型
Conntent-Length 响应数据长度
Last-Midified 资源最后更改时间
Connection 连接方式

1.4 POST方法
要求被请求服务器接受附在请求后面的数据,常用于提交表单,一般要在头部声明数据长度,信息头说明参见GET方法。


二、utllib模块
python内置了urllib包来处理http请求,主要是一下几个模块:
urllib.error :处理异常模块,包含了urllib.request产生的异常
urllib.parse : 解析和处理url模块
urllib.request : 用来发送request和获取request的 结果
urllib.response : 响应模块
urllib.robotparser 解析页面的 robots.txt文件,与爬虫相关


2.1 爬取网页:
先需要导入用到的模块:urllib.request,在导入模块之后,需要使用urllib.request.urlopen打开并爬取一个网页。
读取内容常见的有三种方式:
——read() 读取文件的全部内容,readline() 读取文件的一行内容。与readlines()不同的是,read() 会把读取的内容赋给一个字符串变量,而readlines() 会把读取到的内容赋值给一个列表变量。


主要方法:
urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)


#####获取网页,保存网页信息到文件
 import sys
 from urllib.request import urlopen
 def get_web(url, fname):
 html = urlopen(url)
 with open(fname, ‘wb’) as fobj:
 while True:
 data = html.read(4096)
 if not data:
 break
 fobj.write(data)
 html.close()
 if name == ‘main’:
 get_web(sys.argv[1], sys.argv[2])
 ########### 爬取网页图片的网址
 import sys
 import re
 def get_url(patt, fname):
 cpatt = re.compile(patt)
 result = []
 with open(fname) as fobj:
 for line in fobj:
 m = cpatt.search(line)
 if m:
 result.append(m.group())
 return result
 if name == ‘main’:
 url = r’http://[.\w/-]+.(jpg|png|jpeg|gif)’
 print(get_url(url, sys.argv[1]))
 ########### 批量爬取图片,下载到本机。
 import os
 from get_url import get_url
 from getweb import get_web
 get_web(‘http://www.tedu.cn/’, ‘/tmp/tedu.html’)
 img_url = r’http://[.\w/-]+.(jpg|png|jpeg|gif)’
 urls = get_url(img_url, ‘/tmp/tedu.html’)
 img_dir = ‘/tmp/images’
 if not os.path.exists(img_dir):
 os.mkdir(img_dir)
 for url in urls:
 fname = os.path.join(img_dir, url.split(’/’)[-1])
 try: ##爬取过程出现了问题,自动跳过,进入下一图片爬取
 get_web(url, fname)
 except:
 pass

2.2 模拟客户端
设置一些Headers信息(User-Agent),模拟成浏览器去访问这些网站。

import sys
 from urllib.request import urlopen
 from urllib.request import Request
 def get_web(url, fname):
 header = {
 ‘User-Agent’: ‘Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0’
 }
 request = Request(url, headers=header)
 html = urlopen(request)
 with open(fname, ‘wb’) as fobj:
 while True:
 data = html.read(4096)
 if not data:
 break
 fobj.write(data)
 html.close()
 if name == ‘main’:
 get_web(sys.argv[1], sys.argv[2])

2.3 数据编码
一般来说,URL标准中只会允许一部分ASCII字符,比如数字、字母、部分符号等,而汉字等不符合URL标准,因此要进行编码,可以使用urllib.request.quote()进行。

from urllib.request import quote
 import webbrowser
 words = quote(‘hello world!’)
 search = ‘https://www.baidu.com/s?wd=’ + words
 print(search)
 webbrowser.open_new_tab(search)


2.4 HTTP异常处理
如果访问的页面不存在或拒绝访问,程序将抛出异常,捕获异常需要导入urllib.error模块。
——启动一个web服务,在web服务器的文档目录下创建目录ban,权限设置为700;编写python程序访问不存在的路径和ban目录,处理404和403错误;404错误打印“无此页面”,403错误打印“无权访问“。

]# mkdir -m 700 /var/www/html/ban
 ]# systemctl restart httpd
 】>>>import urllib.request
 】>>>html =urllib.request.urlopen(‘http://192.168.4.254/ban’) ###403访问拒绝
 】>>>html =urllib.request.urlopen(‘http://192.168.4.254/abc.html’) ##404 网页不存在
 import sys
 from urllib.request import urlopen
 from urllib.error import HTTPError
 def get_web(url, fname):
 try:
 html = urlopen(url)
 except HTTPError as e: ## 返回HTTPError类的实例e
 print(e)
 if e.code == 403:
 print(‘权限不足’)
 elif e.code == 404:
 print(‘没有那个地址’)
 return ##函数遇到reture就会返回,不再往下执行代码
 with open(fname, ‘wb’) as fobj:
 while True:
 data = html.read(4096)
 if not data:
 break
 fobj.write(data)
 html.close()
 if name == ‘main’:
 get_web(sys.argv[1], sys.argv[2])

三、paramiko模块
]# pip3 install paramiko ##安装模块
基础使用介绍:

——SSHClient:创建用于连接ssh服务器的实例
 ]>>>ssh =paramiko.SSHClient()
 ——paramiko.AutoAddPolicy: 设置自动添加主机密钥
 ——ssh.connect :连接ssh服务器
 ——ssh.exec_comand: 在ssh服务器上执行指定命令
 import paramiko
 ssh = paramiko.SSHClient() # 创建实例
 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 相当于回答yes
 ssh.connect(
 hostname=‘127.0.0.1’,
 username=‘root’,
 port=22,
 password=‘redhat’
 )
 a = ssh.exec_command(‘ls /home’)
 #a是由类文件对象组成的列表,共三项,分别是输入、输出、错误
 print(len(a))
 out = a[1].read()
 error = a[2].read()
 print(out.decode(‘utf8’))
 print(error.decode(‘utf8’))
 ssh.close()

####远程通过SSH控制多台主机
 import sys
 import getpass
 import paramiko
 import threading
 import os
 def remote_comm(host, pwd, command):
 ssh = paramiko.SSHClient()
 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
 ssh.connect(hostname=host, username=‘root’, password=pwd)
 stdin, stdout, stderr = ssh.exec_command(command)
 out = stdout.read()
 error = stderr.read()
 if out:
 print(’[%s] OUT:\n%s’ % (host, out.decode(‘utf8’)))
 if error:
 print(’[%s] ERROR:\n%s’ % (host, error.decode(‘utf8’)))
 ssh.close()
 if name == ‘main’:
 if len(sys.argv) != 3:
 print(‘Usage: %s ipaddr_file “command”’ % sys.argv[0])
 exit(1)
 if not os.path.isfile(sys.argv[1]):
 print(‘No such file:’, sys.argv[1])
 exit(2)
 fname = sys.argv[1]
 command = sys.argv[2]
 pwd = getpass.getpass()
 with open(fname) as fobj:
 ips = [line.strip() for line in fobj]
 for ip in ips:
 t = threading.Thread(target=remote_comm, args=(ip, pwd, command))
 t.start()

####用户名、密码登陆方式
 import paramiko
 paramiko.util.log_to_file(‘paramiko.log’)
 ssh =paramiko.SSHClient()
 try:
 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
 ssh.connect(hostname=‘192.168.4.10’,username=‘root’,password=‘123’)
 cmd = ‘ls /home’
 stdin,stdout,stderr =ssh.exec_command(cmd)
 print(stdout.readlines())
 print(stdout.read().decode(‘utf8’))
 except Exception as e:
 print("%s:%s" %(e.class,e))
 finally:
 ssh.close()

##免密登陆方式
 import paramiko
 ssh =paramiko.SSHClient()
 SSH_PRIVATE_KEY = ‘/root/.ssh/id_rsa’   ###本地密钥文件路径
 try:
     key = paramiko.RSAKey.from_private_key(SSH_PRIVATE_KEY)  ##无解密密码时
     #key =paramiko.RSAKey.from_private_key(SSH_PRIVATE_KEY,password=‘123’)  #有解密密码时
     ssh.load_system_host_keys()
     #通过known_hosts 方式进行认证可以用这个,如果known_hosts 文件未定义还需要定义 known_hosts
     ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
     # 自动确认连接
     ssh.connect(hostname=‘192.168.4.10’,port=22,username=‘root’,pkey=key)
     stdin,stdout,stderr = ssh.exec_command(“ps -aux”)
     result = stdout.read()
     print(result.decode(‘utf8’))
 except Exception as e:
     print("%s:%s" %(e.class,e))
 finally:
     ssh.close()