一、 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()