用于网络抓取的三大 Python HTTP 客户端

米赫内亚-奥克塔维安-马诺拉什(Mihnea-Octavian Manolache),2022 年 12 月 02 日

说到网络搜刮,Python HTTP 客户端的多样性使其成为最受欢迎的选择之一。但这些 HTTP 客户端到底是什么,如何使用它们来构建网络抓取器呢?在今天的文章中,我们将讨论这个问题。在本文结束时,您应该对以下内容有一个扎实的了解:

  • 什么是 HTTP 客户端?
  • 2022 年最好的 Python HTTP 客户端是什么?
  • 为什么 Python 是网络搜索的最佳选择?
  • 如何使用 HTTP 客户端创建网络搜刮器

什么是 Python HTTP 客户端以及如何使用它们

为了深入了解互联网的通信方式,我们应该熟悉超文本传输协议(HTTP)。不过,我们今天的重点是围绕 python HTTP 客户端展开。因此,我假定你已经熟悉 HTTP。

一般来说,HTTP 客户端指的是与服务器进行通信的实例或程序。例如,网络浏览器就可以被视为 HTTP 客户端。不过,作为程序员,我们在构建应用程序时很少使用真正的浏览器,除非是在编写网络搜刮程序或进行研究时。

尽管如此,当我们以更程式化的方式提及 HTTP 客户端时,我们通常指的是用于执行 HTTP 请求的方法或类的实例。由于 Python 无疑是最流行的编程语言之一(也是我个人的最爱),今天我们将讨论最好的 Python HTTP 客户端,以及如何在实际项目中实现它们。

了解 HTTP 协议

在继续学习之前,尽管我建议大家查看HTTP 文档,但还是让我快速介绍一下 HTTP 的一些基本概念。首先,HTTP 可能是最常用的互联网协议之一。我们每天都用它在客户端和服务器之间交换信息。 

为了实现这一点,HTTP 使用了请求方法。这些方法表示客户端要在服务器上执行的操作。例如,如果您想从服务器获取某些信息,您可以使用 GET。如果要向服务器发送某些信息,则使用 POST。下面列出了最常见的 HTTP 请求方法:

  • GET- 从服务器检索数据
  • HEAD- 只检索标题,不检索正文(实际数据)
  • POST - 向服务器发送一些信息
  • PUT- 向服务器发送信息并替换资源的所有当前表示形式
  • PATCH- 向服务器发送信息并部分修改资源
  • DELETE- 从服务器上删除资源

为什么用 Python 处理 HTTP 请求

首先,Python 拥有优秀的语法和更强大的社区。因此,它非常适合学习。我自己在刚开始编程时也选择了 Python。事实上,Python HTTP 客户端是我最早接触到的技术之一。但这是另一个话题。 

我今天写这篇文章的目的是让大家不仅对基本理论有所了解,还能对实际操作有一个大致的了解。 

Python 在这两方面都很出色,原因有很多。仅列举几条:

  • 语法- 写 Python 很像写英语。因此,阅读 Python 脚本可以帮助您将理论概念与实际实现联系起来。 
  • 支持- Python 拥有一个非常庞大的社区。大多数情况下,如果您遇到问题,在 StackOverflow 上提出一个简单的问题就能找到答案。 
  • 可用性- Python 的软件包库是最广泛的软件包库之一。例如,仅 Python HTTP 客户端就有十几个软件包。但我们今天将重点讨论最流行的几种。 

3(+1) 最佳 Python HTTP 客户端

说到如何对软件包进行分类,以评选出最佳 Python HTTP 客户端的前三名,我认为这既与功能有关,也与个人偏好有关。因此,以下是我认为的 Python HTTP 客户端库的前三名,而不是总体排名。

1.请求--强大的简洁性

Requests可能是 Python 社区最受欢迎的 HTTP 客户端之一。我也不例外。每当我测试一个新的网络搜索器时,我都会使用 Python 的 Requests。它就像说.get 一样简单,功能却和真正的网络浏览器一样强大。 

除其他外,申请图书馆还提供

  • SSL 验证 
  • HTTPS 代理支持
  • Cookie 持久性和会话
  • 保持活力功能
  • 自定义验证

