一步一步学爬虫(2)之httpx的使用

一步一步学爬虫(2)之httpx的使用

    • 2.4 httpx的使用
      • 2.4.1 示例
      • 2.4.2 安装
      • 2.4.3 基本使用
      • 2.4.4 Client对象
      • 2.4.5 支持HTTP/2.0
      • 2.4.6 支持异步请求

2.4 httpx的使用

  • 前面提到的urllib和requests库的使用,可以爬取绝大多数网站数据,但是HTTP/2.0协议的网站,就没法爬取了。这种情况就用到了httpx库。

2.4.1 示例

  书上给举了这个例子 https://spa16.scrape.center/. 这应该是崔老师自己的站点,自己做的样例,强烈推荐,这本最新的爬虫书. 那么问题来了,我们是怎么知道它使用的是http/2.0呢,requests不能用吗?
  打开浏览器 去检查元素,看network那个标签下的All(全部)里面的第一个,右侧标头里面的请求标头Request Headers。如图。
一步一步学爬虫(2)之httpx的使用_第1张图片
  既然是HTTPS2.0的,用requests库是无法爬取的,不妨尝试一下看:

import requests

url = "https://spa16.scrape.center"
resp = requests.get(url)
print(resp.text)

  运行结果自然是报错。这里的报错,并不是没有设置请求头的问题。真实原因是requests这个库是使用HTTP/1.1访问目标网站,而这个网站是2.0,自然没法访问。

2.4.2 安装

  • httpx可以直接用pip3工具安装。
    pip3 install httpx
  • 另外,除了这个httpx,想要支持HTTP/2.0,还要再安装一个工具。
    pip3 install 'httpx[http2]'

2.4.3 基本使用

  httpx 和 requests 的很多 API 存在相似之处,我们先看下最基本的 GET 请求的用法:

import httpx

response = httpx.get('https://www.httpbin.org/get')
print(response.status_code)
print(response.headers)
print(response.text)

  这里我们还是请求之前的测试网站,直接使用 httpx 的 get 方法即可,用法和 requests 里的一模一样,将返回结果赋值为response 变量,然后打印出它的status_code、headers、text等属性,运行结果如下:

200
Headers({'date': 'Mon, 26 Dec 2022 15:28:48 GMT', 'content-type': 'application/json', 'content-length': '311', 'connection': 'keep-alive', 'server': 'gunicorn/19.9.0', 'access-control-allow-origin': '*', 'access-control-allow-credentials': 'true'})
{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Host": "www.httpbin.org", 
    "User-Agent": "python-httpx/0.23.1", 
    "X-Amzn-Trace-Id": "Root=1-63a9bdb0-0d54247f5449601021648371"
  }, 
  "origin": "39.69.199.58", 
  "url": "https://www.httpbin.org/get"
}

  输出结果包含三项内容,status_code属性对应状态码为200;headers 属性对应响应头,是一个 Headers 对象,类似于一个字典;text 属性对应响应体,可以看到其中的 User-Agent是 python-httpx/0.23.1,代表我们是用 httpx 请求的。
  下面换一个 User-Agent 再请求一次,代码改写如下:

import httpx

headers = {
    'User-Agent': 'Mozilla/5.0(Macintosh;Intel Mac OS X 10_15_7) ApplewebKit/537.36 (KHTML, like Gecko) '
                  'Chrome/90.0.4430.93 Safari/537.36'}
response = httpx.get('https://www.httpbin.org/get', headers=headers)
print(response.text)

  这里我们换了一个User-Agent 重新请求,并将其赋值为 headers 变量,然后传递给 headers参数,运行结果如下:

{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Host": "www.httpbin.org", 
    "User-Agent": "Mozilla/5.0(Macintosh;Intel Mac OS X 10_15_7) ApplewebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36", 
    "X-Amzn-Trace-Id": "Root=1-63a9be5f-5a590f5402f8cc9c0eb7ec6a"
  }, 
  "origin": "39.69.199.58", 
  "url": "https://www.httpbin.org/get"
}

  发现更换后的User-Agent生效了,这是请求HTTP/1.1的情况。那再试试开始的那个网站,代码如下:

