cURL是命令行网络数据传输的主力工具。它支持HTTP、HTTPS以及众多其他协议,几乎每台您接触到的机器上都预装了它,因此当工程师需要检查端点、测试API或拉取页面时,它是第一个被想到的工具。GET方法是这一切的核心:这是您向服务器请求资源并读取返回内容的方式。

本指南是一篇关于如何使用cURL发送GET请求的专项演练。您将从最基本的命令开始,逐步叠加查询参数、请求头、重定向、JSON处理,以及让您清楚看到服务器实际返回内容的各种标志。读完之后,您将掌握足以应对真实调试和小规模抓取任务的cURL技能,以及了解原始GET请求力不从心的边界所在。

GET请求究竟做了什么

GET是最简单也是最常见的HTTP方法。当您在浏览器中打开一个URL,浏览器会向服务器发送一个GET请求,服务器随即回复该资源:HTML、图片、JSON载荷,或该地址上存在的任何内容。GET只做读取。它不像POST或PUT那样发送请求体来创建或修改任何东西,这使它成为获取页面、调用只读API端点和拉取静态资源的正确方法。

cURL默认使用GET,因此对于普通的获取请求,您无需指定方法。最短的请求就是程序名后跟一个URL:

bash
curl https://httpbin.org/get

这会将响应体打印到您的终端。httpbin.org是一个免费的请求检查服务,它会回显它接收到的所有内容,非常适合学习:下面所有示例都使用它,这样您可以运行命令,亲眼看到cURL发送了什么。如果您想明确指定方法,-X GET--request GET可以写出来,但对于普通GET请求,这是多余的。

传递查询字符串参数

大多数真实的端点都需要参数。查询字符串是URL中?之后的部分,以key=value对的形式写出,用&连接。最直接的传递方式是将它们直接放在URL中,用引号括起来,防止Shell将&解读为后台任务:

bash
curl 'https://httpbin.org/get?city=Berlin&page=2'

单引号很重要。没有它们,Shell会看到&并分割命令,因此对于任何包含&?或空格的URL,务必加上引号。

cURL也可以通过-G-d为您拼装查询字符串。-d标志通常用于构建POST请求体,但加上-G后,cURL会将该数据作为GET查询字符串附加到URL上:

bash
curl -G \
  -d "city=Berlin" \
  -d "page=2" \
  https://httpbin.org/get

两条命令发送的是同一个请求。当您有多个参数或在脚本中生成它们时,-G形式可读性更好,因为每对参数独立成一个标志,无需手动拼接?key=value&key=value字符串。

URL编码参数值

普通的-d不做任何编码,因此包含空格、&符号或斜杠的值会破坏查询字符串。当值尚未安全时,结合-G使用--data-urlencode。cURL会为您编码该值,并将其作为查询参数附加:

bash
curl -G \
  --data-urlencode "q=web scraping & data" \
  --data-urlencode "sort=date desc" \
  https://httpbin.org/get

在回显的响应中,您会看到空格变成了%20,&符号变成了%26,这正是服务器所期望的格式。每当值来自用户输入或包含字母、数字和基本标点以外的内容时,请使用--data-urlencode。它能让您避免日后追查那些难以发现的编码错误。

添加请求头

请求头携带关于您请求的元数据:您接受哪种内容类型、您声称的用户代理、授权令牌等等。-H标志每次设置一个请求头,您可以根据需要重复使用多次:

bash
curl \
  -H "Accept: application/json" \
  -H "User-Agent: my-script/1.0" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  https://httpbin.org/headers

/headers端点会回显它接收到的每个请求头,您可以确认cURL发送的内容完全符合预期。设置一个真实的User-Agent和明确的Accept头,也是让自动化请求看起来不像默认cURL脚本的第一小步,当您开始抓取真实站点时,这一点便显得至关重要。关于请求头处理的深度解析,请参阅如何使用cURL发送HTTP头

将响应体保存到文件

默认情况下,cURL将响应流输出到标准输出。要将其写入文件,请使用-o加上您选择的文件名,或使用-O复用URL中的远程文件名:

bash
# write to a name you pick
curl -o page.html https://httpbin.org/html

# keep the remote filename
curl -O https://httpbin.org/image/png

当服务器的文件命名合理时,使用-O;当您希望控制字节落地位置时,使用-o。在编写脚本时,添加-s(静默)以抑制进度计,并添加-f(失败)以使cURL在HTTP错误时返回非零退出码,而不是欣然保存一个错误页面。

