Python requests 示例备记

193 阅读3分钟

参考:www.byhy.net/tut/auto/ap…

Get

proxies = {
    'http': 'http://127.0.0.1:8866',
    'https': 'https://127.0.0.1:8866',
}

headers = {
    # 请求头
    'user-agent':'my-app/0.0.1'
}
urlpara = {
    # 参数
    'wd': 'cat',
}

response = requests.get('https://www.baidu.com', verify=False, params=urlpara, headers=headers)
print(response.text)

Post

if __name__ == '__main__':
    proxies = {
        'http': 'http://127.0.0.1:8866',
        'https': 'https://127.0.0.1:8866',
    }
    # 上传 xml
    payload = '''
    <?xml version="1.0" encoding="UTF-8"?>
    <WorkReport>
        <Overall>良好</Overall>
        <Progress>30%</Progress>
        <Problems>暂无</Problems>
    </WorkReport>
    '''
    # 如果传入的是字符串类型,Requests会使用缺省编码latin-1编码为字符串放到http消息体中
    # 如果传入的是字典类型,则Requests会按照 Content-Type 为 application/x-www-form-urlencoded (即key1=value1&key2=value2...) 对请求体进行urlencode
    # 所以 data 要 encode
    # 关于 verify=False
    # https://zhuanlan.zhihu.com/p/144694140
    # 消息体中的数据放 data 中
    response = requests.post('https://httpbin.org/post', verify=False, data=payload.encode('utf8'))
    print(response.text)

image.png

POST: urlencode 格式消息体

proxies = {
    'http': 'http://127.0.0.1:8866',
    'https': 'https://127.0.0.1:8866',
}
payload = {'key1': 'value1', 'key2': 'value2'}
response = requests.post('https://httpbin.org/post', verify=False, data=payload)
print(response.text)

image.png

如果 payload 有中文:

payload = {'key1': '值1', 'key2': '哈哈'}

# 由于data是字典,则:请求体中会进行按照 
# Content-Type: Content-Type: application/x-www-form-urlencoded 进行 urlencode:
key1=%E5%80%BC1&key2=%E5%93%88%E5%93%88

这里需要注意:如果传的不是字典,而是纯字符串:

# Error
response = requests.post('https://httpbin.org/post', verify=False, data='key1=值&key2=哈哈')

程序会报错:

Body ('值') is not valid Latin-1. Use body.encode('utf-8') if you want to send it encoded in UTF-8.

因为传字符串的话默认使用 Lanti-1 编码,这就需要进行编码了:

# OK
response = requests.post('https://httpbin.org/post', verify=False, data='key1=值&key2=哈哈'.encode('utf8'))

如果这样写,请求头里就没有了 Content-Type: application/x-www-form-urlencoded, 如果服务器强制校验 Content-Type 的话,可能会发生错误,所以一般还是直接传字典得了

Post: JSON 格式消息体

import requests, json

if __name__ == '__main__':
    proxies = {
        'http': 'http://127.0.0.1:8866',
        'https': 'https://127.0.0.1:8866',
    }
    payload = {
        "Overall": "良好",
        "Progress": "30%",
        "Problems": [
            {
                "No": 1,
                "desc": "问题1...."
            },
            {
                "No": 2,
                "desc": "问题2...."
            },
        ]
    }
    # OK:
    # response = requests.post("http://httpbin.org/post", data=json.dumps(payload))

    # json.dumps 会把字典转成json格式的字符串,并且对非ascii吗进行unicode转码,可以使用ensure_ascii=False不让它转
    # OK:
    # response = requests.post("http://httpbin.org/post", data=json.dumps(payload, ensure_ascii=False).encode())

    # OK:
    # 这种是推荐的做法,因为这种方式会在请求头上添加 Content-Type: application/json
    response = requests.post("http://httpbin.org/post", json=payload)

    print(response.text)

获取响应状态码

response = requests.get("http://httpbin.org")
print(response.status_code)

获取响应头

import requests

if __name__ == '__main__':
    proxies = {
        'http': 'http://127.0.0.1:8866',
        'https': 'https://127.0.0.1:8866',
    }
    response = requests.get("http://httpbin.org")
    # response.headers 是 dict 的子类
    print(type(response.headers)) # <class 'requests.structures.CaseInsensitiveDict'>
    print(response.headers)
    # print(dict(response.headers)) # 可以强转
    print(response.headers['Content-Length'])

获取响应体

import requests, json

if __name__ == '__main__':
    proxies = {
        'http': 'http://127.0.0.1:8866',
        'https': 'https://127.0.0.1:8866',
    }
    # payload = {
    #     'key1': 'value1',
    #     '键2': '值2'
    # }
    payload = {'key1': '值1', 'key2': '哈哈'}
    response = requests.post("http://httpbin.org/post", data=payload)
    # response = requests.get("http://www.thinkermaster.com/daliu/test/userInfo")
    # response = requests.get("http://mirrors.sohu.com/")

    ###########################
    #        编码相关
    ###########################
    # requests 会根据服务器返回的响应消息头(比如 Content-Type)对编码格式做推测
    # 但是有时候,服务端并不一定会在消息头中指定编码格式,这时, requests的推测可能有误,需要我们指定编码格式
    # response.encoding = 'utf8'
    # print(response.encoding) # utf8
    # 获取字符串内容
    # print(response.text)
    # 获取字节串内容 Byte content
    print(response.content)
    # 把字节串解码成字符串
    print(response.content.decode('utf8'))
    # json.dumps 是编码为字符串,json.loads是解码为python对象

    ###########################
    #  json数据 -> Python对象
    ###########################
    text = response.content.decode('utf8')
    # loads可接收的参数类型为:the JSON object must be str, bytes or bytearray
    data = json.loads(text)
    print(type(data)) # <class 'dict'>
    print(data['headers']['Content-Type']) # application/x-www-form-urlencoded

    ###########################
    #  json数据 -> Python对象 2
    ###########################
    obj = response.json()
    print(obj['headers']['Content-Type'])

Session-Cookie 支持

import requests

if __name__ == '__main__':
    # 打印HTTP响应消息的函数
    def printResponse(response):
        print('\n\n-------- HTTP response * begin -------')
        print(response.status_code)

        for k, v in response.headers.items():
            print(f'{k}: {v}')

        print('')

        print(response.content.decode('utf8'))
        print('-------- HTTP response * end -------\n\n')


    # 创建 Session 对象
    session = requests.Session()

    # 通过 Session 对象 发送请求
    response = session.post("http://127.0.0.1/api/mgr/signin", data={
               'username': 'byhy',
               'password': '88888888'})
    printResponse(response)

    # 通过 Session 对象 发送请求
    response = session.get("http://127.0.0.1/api/mgr/customers",
                     params={
                         'action': 'list_customer',
                         'pagesize': 10,
                         'pagenum': 1,
                         'keywords': '',
                     })

    printResponse(response)