Back to Blogs
python
http
request

Python HTTP Request

Soloman
2019-04-28

Python HTTP Request

1 urllib3

  1. 线程安全

  2. 连接池

  3. 客户端SSL/TLS验证

  4. 文件分部编码上传

  5. 协助处理重复请求和HTTP重定位

  6. 支持压缩编码

  7. 支持HTTP和SOCKS代理

安装

pip install urllib3

基本使用测试

import json
import logging
import urllib3
logging.basicConfig(level=logging.INFO)


def test_urllib3():
    logging.info(urllib3.__version__)
    test_url1 = 'http://www.soloman.vip/robots.txt'
    test_url2 = 'http://httpbin.org/'
    http = urllib3.PoolManager(num_pools=5, timeout=2.0)
    response = http.urlopen('GET', test_url1, retries=2, redirect=2, timeout=1)
    if response.status == 200:
        logging.info(response.data.decode('utf-8'))

    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64)',
        'Host': 'httpbin.org',
        'Content-Type': 'application/json'
    }
    data = {'word': 'hello'}
    data = json.dumps(data).encode()
    response = http.request('POST', test_url2, body=data, headers=headers, timeout=5)
    logging.info(response.status)


if __name__ == '__main__':
    test_urllib3()

urllib3 官方文档

2 requests

安装

pip install requests

requests.get()

import requests


r = requests.get(url, params=None, **kwargs)
# url: 网站地址。
# params: url中的额外参数,字典或者字节流格式,可选。
# **kwargs : 12个控制访问的参数
"""
params:字典或字节序列, 作为参数增加到url中,使用这个参数可以把一些键值对以?key1=value1&key2=value2的模式增加到url中
data:字典,字节序列或文件对象,与params不同的是,data提交的数据并不放在url链接里, 而是放在url链接对应位置作为数据来存储。,它也可以接受一个字符串对象。
json:json格式的数据。
例如:kv = {'key1': 'value1'} 
r = requests.post('http://python123456.io/ws', json=kv)

headers:可以用这个字段来定义http的访问的http头,可以用来模拟任何我们想模拟的浏览器来对url发起访问。
例子: hd = {'user-agent': 'Chrome/10'} 
r = requests.post('http://python123.io/ws', headers=hd)

cookies:字典或CookieJar,指的是从http中解析cookie
auth:元组,用来支持http认证功能
files:字典, 是用来向服务器传输文件时使用的字段。
例子:fs = {'files': open('data.txt', 'rb')} 
r = requests.post('http://python123456.io/ws', files=fs)

timeout: 用于设定超时时间, 单位为秒,如果在timeout时间内请求内容没有返回, 将产生一个timeout的异常。
proxies:字典, 用来设置访问代理服务器。
allow_redirects: 开关, 表示是否允许对url进行重定向, 默认为True。
stream: 开关, 指是否对获取内容进行立即下载, 默认为True。
verify:开关, 用于认证SSL证书, 默认为True。
cert: 用于设置保存本地SSL证书路径
"""

# 响应的内容。使用requests方法后,会返回一个response对象,其存储了服务器响应的内容,如:
r.encoding                       # 获取当前的编码
r.encoding = 'utf-8'             # 设置编码
r.text                           # 以encoding解析返回内容。字符串方式的响应体,会自动根据响应头部的字符编码进行解码。
r.content                        # 以字节形式(二进制)返回。字节方式的响应体,会自动为你解码 gzip 和 deflate 压缩。
r.headers                        # 以字典对象存储服务器响应头,但是这个字典比较特殊,字典键不区分大小写,若键不存在则返回None
r.status_code                    # 响应状态码
r.raw                            # 返回原始响应体,也就是 urllib 的 response 对象,使用 r.raw.read()   
r.ok                             # 查看r.ok的布尔值便可以知道是否登陆成功
r.json()                         # Requests中内置的JSON解码器,以json形式返回,前提返回的内容确保是json格式的,不然解析出错会抛异常
r.raise_for_status()             # 失败请求(非200响应)抛出异常