查看响应头和状态码,而非仅看响应体

在调试时,响应体往往是最不有趣的部分。cURL提供了几种检查响应元数据的方式。-i将响应头添加在响应体之前,-I发送HEAD请求并只显示响应头,-D -将响应头转储到指定目标(这里-表示标准输出),而响应体则发往-o指定的地方:

bash
# body with headers on top
curl -i https://httpbin.org/get

# headers only (HEAD request)
curl -I https://httpbin.org/get

# headers to stdout, body to a file
curl -D - -o body.html https://httpbin.org/html

当您只关心内容类型、内容长度、缓存头或状态行等元数据,而不想下载整个载荷时,请使用-I。这是在下载前快速确认资源是否存在或其类型的便捷方式。

跟随重定向

服务器经常以301或302重定向响应GET请求,将您指向其他地址。cURL默认不跟随重定向,因此对一个会重定向的URL发出裸请求,返回的是简短的重定向响应,而非最终页面。添加-L(location)让cURL追踪重定向到其目的地:

bash
curl -L "https://httpbin.org/redirect-to?url=https://httpbin.org/get"

不加-L,您得到的是重定向本身;加上之后,您得到的是最终URL处的内容。如果您想限制cURL跟随的跳数,添加--max-redirs加上一个数字,防止重定向循环无限运行。

打印状态码和耗时

对于健康检查和脚本,您通常只需要一个具体数据,比如HTTP状态码或请求耗时,而不是整个响应。-w(write-out)标志在传输完成后打印所选变量。配合-o /dev/null丢弃响应体,并配合-s保持安静:

bash
# just the status code
curl -s -o /dev/null -w "%{http_code}\n" https://httpbin.org/get

# status plus total time in seconds
curl -s -o /dev/null \
  -w "status=%{http_code} time=%{time_total}s\n" \
  https://httpbin.org/get

第一条命令打印类似200的内容,仅此而已,非常适合Shell条件判断或监控定时任务。其他有用的-w变量包括%{size_download}%{num_redirects}%{url_effective},最后一个在您想看到一串重定向最终落在哪里时非常方便。

处理JSON API响应

许多GET端点返回JSON。要表明您需要JSON,设置Accept头,并将cURL的输出通过管道传给jq(命令行JSON处理器),以便舒适地阅读结果。jq会美化打印载荷,并允许您用一种小型查询语言选取字段:

bash
# pretty-print the whole JSON response
curl -s -H "Accept: application/json" https://httpbin.org/get | jq .

# pull a single field out of the response
curl -s https://httpbin.org/get | jq '.headers["User-Agent"]'

在使用管道时,-s标志至关重要:它去除进度计,使进入jq的只有干净的JSON。从那里,您可以精确提取所需的值,这使cURL加jq无需编写任何程序代码,就成为了一个快速、可脚本化的API客户端。

用于调试的详细模式

当一个请求表现出您无法解释的行为时,-v(详细)会展示完整的交互过程:DNS和TLS握手、cURL发送的精确请求行和请求头(前缀>),以及收到的响应状态和响应头(前缀<):

bash
curl -v https://httpbin.org/get

详细输出是解答"我的请求头究竟有没有被发出去?"或"这个重定向去哪里了?"这类问题的最快方式。如果您需要捕获原始字节用于错误报告,--trace-ascii trace.txt会将更详细的日志写入文件。

一个实用的思维模型

将GET请求分为两个层次来思考。第一层是发送什么:URL、查询参数和请求头。第二层是看到什么:响应体、响应头、状态码和耗时。上面几乎每一个cURL标志都属于这两层之一,这使得长长的选项列表变得容易记忆。

原始GET力不从心的地方

GET请求是网络爬虫的基础:拉取一个页面,从根本上说,就是发送一个GET请求并读取返回的HTML。对于静态页面和友好的API,cURL独挑大梁绰绰有余。当您将它指向现代商业网站时,障碍很快就会出现。两个限制一下子就能感受到。

首先,cURL只获取原始HTML,其余什么都不做。它不运行JavaScript,因此任何在浏览器中构建内容的页面都会给cURL一个几乎空白的外壳。其次,不希望机器人访问的网站会监控爬虫形态的流量:默认的User-Agent、数据中心IP,以及来自同一地址的突发请求,在您收集到任何有用内容之前,往往就会遭遇挑战或被封锁,通常是CAPTCHA的形式。您可以通过轮换IP和自行渲染页面来解决一部分问题。请参阅cURL用于网络爬虫如何使用带代理的cURL了解这些技术,但维护一套无头浏览器集群和健康的代理池很快就会占据大部分工作量。

