Curl 使用总结
随着网络应用的盛行,HTTP脚本编程成为一项流行的技术。你可能需要到某个 web 页面自动的下载一些信息(采集),并且需要模仿成一个正常浏览器的样子,甚至需要上传或 POST 数据。而cURL就是HTTP脚本编程的利器。
###什么是cURL
cURL的官方网站上这样解释:“The name is a play on ‘Client for URLs’”。意思为“访问URL的客户端”。
“cURL is a command line tool for doing all sorts of URL manipulations and transfers”,cURL是用于进行各种对URL的操作和访问传输的命令行工具。 而在Linux man手册里这样解释:“cURL - transfer a URL”,意思是对URL的访问传输。通俗的讲,我们认为 cURL 是一个强大的对 URL 进行操作的命令行工具。 而 cURL 的写法,URL 突出大写,也正是强调对 URL 的操作。
###cURL主要特点
- 支持多协议
URL的定义为“统一资源定位符”(详见RFC 3986),是不局限于HTTP协议的。因此cURL支持多种协议,如DICT, FILE, FTP, FTPS, GOPHER, HTTP, HTTPS,IMAP, IMAPS,LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, TELNET and TFTP等。
- 命令行操作,简单强大
CURL是无GUI界面的,全部基于命令行操作,这无疑使它可以很方便的集成在像Linux脚本等程序中,而通过我们进一步编程处理,就可以完成非常强大的功能。
- 开源跨平台
cURL工具是由libcurl开源项目组提供,此项目组提供开源的libcurl库,此库是由C语言实现客户端 URL 操作库,提供对 URL 的访问等操作功能,cURL工具就是采用libcurl实现。而因为libcurl库是适用于多个平台的,因此cURL也适用于多个平台,如Win、Linux、OS/400、TPF等平台。这成为 cURL 比 GNU 官方的 wget 更强大的原因之一。
###curl命令格式:
curl [选项] [URL...]
-
-#/–progress-bar 查看下载进度条。
-
-O/–remote-name 下载并从url中提取文件名。 多个URL的情况同-o选项相同:
curl -O -O http://www.example.com/a.html http://www.example.com/b.html curl -O http://www.example.com/a.html -O http://www.example.com/b.html
两个URL分别保存在a.html和b.html中。
-
-C/–continue-at offset 断点续传。offset参数指定跳过多少bytes。
curl -# -O http://exmple.com/a.pdf
下载QQ安装程序,在下载未完成时Ctrl+C结束下载,然后使用
curl -# -C - -O http://example.com/a.pdf //“-C -”指定自动检测断点续传开始位置。
进行断点续传。可看到第二次下载时并不是重新下载,而是从上次结束的地方下载。
-
-r/–range range 分块下载,指定每块下载的字节范围。此选项适用于HTTP/FTP/SFTP及本地文件。如上例中下载qq,分块下载如下:
curl -r 0-10240 -o a.pdf http://example.com/p=ab.pdf //下载前10240bytes。 curl -r 10241-20480 -o b.pdf http://example/ao //下载10241-20480bytes。 curl -r 20481- -o qq.exe.part3 http://example/ 下载20481bytes及之后的字节。
下载完后可使用 cat a.pdf > qq.exe的形式得到完整文件(win下需要使用copy /b)。
-
–limit-rate speed 限速下载。默认单位为bytes/s,’k’或’K’指定使用单位KB/s,可以使用’m’或’M’指定使用单位MB/s,’g’或’G’指定使用单位GB/s。如
curl -# -O –limit-rate 100K http://example.com //指定限速为100KB/s。
限速是限制平均速度,某时刻的突发速度可能超过限制速度,但平均速度会低于限制速度。
如果同时使用了-Y/–speed-limit限制了最低下载速度,-Y/–speed-limit选择优先级更高。因此如果-Y /–speed-limit指定的值高于限制的速度,那么限制的速度回被突破,以保证最低下载速度有效(因为如果低于-Y/–speed-limit 指定的最低下载速度,下载会被取消)。
-
-y/–speed-time time -y指定超时时间,即低于最低速度多次时间时取消下载。
-
-Y/–speed-limit speed -Y指定最低速度而未指定超时时间时,超时时间默认为30。
-
-z/–time-cond date expression 只在更新时下载。
具体的时间格式请参考man 3 curl_getdate(这个只有在安装了libcurl开发库之后才有),或者 curl_getdate在线文档。如果时间格式解析失败,curl将会把此字段理解为文件名,从文件中读取时间。需要网页中有相关字段表明最后更新日期。
-
文件批量下载
curl -O http://10.1.1.3/{a,b}/[1-7].php
a/1.php-a/7.php会保存在当前目录下的1.php-7.php中。b/1.php-b/5.php如果也保存在当前目录下的 1.php-5.php的话,会覆盖以前的文件。因此curl会把b/1.php-b/5.php的内容在终端输出而不会保存文件。而执行:
curl "http://10.1.1.103/{a,b}/[1-7].php" -o "#1_#2.php"
则会使用“目录_文件”的形式命名文件,避免文件名冲突。
{}、[]类似于正则表达式中的语法,用以取得多个文件。#加数字的形式用以取得正则表达式的当前值。如 #1 表示第一个正则表达式的当前值,上例中即为{a,b}的值。
当下载http://10.1.1.103/a/1.php时,#1为“a”,#2为“1”,#1_#2.php即为“a_1.php”。从而完成批量文件的自动命名。
注
注意此时网址包含在双引号中,这是因为如果不被包含在引号中,{}中的内容无法使用#1的形式引用,会出现如下错误
internal error: invalid pattern type (0)
Warning: bad output glob!
-
-T, –upload-file file
使用HTTP的PUT方法上传文件,需要目标URL支持HTTP的PUT方法。可以与-d、–data-urlencode、-F同时使用。
上传一个文件: curl -u ftpuser:ftppass -T myfile.txt ftp://ftp.testserver.com
上传多个文件: curl -u ftpuser:ftppass -T “{file1,file2}” ftp://ftp.testserver.com
从标准输入获得文件内容: curl -u ftpuser:ftppass -T - ftp://ftp.testserver.com/myfile_1.txt 这个命令会将标准输入的内容保存在ftp://ftp.testserver.com/myfile_1.txt中。
-
-L, –location 有的网址是自动跳转的,curl就会跳转到新的网址。
curl -L www.sina.com
-
-i, –include 参数可以显示http response的头信息,连同网页代码一起。
curl -I www.sina.com
HTTP/1.1 301 Moved Permanently Server: nginx Date: Tue, 19 Aug 2014 15:44:21 GMT Content-Type: text/html Location: http://www.sina.com.cn/ Expires: Tue, 19 Aug 2014 15:46:21 GMT Cache-Control: max-age=120 Age: 4 Content-Length: 178 X-Cache: HIT from xd33-95.sina.com.cn
<html> <head><title>301 Moved Permanently</title></head> <body bgcolor="white"> <center><h1>301 Moved Permanently</h1></center> <hr><center>nginx</center> </body> </html>
-
-I, –head
curl -I www.sina.com
HTTP/1.1 301 Moved Permanently Server: nginx Date: Tue, 19 Aug 2014 15:44:38 GMT Content-Type: text/html Location: http://www.sina.com.cn/ Expires: Tue, 19 Aug 2014 15:46:38 GMT Cache-Control: max-age=120 Age: 31 Content-Length: 178 X-Cache: HIT from xd33-90.sina.com.cn
-
-v/–verbose 查看通信过程、调试。
这个参数可以清晰的查看到curl的通信过程,以便于调试,如执行:
curl -v http://www.sina.com 可以清晰的看到curl发出的HTTP请求及服务器返回的HTTP响应
以下所有命令都可以通过加入-v选项,查看具体通信过程。 更详细的调试信息可以使用–trace-ascii选项,如:
curl --trace-ascii debug.txt http://www.sina.com
curl --trace output.txt www.sina.com
####GET一个网页
curl http://www.example.com 网页源码将被打印出来。
-
-o/–output file 指定保存目录便于后续处理,我们将网页内容保存在文件中:
curl -o example.html http://www.example.com 此时仍会显示进度条等信息。
curl -o example.html http://www.example.com -o example1.html http://www.example1.com 可同时下载多个URL,每个-o对应一个URL
-
-s/–silent 静默模式
通过脚本结合curl可以实现很复杂的功能,而在脚本中调用curl,我们不需要进度条等信息。如执行:
curl -s -o adeploy.html http://www.adeploy.com 将不会显示任何信息。
- -A, –user-agent agent string 指定User-Agent字段
此选项字段用于指定HTTP请求头的User-Agent字段,即客户端(如浏览器)类型。很多网站为了防止自动化程序采集,仅允许浏览器访问,最简单的办法就是通过User-Agent字段识别客户端类型做出处理。而如下命令:
curl -A “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)” http://www.adeploy.com
“Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)”为firefox的UserAgent值。
通过-A指定User-Agent字段,使curl伪装成Firefox,从而绕过网站的检测。
User-Agent字段可以通过抓包分析得到,或者通过chrome的Developer Tools、Firefox的Firebug等工具得到。 而如果一个网站对浏览器的限制也很严格的话,那我们甚至可以通过修改User-Agent伪装成百度蜘蛛或者googlebot 突破限制,因为基于SEO的考虑,网站对搜索引擎蜘蛛的限制很小。
- -e/–referer URL 设置Referer
此选项字段用于指定 HTTP 请求头中的 Referer 字段,即来源网页。一个服务器端常用的限制方法, 就是检查http访问的referer。比如你先访问首页,再访问里面所指定的下载页,这第二次访问的referer 地址就是第一次访问成功后的页面地址。这样,服务器端只要发现对下载页面某次访问的referer地址不是 首页的地址,就可以断定那是个盗连了~~~~~
为了防盗链,很多网页尤其是图片等可下载资源会检测Referer字段,对于非自己站内的来源全部屏蔽掉,此时我们就需要这个参数。 通过执行:
curl -A "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" -e http://www.baidu.com http://www.adeploy.com
####POST
-X, –request command
curl -X POST www.example.com
curl -d "firstName=Kris" -d "lastName=Jordan" www.example.com
curl -X PUT -H 'Content-Type: application/json' -d '{"firstName":"Kris", "lastName":"Jordan"}' www.example.com
curl -X PUT -H 'Content-Type: application/json' -d @example.json www.example.com
-d, –data data
指定HTTP请求时发送的数据(主要为POST请求),使用和用户通过浏览器提交表单时一样的方式。
使用的content-type是application/x-www-form-urlencoded。
相当于-data-ascii。发送纯粹二进制的数据(data purely binary),需要使用–data-binary。
URL-encode编码要发送的数据,需要使用–data-urlencode。
当有多个-d时,curl会自动将发送的数据段是用“&”符号拼接,如:-d name=Adeploy -d age=100
将自动拼接为name=Adeploy&age=100作为post数据块(post chunk)发送。
如果想指定文件中的内容,可以使用-d @filename的形式。如文件foobar中内容为name=Adeploy,
使用-d @foobar即可达到-d name=Adeploy一样的效果(只有第一个=作为特殊字符)。从文件读入
时要注意=、@等特殊字符的异常情况。
而-d @-可以指定要发送的内容来自标准输入(stdin)。如执行curl -d @- http://127.0.0.1/welcome.php,
在终端输入数据后回车、Ctrl+D后达到相同效果。
对于文件的使用,对于其他类似选项适用。
但-d/–data不会对数据进行url编码,而实际场景中我们最常用的还是发送url编码后的数据。
curl --data "data=xxx" example.com/form.cgi
–data-urlencode data
使用URL-encode编码要发送的数据。除此之外,其余同-d。-d选项默认是不会对要发送数据进行编码的,
在旧版本没有–data-urlencode选项的curl时,要发送编码的数据,必须手动对数据进行编码,或者将数
据存放在编码的文件中。比如要发送数据为”Adeploy blog”,必须手动把空格变为”%20″:
curl -d name=Adeploy%20blog -d age=100 http://127.0.0.1/welcome.php
而–data-urlencode自动完成此过程:
curl –data-urlencode name=Adeploy blog –data-urlencode age=100 http://127.0.0.1/welcome.php
curl --data-urlencode "date=April 1" example.com/form.cgi
在我们的程序中,直接使用-d发送需urlencode编码的数据(一般为除字母数字外的其他字符,如空格,汉字等),
程序也会正常处理,那我们为什么还需要使用–data-urlencode呢?
原因如下:
1)能正常处理是apache服务器的原因。实际使用中服务器、程序语言不同,很可能出现无法处理不urlencode编码
的数据,尤其是汉字和jsp程序,容易出现乱码
2)我们在使用浏览器操作时,浏览器会自动进行urlencode操作。为了尽可能逼真,我们使用–data-urlencode尽
可能模仿浏览器的操作
–data-urlencode同样可以使用@指定从文件中输入。而且可以使用name@filename的形式。如使用–data-urlencode
name@foobar,文件foobar中内容为Adeploy,即可达到–data-urlencode name=Adeploy的效果。这在-d选项中是
不行的。需要注意的是此用法不会对name进行编码,所以需要预先编码好name字段。实际场景中一般name字段都是
固定的,so it’s not too much trouble.
–data-binary data
发送指定的不做任何处理的数据(This posts data exactly as specified with no extra processing whatsoever),其余同-d。
-F, –form name=content
1. 一般使用-F file=@filename的形式,其中file为文件表单的name,filename为文件名。@后面的文件作为文件上传处理。
curl --form upload=@localfilename --form press=OK [URL]
<form method="POST" enctype='multipart/form-data' action="upload.cgi">
<input type=file name=upload>
<input type=submit name=press value="OK">
</form>
curl -F "firstName=Kris" -F "publicKey=@idrsa.pub;type=text/plain" www.example.com
{
"method": "POST",
...
"headers": {
"content-length": "697",
"content-type": "multipart/form-data;
boundary=----------------------------488327019409",
... },
"body": "------------------------------488327019409\r\n
Content-Disposition: form-data;
name=\"firstName\"\r\n\r\n
Kris\r\n
------------------------------488327019409\r\n
Content-Disposition: form-data;
name=\"publicKey\";
filename=\"id_rsa.pub\"\r\n
Content-Type: text/plain\r\n\r\n
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAkq1lZYUOJH2
... more [a-zA-Z0-9]* ...
naZXJw== krisjordan@gmail.com\n\r\n
------------------------------488327019409
--\r\n",
}
2. 对于 < 后的文件,curl 会读取其内容,而不会作为文件上传。类似 -d 选项中 @ 的作用。
curl -F name=<foobar.txt -Fage=100 http://127.0.0.1/welcome.php
foobar.txt内容为Adeploy,则此命令与以下命令等价:
curl -F name=Adeploy -Fage=100 http://127.0.0.1/welcome.php
而-F @foobar.txt表示将foobar.txt作为文件上传。
3. -F不进行url编码
-F与-d类似,都是不对数据进行urlencode编码,而且-F不能与-d或–data-urlencode共用。
因此如果上传文件的同时还需要提交其他需要urlencode编码的字段(如中文用户名),就会出现问题。
除手动编码外,实用的解决办法是自己编写urlencode函数(网上可以找到Linux脚本实现的urlencode
函数或C语言版本、Perl版本、Python),调用即可。
4. 使用\"type=\"指定Content-Type
如curl -F “web=@index.html;type=text/html” url.com
将index.html以text/html的Content-Type上传。
-form-string name=string
基本同-F,但是此参数后面跟”@”、”<”、”;type=”时,不做特殊含义解析。
-H, –header header
curl -H "Accept: application/json" -H "Authorization: OAuth 2c3455d1aeffc" http://sina.com
-G/–get
和-d/–data、–data-binary一块使用时,表示强制使用GET的方式提交表单。
和 -I/–head 一块使用时,表示把提交的数据加在url中,而不是加在数据头中。
###cookie使用
cookie的形式就是 “属性:值” 对形式,-b 后可直接以“属性=值”的形式给出cookie,当有多个属性时以分号间隔且包含在双引号中。如执行:
curl -A "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" -b "user=Adeploy;pass=password" http://www.adeploy.com
会将 cookie 信息 user=Adeploy;pass=password 附加在HTTP请求头中。
我们登录网站后,为保持登录状态,需要使用cookie信息。
- -D/–dump-header file 保存协议头部信息
头部信息中包含最常使用的cookie信息,如执行:
curl -A "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" -e http://www.baidu.com -D header.txt http://www.adeploy.com
会将头部信息保存至 adeploycookie.txt 中。
- -b, –cookie name=data 指定cookie
-b 后可直接加 -D 保存的文件,curl 会自动从中读取出 cookie 值,而且 -b 选项不会修改此文件。如执行:
curl -A "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" -e http://www.baidu.com -b header.txt http://www.adeploy.com
会自动将adeploycookie.txt中cookie信息附加至HTTP请求头中。因此,结合-D和-b参数,即可完成cookie的保存和后续使用。
###Redirects重定向
打开某些网页,网页会显示“ 3XX Moved Permanently ”,即网页被移动到其他位置,新位置一般由HTTP响应头中的 Location 字段给出。 重定向一般是因为网站结构调整后,避免用户访问原来页面出现404错误。 而另一类常见的用法就是在登陆成功后,网页显示成功信息,然后将用户重定向至内容页面。
- -L/–location 选项可以自动跟踪重定向
####认证相关选项
-E/--cert <certificate[:password]>
--cert-type <type>
--cacert <CA certificate>
--capath <CA certificate directory>
-k/--insecure
--key <key>
--key-type <type>
--proxy-anyauth
--proxy-basic
--proxy-digest
--proxy-negotiate
--proxy-ntlm
####代理选项
--socks4a <host[:port]>
--socks4 <host[:port]>
--socks5 <host[:port]>
--socks5-hostname <host[:port]>
--socks5-gssapi-service <servicename>
--socks5-gssapi-nec
-x/--proxy <proxyhost[:port]>
-U/--proxy-user <user:password>
curl -x proxy.xxx.com:8080 -U username:password -e http://www.ip138.com/ http://iframe.ip138.com/city.asp
curl -x 'http://username:password@proxy.xxx.com' -e http://www.ip138.com/ http://iframe.ip138.com/city.asp
###wget VS cURL
####相同点
* 可通过FTP/HTTP/HTTPS协议下载文件的命令行工具;
- 可以发送HTTP POST请求;
- 支持cookie的使用;
- 被设计为无界面(UI),可在如脚本中使用;
- 开源且免费的软件。
####不同点
curl
- curl是基于libcurl库实现,因此特性来源于libcurl库。libcurl库跨平台、开源且免费,因此curl不只是一个命令行工具
- 管道。curl在传统的UNIX风格的基础上加以扩展,对输入输出做出更多的处理,从而贯彻了”everything is a pipe” 的设计思想。
- 单点传送(Single shot)。curl被设计为用于数据的单点传送。它只会传送用户指定的URLS,并不包含任何递归下载的逻辑,也不对html进行任何解析。
- 更多协议支持。目前curl 支持的协议有: FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, LDAP, LDAPS, FILE, POP3, IMAP, SMTP 和 RTSP 。Wget仅仅支持 HTTP, HTTPS 和 FTP。(协议的支持情况可能会随着时间发展而变化。)
- 更多平台支持,便于移植。与wget相比,curl可在更多平台上编译和运行。比如OS/400, TPF 和其他很多非UNIX的平台。
- 更强大的SSL库和SSL支持。curl能应用于多个不同的 SSL/TLS 库, 并提供了更多的可控性和对协议细节更广泛的支持。
- curl支持更多的HTTP认证方式。尤其是当你使用HTTP代理的时候,curl支持Basic, Digest, NTLM and Negotiate认证方式(参见HTTP认证模式)。
- libcurl库支持多种不同的SOCKS代理,基于libcurl实现的curl工具也支持。而wget不支持。
- 双向通信。 curl 提供了上传能力,Wget仅仅支持HTTP POST方式。
-
HTTP multipart/form-data 的发送能力。 这使得用户可以进行HTTP上传,更好的模拟浏览器的行为从而更大程度的实现HTTP操作的自动化,提供了更多操作的可能。
- 压缩。 curl 支持GZIP和 inflate Content-Encoding 并且自动进行解压缩操作。
- curl提供并执行Transfer-Encoded HTTP的解压缩,而wget不会
- curl在7.27.0之后,提供对metalink的支持(好吧,百度百科对metalink的解释是不对的, 百度百科说的是oracle公司的一个服务)。而wget需要依靠一个Google Summer开源项目才能支持metalink。
wget
- wget仅仅是一个命令行工具。没有库提供使用。
- 递归下载支持。wget相比curl最大的优点在于对递归下载的支持,甚至下载一个资源如网页或FTP目录指向的所有资源。
- 下载时无需指定保存文件名。而curl需要使用-o或-O指定。
- 仅支持GnuTLS 和 OpenSSL两种SSL库。
- 仅支持HTTP代理的基本认证(Basic auth)。
- 不支持SOCKS代理。
- 项目更老,基于GPL开源协议,隶属GNU项目。curl基于MIT开源协议,不隶属于任何组织,版权由作者一人所有。
参考
http://curl.haxx.se/docs/httpscripting.html