Requests 库是网页抓取中下载网页 HTML 代码的常用工具。但你知道吗,它也可以用来下载和抓取其他类型的信息,例如图片。
本文将向你展示如何使用 Python 下载图片。它将涵盖三个库:Requests、urllib3 和 wget。此外,它还将展示如何使用代理隐藏你的 IP 地址,同时抓取图片。
使用 Requests 下载图片
如果你已经在使用 Requests 库来抓取网页,那么它也是下载图片的不二之选。Requests 是一个功能强大、广泛使用的 Python 库,用于发送 HTTP 请求和处理响应。
虽然 Requests 擅长从网页和 API 中获取数据,但它不能直接处理图片。不过,不要担心—Python 有内置的工具来解决这些问题。
要使用 Requests 下载图片,只需要:
- 使用 Requests 请求文件。
- 将响应的内容写入图片文件。
例如,如果你想从 Books to Scrape(一个网页抓取沙箱)下载一本书的封面,这是如何做到的。
首先,导入库。
import requests
然后,创建一个变量来保存要下载的图像的URL。
url = 'https://books.toscrape.com/media/cache/2c/da/2cdad67c44b002e7ead0cc35693c0e8b.jpg'
使用requests.get()请求图像。
res = requests.get(url)
最后,将其写入文件。
with open('img.jpg','wb') as f: f.write(res.content)
不过,您确实需要小心,不要在此方法中使用错误的扩展。例如,尝试将PNG文件写入JPG文件将导致文件不可读。
下面是解决这个问题的方法。如果您从页面获取URL,则可以从URL中提取文件名和/或扩展名,并将其用作下载文件的文件名。
def extract_name(url): file_name = url.split("/")[-1] return file_name with open(extract_name(url),'wb') as f: f.write(res.content)
这将确保文件内容与名称匹配。
为 Requests 使用代理
如果你使用脚本下载一两张图片,没人会注意。但是,如果你想下载大量图片,例如整个书籍封面集合,而不仅仅是一张,你需要小心。网站管理员通常不喜欢大规模的抓取活动,特别是当它涉及到加载大量元素,例如图片时。
为了避免被检测,使用代理是必不可少的。代理充当着你和你访问的网站之间的门户,允许你隐藏你的 IP 地址。
将代理添加到 Requests 请求中非常简单。你只需要一个代理提供商,我推荐使用如 Bright Data 和IPRoyal 之类的轮换住宅代理,因为它们可以为每个请求提供一个新的IP,使其快速设置和安全使用。
然后,在脚本中创建一个字典来保存代理链接。
proxies = { 'http': 'http://link-to-proxy.com', 'https': 'http://link-to-proxy.com' }
然后,您可以通过代理参数向requests.get()函数提供字典。
response = requests.get( url, proxies=proxies )
现在,您将能够下载图像而不会被网站所有者检测到。
下面是使用代理从网站下载图像的完整代码:
import requests def extract_name(url): file_name = url.split("/")[-1] return file_name proxies = { 'http': 'http://link-to-proxy', 'https': 'http://link-to-proxy' } url = 'https://books.toscrape.com/media/cache/2c/da/2cdad67c44b002e7ead0cc35693c0e8b.jpg' res = requests.get( url, proxies=proxies ) with open(extract_name(url),'wb') as f: f.write(res.content)
使用Urllib3下载图像
Urllib3 是 Python 的一个 HTTP 客户端库,与 Requests 库相似。实际上,Requests 库在其实现中使用了 urllib3。两个库非常相似,选择哪一个库通常取决于你已经在工作流程中使用的库。
如果你选择使用 urllib3 而不是 Requests,这里是使用它下载图片的方法:
首先,导入库:
import urllib3
然后,用您想要抓取的图像的URL创建一个变量。
url = 'http://books.toscrape.com/media/cache/2c/da/2cdad67c44b002e7ead0cc35693c0e8b.jpg'
之后,下载图像:
res = http.request('GET', url)
现在可以从URL中提取文件名并将其保存到文件中。
def extract_name(url): file_name = url.split("/")[-1] return file_name with open(extract_name(url),'wb') as f: f.write(res.data)
下面是完整的代码:
import urllib3 url = 'http://books.toscrape.com/media/cache/2c/da/2cdad67c44b002e7ead0cc35693c0e8b.jpg' res = urllib3.request('GET', url) def extract_name(url): file_name = url.split("/")[-1] return file_name with open(extract_name(url),'wb') as f: f.write(res.data)
为 Urllib3 使用代理
与使用 Requests 相似,使用 urllib3 下载图片时也需要使用代理来隐藏你的活动,以免被网站所有者发现。
不幸的是,使用 urllib3 的代理比使用 Requests 的代理要复杂一些。 特别是当你想使用授权代理时—这些代理需要你提供用户名和密码来访问它们。
要使用 urllib3 的授权代理,你需要三个东西:
- 代理提供商的 URL 和端口
- 用户名;
- 密码。
首先,使用urllib3.make_headers()函数生成代理授权的标头。将用户名和密码替换为您使用的实际用户名和密码。
default_headers = urllib3.make_headers(proxy_basic_auth='username:password')
然后,创建ProxyManager对象的一个新实例。它将确保所有请求都将使用代理。用仪表板中的详细信息替换代理主机和端口。
http = urllib3.ProxyManager('http://proxy-host:port', proxy_headers=default_headers)
现在您可以调用http对象上的.get()方法来使用代理连接到网站。
url = 'http://books.toscrape.com/media/cache/2c/da/2cdad67c44b002e7ead0cc35693c0e8b.jpg' res = http.request('GET', url)
剩下的代码和没有代理时一样:
def extract_name(url): file_name = url.split("/")[-1] return file_name with open(extract_name(url),'wb') as f: f.write(res.data)
下面是完整的脚本代码:
import urllib3 default_headers = urllib3.make_headers(proxy_basic_auth='username:password') http = urllib3.ProxyManager('http://proxy-host:port', proxy_headers=default_headers) url = 'http://books.toscrape.com/media/cache/2c/da/2cdad67c44b002e7ead0cc35693c0e8b.jpg' res = http.request('GET', url) def extract_name(url): file_name = url.split("/")[-1] return file_name with open(extract_name(url),'wb') as f: f.write(res.data)
使用 Wget 下载图片
Wget 是一个 Python 库,它封装了一个流行的 Linux 命令行工具,也名为 wget。使用该库,你可以下载各种文件(包括图片),并提供一个与 Python 代码无缝集成的友好界面。
如果你有一个文件的 URL,使用 wget 下载它非常简单。
首先,导入库。
import wget
然后,创建一个变量来保存图像的URL。
url = 'https://books.toscrape.com/media/cache/2c/da/2cdad67c44b002e7ead0cc35693c0e8b.jpg'
最后,在URL上运行wget.download()函数来下载图像。
wget.download(url)
为 Wget 使用代理
要了解如何通过代理运行 wget 请求,可以查看我们的 Wget 代理命令行教程。并且,要了解如何通过 Python 调用 CLI 工具,可以查看这篇文章。
那么,如果你是想下载某个网站的图标,方法就更简单了,你只需要使用免费在线工具,如 Favicon Extractor 即可一键获取。
常见问题
我无法打开使用 Python 下载的图片,该怎么办?
这个 bug 可能来自多种问题,但主要原因可能是你使用了错误的文件扩展名来保存图片。这将创建一个看似图像格式的文件,但实际上不可读,就像将文本文件重命名为 img.jpg 一样。
TypeError: ‘module'对象不可调用
如果你使用的是旧版本的 urllib3,不支持简洁的请求语法,这个错误可能会发生。要解决这个问题,可以升级库到最新版本或按照用户指南中描述的方式创建 PoolManager 来处理请求。
隧道连接失败:407 Proxy Authentication Required
这个错误意味着你在抓取时未能成功认证代理提供商。这是一个常见的问题,解决方法是按照我们的指导一步步使用 urllib3 的代理。
结 论
借助本文中描述的任意工具,在 Python 中下载图片都相对容易。 具体库的选择并不重要,所以最好选择你已经使用的工具。但是,如果你刚刚开始,我们推荐使用 Requests,因为它易于使用,并且在许多其他基于 Web 的 Python 任务中都非常有用。