写在前面

我相信很多小伙伴学完Python基础后,一定会去接触爬虫,也有很多人入门Python都是从爬虫开始的,包括我自己也是这样的。几乎所有学Python都知道requests这个库,它是大名鼎鼎K神的得意之作,非常非常非常好用

但是随时Python异步async的大流行,由于requests本身是阻塞的导致在使用异步的时候有些捉襟见肘。今天我就给大家推荐一个牛*的库,可以同时支持同步和异步的请求,一箭双雕,一起来看一下吧

如何安装

直接 pip install httpx 即可,非常方便
如果你觉得安装速度太慢的话,不妨试试这个:pip install httpx -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

HTTPX需要Python 3.6+

快速使用

同步的http请求

import httpx

response = httpx.get('http://www.example.org/')

print(response)
#output: <Response [200 OK]>

print(response.status_code)
#output:200

print(response.headers['content-type'])
#output:'text/html; charset=UTF-8'

print(reponse.text)
#output:网站源码

get()方法很简单,与requests库非常相似

异步请求

不了解Python异步函数的可以先去看看我这篇文章Python高级编程之异步函数 asyncawait的使用

异步的请求:

import httpx
import asyncio

async def main():
    async with httpx.AsyncClient() as client:
        #异步请求用 AsyncClient()
        response = await client.get('http://www.example.org/')
        print(response)
asyncio.run(main())

直接和Python内置的asyncio库进行组合使用,进行异步请求

强大的功能

httpx支持很多http的请求方式,除了我们常见的get请求之外 ,还支持自定义header,自定义post表单数据,发送文件分段上传,发送二进制请求数据等等。下面给大家简单演示一下:

import httpx

#在url中传递参数,我们在爬虫中经常用到
params = {'key1':'value1','key2':'value2'}
response = httpx.get('https://httpbin.org/get',params=params)

#发生post数据
httpx.post('https://httpbin.org/post',data={'key':'value'})

#自定义 Headers
url = 'https://httpbin.org/headers'
headers = {'user-agent':'my-app-test/4.1.2'}
response = httpx.get(url=url,headers=headers)

实战异步玩一下

既然httpx它的一个很大的卖点是异步,说了这么多,我们用一个小的异步爬虫案例来玩一下httpx库,并发爬取有道词典看看效果

from pyquery import PyQuery as pq
import asyncio
import httpx
import time

async def my_request(client,word='china'):
    desc_text = ''
    url_base = f'http://dict.youdao.com/w/eng/{word}/'
    r = await client.get(url_base)
    doc = pq(r.text)

    for li in doc.items('#phrsListTab .trans-container ul li'):
        desc_text += li.text()
    print(desc_text)

async def main():
    async with httpx.AsyncClient() as client:  #异步请求用 AsyncClient()
        start = time.time()
        task_list = []
        for i in range(100):
            req = my_request(client)
            task = asyncio.create_task(req)
            task_list.append(task)
        await asyncio.gather(*task_list)
        end = time.time()
    print(f'一共用时:{end-start}')

if __name__ == '__main__':
    asyncio.run(main())

整个程序非常短30来行,非常简单,就分两部分:

  1. 第一部分:就是用httpx构造一个client发起异步请求,连续请求100次,然后把这个100个请求任务包裹在async框架里面,进行并发处理
  2. 第二部分:就是每一个去有道发起一个请求,然后用pyquery进行解析html文本数据

值得注意的是100次请求平均用时1.5秒

如果用requests库同步处理的花至少要52秒左右,可以看到httpx快得不止一点点
requests版本代码

import time
import requests
from pyquery import PyQuery as pq

def my_request(word='china'):
    desc_text = ''
    url_base = f'http://dict.youdao.com/w/eng/{word}/'
    r = requests.get(url_base)
    doc = pq(r.text)

    for li in doc.items('#phrsListTab .trans-container ul li'):
        desc_text += li.text()
    print(desc_text)
def main():
    s = time.time()
    for i in range(100):
        my_request()
    e = time.time()
    print(f"一共用时:{e-s}")

if __name__ == '__main__':
    main()

写在最后

上面只介绍了一部分功能,httpx还有很多强大的功能,使用方法跟requests差不多。requests能支持的httpx都支持,requests不能干的事情httpx也能干。这个库野心还是很大的,当你的项目既要支持同步请求和也要支持异步请求的时候,httpx就该上场啦!有兴趣的小伙伴赶紧试试吧


世界因代码而改变 Peace Out
世界因代码而改变 Peace Out
最后修改:2020 年 10 月 07 日 03 : 26 PM
如果觉得我的文章对你有用,请随意赞赏