这些只是其中的一部分。你可以在这里查看完整的功能列表。现在,让我向你展示如何处理请求:

import requests
r = requests.get("http://google.com")
print(r.test)

正如你所看到的,只需 3 行代码,请求库就能帮助我们从服务器收集 HTML 行。在上面的示例中,我们向服务器发出 GET 请求并打印结果。但正如我所说,这个库的功能要丰富得多。让我们构建一个更复杂的示例,使用代理和 POST 请求等功能:

import requests

def get_params(object):
params = ''
for key,value in object.items():
if list(object).index(key) < len(object) - 1:
params += f"{key}={value}."
else:
params += f"{key}={value}"
return params

API_KEY = '<YOUR_API_KEY>'

TARGET_URL = 'https://httpbin.org/post'

DATA = {"foo":"bar"}

PARAMETERS = {
"proxy_type":"datacenter",
"device":"desktop"
}

PROXY = {
"http": f"http://webscrapingapi.{ get_params(PARAMETERS) }:{ API_KEY }@proxy.webscrapingapi.com:80",
"https": f"https://webscrapingapi.{ get_params(PARAMETERS) }:{ API_KEY }@proxy.webscrapingapi.com:8000"
}

response = requests.post(
url=TARGET_URL,
data=DATA,
proxies=PROXY,
verify=False
)

print(response.text)

让我们看看我们在做什么:

  1. 我们正在定义 `get_params` 函数,该函数接收一个对象并将其作为 URL 参数字符串返回。
  2. 我们正在定义变量:
    undefinedundefinedundefinedundefinedundefined
  3. 我们使用 Requests 中的 `post` 方法来发送 HTTP post 请求。
  4. 我们正在打印响应正文

2.HTTPX - 重新发明的请求

HTTPX是一个相对较新的客户端。然而,在很短的时间内,它就成为了最值得推荐的 Python HTTP 客户端之一。例如,Flask(Python 最大的网络框架之一)在其官方文档中就推荐使用 HTTPX。 

我说 HTTPX 是请求的再创造,是因为这两个库的语法非常相似。事实上,HTTPX 的目标是与 requests 完全兼容。两者在设计上只有一些细微差别,在此重点介绍一下。 

下面是 HTTPX 中的基本 POST 请求:

import httpx

TARGET_URL = 'https://httpbin.org/post'

DATA = {"foo":"bar"}

r = httpx.post(
url=TARGET_URL,
data=DATA,
)

print(r.text)

正如你所看到的,与 Requests 示例相比,我们主要改变了软件包的名称。既然它们如此相似,问题仍然是,为什么选择 HTTPX 而不是 Requests。因为 HTTPX 是少数几个提供异步支持的 Python HTTP 客户端之一。总而言之,如果你想重构基于请求的代码,HTTPX 是一个不错的选择。 

3. urllib3 - 线程安全连接

Python 有几个 "urllib",这通常会让新程序员感到困惑。urllib 是 Python 最初的 HTTP 客户端,包含在 Python 1.2 标准库中。

不过,说到urllib3,它实际上是一个第三方 Python HTTP 客户端。尽管名字叫 urllib3,但它与这两个 "前辈 "毫无关系。此外,Python 社区有传言称,标准库中无意包含 urllib3。至少在不久的将来是这样。 

尽管这个软件包并没有与 Python 标准库正式链接,但许多开发人员还是使用了它,因为它提供了以下功能:

  • 螺纹安全
  • 客户端 SSL / TLS 验证
  • HTTP 和 SOCKS 代理支持
  • 完整的测试覆盖范围

理论部分讲完了,让我们来看看实现的例子:

import urllib3,json

TARGET_URL = 'https://httpbin.org/post'

DATA = {"foo":"bar"}

http = urllib3.PoolManager()

encoded_data = json.dumps(DATA)

r = http.request('POST', TARGET_URL, body=encoded_data)

print(r.data.decode('utf-8'))