import httpx

response = httpx.get('https://spa16.scrape.center')
print(response.text)

  运行后发现,依然报错。原因是httpx使用HTTP/2.0的时候需要声明一下,如下:

import httpx

client = httpx.Client(http2=True)
response = client.get('https://spa16.scrape.center')
print(response.text)

  然后,就运行正常了。
一步一步学爬虫(2)之httpx的使用_第2张图片
  然后其他用法和requests库是一样的,同样能用status_code得到状态码,响应text文本内容,以及content得到二进制内容和headers响应头、json方法等。

2.4.4 Client对象

  这个方法,可以结合request中的session对象类比学习。
  下面我们学习Client对象的使用。官方的使用方式是with as语句。示例如下:

import httpx

with httpx.Client(http2=True) as client:
	resp = client.get('https://spa16.scrape.center')
	print(resp.text)

  这个用法等价于:

import httpx

client = httpx.Client(http2=True)
try:
    resp = client.get('https://spa16.scrape.center')
    print(resp.text)
finally:
    client.close()

2.4.5 支持HTTP/2.0

  • HTTP/1.1的网站示例。

    import httpx
    
    url = "http://www.httpbin.org/headers"
    client = httpx.Client(http2=True)
    resp = client.get(url)
    print(resp.text)
    print(resp.http_version)
    
  • 运行结果 如下:

    {
      "headers": {
        "Accept": "*/*", 
        "Accept-Encoding": "gzip, deflate", 
        "Host": "www.httpbin.org", 
        "User-Agent": "python-httpx/0.23.1", 
        "X-Amzn-Trace-Id": "Root=1-63a9c6e9-503cf55e6ceb91b96402ec9e"
      }
    }
    
    HTTP/1.1
    
  • HTTP/2.0的网站示例。

    import httpx
    
    url = "https://spa16.scrape.center"
    client = httpx.Client(http2=True)
    resp = client.get(url)
    print(resp.text)
    print(resp.http_version)
    
  • 运行结果,如下:

    DOCTYPE html>
    <html lang=en>
    	<head>
    		<meta charset=utf-8>
    		<meta http-equiv=X-UA-Compatible content="IE=edge">
    		<meta name=viewport content="width=device-width,initial-scale=1">
    		<meta name=referrer content=no-referrer>
    		<link rel=icon href=/favicon.ico> <title>Scrape | Booktitle>
    		<link href=/css/chunk-50522e84.e4e1dae6.css rel=prefetch>
    		<link href=/css/chunk-f52d396c.4f574d24.css rel=prefetch>
    		<link href=/js/chunk-50522e84.6b3e24aa.js rel=prefetch>
    		<link href=/js/chunk-f52d396c.f8f41620.js rel=prefetch>
    		<link href=/css/app.ea9d802a.css rel=preload as=style>
    		<link href=/js/app.b93891e2.js rel=preload as=script>
    		<link href=/js/chunk-vendors.a02ff921.js rel=preload as=script>
    		<link href=/css/app.ea9d802a.css rel=stylesheet>
    	head>
    	<body>
    		<noscript>
    			<strong>We're sorry but portal doesn't work properly without JavaScript enabled. Please enable it to continue.strong>
    		noscript>
    		<div id=app>div>
    		<script src=/js/chunk-vendors.a02ff921.js> script> <script src=/js/app.b93891e2.js> script> body> html>
    HTTP/2
    

2.4.6 支持异步请求

  httpx还支持异步客户端请求(即AsyncClient),支持Python的async请求模式,写法如下:

import httpx
import asyncio


async def fetch(url):
    async with httpx.AsyncClient(http2=True) as client:
        resp = await client.get(url)
        print(resp.text)


if __name__ == '__main__':
    asyncio.get_event_loop().run_until_complete(fetch('https://www.httpbin.org/get'))

你可能感兴趣的:(Python爬虫,爬虫,httpx,python)