Crawlbase Crawling API

当普通GET请求遭遇JavaScript渲染或反机器人封锁时,Crawling API将渲染、住宅IP轮换和CAPTCHA处理折叠进一次请求。您用令牌和目标URL发送一个GET请求,它在受信任IP背后渲染页面并返回处理好的HTML供您解析。同样的cURL技能直接延伸适用。先在免费层试试。

因为该API接受普通GET请求,您现有的cURL知识可以直接映射过来。您用两个查询参数(您的令牌和目标URL)调用其端点,渲染后的HTML便在响应体中返回:

bash
curl -G https://api.crawlbase.com/ \
  --data-urlencode "token=YOUR_CRAWLBASE_TOKEN" \
  --data-urlencode "url=https://www.example.com"

这与前面提到的-G--data-urlencode模式相同,这也是为什么正确编码至关重要:目标URL本身是查询字符串中的一个值,因此必须被干净地编码。当目标采用客户端渲染时,换用JavaScript令牌代替普通令牌,API便会在真实浏览器中运行页面,再返回HTML。

回顾

核心要点

  • GET是默认方法。 curl URL发送的就是GET请求,对于普通获取请求无需指定方法;-X GET是可选的。
  • 参数两种传法。 用引号将参数括在URL中,或用-G-d构建,当值包含空格或特殊字符时,改用--data-urlencode
  • 控制您看到的内容。 -H设置请求头,-o-O保存响应体,-i-I-D显示响应头,-w打印状态码和耗时。
  • 跟随并检查。 添加-L跟随重定向,将JSON管道传给jq,在需要调试完整交互时使用-v
  • 了解边界所在。 原始GET无法渲染JavaScript,大规模爬取时会被封锁;Crawling API接受同样的GET格式,返回渲染后、未被封锁的HTML。

常见问题

使用cURL发送GET请求需要指定方法吗?

不需要。cURL默认使用GET,因此curl https://example.com已经发送了一个GET请求。如果您想明确写出来,可以写curl -X GET https://example.com,但对于普通获取请求,这没有任何区别。只有当您需要不同的方法时才需要-X,比如-X POST-X DELETE

如何在cURL GET请求中传递查询参数?

两种方式。直接将参数放在引号括起的URL中,如curl 'https://example.com/data?a=1&b=2',或让cURL构建查询字符串,如curl -G -d "a=1" -d "b=2" https://example.com/data。两者发送的请求相同。如果任何值包含空格、&符号或其他特殊字符,将-d标志改为--data-urlencode,以便cURL正确编码它们。

如何只查看HTTP状态码?

使用write-out标志并丢弃响应体:curl -s -o /dev/null -w "%{http_code}\n" https://example.com-s隐藏进度计,-o /dev/null丢弃响应体,-w "%{http_code}\n"只打印数字状态码。这是健康检查和Shell条件判断的标准单行命令。

为什么cURL不跟随重定向?

cURL不会自动跟随重定向,除非您明确要求。当服务器返回301或302时,普通请求显示的是简短的重定向响应,而非目的地内容。添加-L(或--location),cURL就会跟随重定向到最终URL。使用--max-redirs限制它追踪的最大跳数。

如何用cURL获取并读取API的JSON响应?

设置Accept头并将输出管道传给jq。例如,curl -s -H "Accept: application/json" https://example.com/api | jq .会美化打印载荷,jq '.field'提取特定值。-s标志防止进度计混入管道,确保进入jq的只有干净的JSON。

我能用cURL GET请求抓取JavaScript密集的网站吗?

不能直接实现。cURL只获取原始HTML,不运行JavaScript,因此在浏览器中渲染内容的页面几乎是空的,而且反机器人系统很快就会封锁默认的cURL流量。要处理这类目标,请通过Crawling API等渲染服务发送GET请求,它在轮换住宅IP背后的真实浏览器中运行页面,并将处理好的HTML返回给您解析。

开始构建

大规模爬取任何站点,无需与基础设施对抗。

Crawlbase 负责处理代理、指纹和 CAPTCHA,让你的团队专注于交付数据流水线,而非维护爬取管道。1,000 次请求免费,无需信用卡。

自助开通 · 无需销售通话 · 提供企业级爬取量