requests.post()

import requests
import json


r = requests.post(url, data=None, json=None, **kwargs)

# post发送json数据请求,设置秒数超时,仅对于连接有效
r = requests.post('https://www.soloman.vip', data=json.dumps({'some': 'data'}, timeout=5))
print(r.json())

# post发送字典数据请求
post_data = {"key1":"value1","key2":"value2"}
headers = {
    'content-type': 'application/json',
    'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0'
}
r = requests.post('https://www.soloman.vip', data=post_data, headers=headers)

# post发送字符串数据请求,自动编码为data
r = requests.post('https://www.soloman.vip', data="welcome to soloman's website!")

# post发送文件数据请求,即上传文件
files = {'files': open('F:\\python\\test\\soloman.txt','rb')}
r = requests.post('https://www.soloman.vip', files=files)

# 定制头信息和cookie信息
header = {'user-agent': 'Soloman app/0.0.1''}
cookie = {'key':'value'}
r = requests.get/post('https://www.soloman.vip', headers=header, cookies=cookie) 

requests.Session

会话对象让你能够跨请求保持某些参数,最方便的是在同一个Session实例发出的所有请求之间保持cookies,且这些都是自动处理的,甚是方便。

import requests


# 会话对象,能够跨请求保持某些参数
s = requests.Session()
s.auth = ('auth','passwd')
s.headers = {'key':'value'}
r1 = s.get('url1')
r2 = s.get('url2') 
session = requests.Session()

# 一般流程
# 1、首先登陆任何页面,获取cookie
session = requests.Session()
i1 = session.get(url1)
# 2、用户登陆,携带上一次的cookie
i2 = session.post(
    url="http://www.xxxx.com/login",
    data={
        'phone': "123",
        'password': "xxxxxx"
    }
)
# 3、携带登录后的的cookie,可访问需要登录才能查看的网页
i3 = session.post(url3)
print(i3.text)

其他请求类型

import requests

r = requests.options(url, **kwargs)
r = requests.head(url, **kwargs)
r = requests.put(url, data=None, **kwargs)
r = requests.patch(url, data=None, **kwargs)
r = requests.delete(url, **kwargs)

requests 官方文档

3 aiohttp

安装

pip install aiohttp

基本使用测试:每次连接都创建一个新 ClientSession 对象

import asyncio
import logging
import aiohttp
logging.basicConfig(level=logging.INFO)
test_url = 'http://httpbin.org/get'


async def fetch_page(client):
    async with client.get(test_url) as resp:
        assert resp.status == 200
        return await resp.text()


async def test_aiohttp():
    async with aiohttp.ClientSession() as client:
        page = await fetch_page(client)
        logging.info(page)
        
        
if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    tasks = []
    for i in range(20):
        task = loop.create_task(test_aiohttp())
        tasks.append(task)

    loop.run_until_complete(asyncio.gather(*tasks))

基本使用测试:每次连接都使用同一个 ClientSession 对象。aiohttp.ClientSession() 中封装了一个 session 的连接池,并且在默认情况下支持 keepalives,官方建议在程序中使用单个 ClientSession 对象,而不是像上面示例中的那样每次连接都创建一个 ClientSession 对象,除非在程序中遇到大量的不同的服务。

import asyncio
import logging
import aiohttp
logging.basicConfig(level=logging.INFO)
test_url = 'http://httpbin.org/get'


async def fetch_page(client):
    async with client.get(test_url) as resp:
        assert resp.status == 200
        return await resp.text()


async def test_aiohttp():
    async with aiohttp.ClientSession() as client:
        tasks = []
        for i in range(20):
            task = asyncio.create_task(fetch_page(client))
            tasks.append(task)
        
        return await asyncio.wait(tasks)
    	# return await asyncio.gather(*tasks)
        
        
if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    ret = loop.run_until_complete(test_aiohttp())
    logging.info(ret)

aiohttp 官方文档