让我们讨论一下 urllib3 与 Requests 的不同之处:

  • http` - `PoolManager` 方法的实例,用于处理线程安全和连接池的详细信息
  • `encoded_data` - 转换后的 JSON 字符串,包含我们要发送的有效载荷
  • `r` - 我们在 urllib3 的帮助下发出的实际 POST 请求。在这里,我们使用的是 `PoolManager` 实例的 `request` 方法。

最后,我们必须对请求返回的数据进行解码。正如你所看到的,我们所做的有几件事与请求不同。

荣誉奖:http.client - 传统 Python HTTP 客户端

http.client也是标准 Python 库的一部分。传统上,程序员不会直接使用它。例如,为了处理 HTTP 和 HTTPS 请求,urllib 实际上将其作为一个依赖项。我把它列入我们的排名,是因为我认为作为程序员,了解我们正在使用的软件包的 "骨骼 "是件好事。

因此,尽管你可能不会使用 http.client 创建一个实际的项目,但这里有一个实现示例,我相信它会帮助你更好地理解 Python HTTP 客户端是如何工作的:

import http.client

TARGET_URL = 'www.httpbin.org'

http = http.client.HTTPSConnection(TARGET_URL)
http.request("GET", "/get")

r = http.getresponse()

print(r.read().decode('utf-8'))

HTTPSConnection "实例需要几个参数,你可以在这里查看。在我们的示例中,我们只定义了 `method`和 `url`(或者更准确地说,端点)。此外,与 urllib3 类似,http.client 返回的是编码后的响应。因此,我们实际上需要在打印前对其进行解码。

使用案例:使用请求构建扫描器

既然我们已经知道如何使用 HTTP 客户端,那就给自己分配一个小项目吧。这不仅有助于学以致用,还能为自己的编程组合增添一些价值。 

由于 Python HTTP 客户端通常用于从服务器收集信息,这些技术最常见的用途就是创建网络搜刮器。因此,接下来我们将重点讨论如何使用 Python 的 HTTP 客户端创建网络搜刮器。因为我个人最喜欢请求(requests),所以我将在本项目中使用它。不过,你也可以将它作为一个起点,甚至可以对它进行调整,以使用我们讨论过的其他一些技术。废话不多说,让我们开始编码吧:

1.项目设置

让我们先创建一个新目录,在其中存放网络刮擦器用的文件。现在打开一个新的终端窗口,然后`cd`进入该目录。在这里,我们要启动一个新的虚拟环境。如果你使用的是类似 UNIX 的操作系统,可以使用

~ " python3 -m venv env && source env/bin/activate              

现在只需创建一个新的 Python 文件,其中包含我们的逻辑,然后在所需的集成开发环境中打开它。如果要使用终端,只需粘贴以下命令即可:

~ " touch scraper.py && code .                                         

2.安装依赖项

我们将使用 pip 安装本项目所需的软件包。目前,我们已经确定要使用 Requests,但这对于网络搜刮器来说还不够。网络搜索器还需要处理数据。这意味着我们需要解析从服务器收集到的 HTML。幸运的是,Python 库提供了种类繁多的软件包。在本项目中,我们将使用 BeautifulSoup。要安装软件包,只需粘贴以下命令即可:

~ " python3 -m pip install requests bs4                                    

3.编写逻辑

我们将把代码分成两部分:一部分用于数据提取,一部分用于数据操作。前一部分由 Requests 软件包负责,后一部分由 BeautifulSoup 负责。话不多说,让我们开始编码,从提取部分开始:

import requests

def scrape( url = None ):
# 如果没有 URL,则无需使用 Python HTTP 客户端
# 我们将打印一条信息并停止执行
if url == None:
print('[!] Please add a target!')
return

response = requests.get( url )
return response

在本节中,我们将定义一个只有一个参数的函数:目标 URL。如果未提供 URL,我们将打印一条信息并停止执行。否则,我们将使用 Request 的 get 方法返回响应。现在,我们知道 Python HTTP clinetts 涵盖了更多的方法,所以让我们添加一个条件参数:

import requests

def scrape( method = 'get', url = None, data = None ):
# 如果没有 URL,则无需使用 Python HTTP 客户端
# 我们将打印一条信息并停止执行
if url == None:
print('[!] Please add a target!')
return

if method.lower() == 'get':
response = requests.get( url )

elif method.lower() == 'post':
if data == None:
print('[!] Please add a payload to your POST request!')
return
response = requests.post( url, data )

return response

如您所见,我们在函数中添加了几个参数。method "参数指定了我们的请求应使用的方法。data "表示我们通过 POST 请求发送的有效载荷。默认情况下,方法是 GET,因此不需要 `method` 参数。 

挑战: 为该函数添加更多方法,丰富我们的刮板功能。这不仅有趣,也是一种很好的学习方法。此外,你还可以将代码变成自己的,这样就可以将它添加到你的作品集中。

到目前为止,我们已经完成了数据提取。让我们来解析 HTML 并对其进行处理:

from bs4 import BeautifulSoup

def extract_elements(data = None, el = None):
if data == None:
print('[!] Please add some data!')
return

if el == None:
print('[!] Please specify which elements you are targeting!')
return

soup = BeautifulSoup(data.text, 'html.parser')
elements = soup.find_all(el)

return elements

但网络搜刮工具应该能够提取更具体的数据。例如,它应该能够根据 CSS 选择器来定位和返回元素。因此,让我们添加处理这部分内容的逻辑:

from bs4 import BeautifulSoup

def extract_elements(data = None, el = None, attr = None, attr_value = None):
if data == None:
print('[!] Please add some data!')
return

if el == None:
print('[!] Please specify which elements you are targeting!')
return

soup = BeautifulSoup(data.text, 'html.parser')
elements = soup.find_all(el, { attr : attr_value })

return elements

BeautifulSoup 允许我们根据属性提取特定数据。因此,我们在这里添加了两个新参数,它们将帮助我们根据元素的属性来定位和提取元素。

现在我们已经拥有了所需的一切。剩下要做的就是将这两个部分组合起来,这样我们就有了网络搜刮器。组装好代码后,只需

  1. 创建一个新变量,用于保存通过请求提取的数据 
  2. 打印 BeautifulSoup 返回的元素

下面是您代码中缺少的两部分:

data = scrape('GET', 'https://webscrapingapi.com')
print( extract_elements(data, 'ul') )

我相信你已经知道了所有东西的作用,因此没有必要再进行翻译。就像我们的 scraper 一样,我建议你玩玩 `extract_elements` 函数,让它不只是简单地返回元素。 

结论

在学习一个新的编程概念时,我认为最好使用现有的不同技术进行测试。不过,在为更大的项目实际构建基础架构时,最好还是先了解每种技术的优缺点,然后再选择其中一种。 

我希望这篇文章无论如何都能帮到你,而且你现在已经对 Python HTTP 客户端的工作原理有了扎实的了解。我也鼓励您多玩玩,因为我相信您会发现适合自己的软件包。

新闻和更新

订阅我们的时事通讯,了解最新的网络搜索指南和新闻。

We care about the protection of your data. Read our <l>Privacy Policy</l>.Privacy Policy.

相关文章

缩图
指南如何抓取亚马逊产品数据:最佳实践与工具综合指南

通过我们的深入指南,探索刮擦亚马逊产品数据的复杂性。从最佳实践和亚马逊 Scraper API 等工具到法律注意事项,了解如何应对挑战、绕过验证码并高效提取有价值的见解。

Suciu Dan
作者头像
Suciu Dan
15 分钟阅读
缩图
指南Scrapy Splash 教程:掌握使用 Scrapy 和 Splash 抓取 JavaScript 渲染的网站的艺术

学习如何使用 Scrapy 和 Splash 抓取 JavaScript 渲染的动态网站。从安装到编写 spider、处理分页和管理 Splash 响应,本综合指南为初学者和专家提供了循序渐进的指导。

Ștefan Răcila
作者头像
Ștefan Răcila
6 分钟阅读
缩图
指南网络抓取 API 快速入门指南

开始使用 WebScrapingAPI - 终极网络搜索解决方案!收集实时数据,绕过反僵尸系统,享受专业支持。

米赫内亚-奥克塔维安-马诺拉什
作者头像
米赫内亚-奥克塔维安-马诺拉什
9 分钟阅读