Curl一个功能非常强大的命令行工具,支持HTTP、FTP等协议,但是自从打算学习CURL以来,一直未能找到详细的CURL教程,使得学习比较困难,因此大程哥想写一篇关于CURL学习的详细中文教程,以访问dachengge.com为示例,供大家学习使用。教程参考CURL官网的Document和Man pages,希望对大家有帮助:
1 HTTP脚本
1.1 背景
本文假设读者有最基本的HTML和网络知识。随着大量的应用转移到网络,使得HTTP脚本越来越多地被访问和使用,自动地从网站获取信息、仿冒用户、向网站提交或者上传数据现在变成了非常重要的任务。
CURL是一个非常有用的工具,能够进行各种URL操作和数据的传输,但是本文只关注如何进行HTTP请求,如果你想对CURL有一个大概的了解,可以使用下面的命令:curl –help或curl –manual。
1.2 HTTP协议
HTTP协议用于从web服务器上读取数据,它是基于TCP/IP协议上的一个简单的协议。该协议同时也能够让你通过使用一些不同的方法向服务器提交数据。
HTTP协议是向服务器发送的要进行一个特殊操作的ACSII文本,随后在要求的内容发送给客户端之前,服务器会向客户端发送几行回应的数据。
客户端CURL向服务器发送一项请求,请求通常包括方法(比如GET、POST、HEAD等等)、一些请求的头、有时还有请求正文。接到请求后,服务器返回状态行(表明访回是否顺利)、回应头和内容正文。正文是客户要求的数据,通常是一些HTML资源、图片。
1.3 通过CURL观察HTTP协议
使用CURL的参数-v,–verbose,会显示出CURL向服务器发送的命令和其它的一些信息。–verbose是一个非常有用的命令,尤其是当你想调试或者了解CURL和服务器交互过程的时候。
向服务器发送命令:
curl –verboses dachengge.com
服务器返回在的结果,不含正文:
* Connected to dachengge.com (119.10.36.34) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: dachengge.com
> Accept: */*
>
< HTTP/1.1 200 OK
如想知道更多的细节,可以使用–trace-ascii 跟要输出的文件,这样它会把跟服务器通信的详细细节存入该文件。另外,如果想知道所有的过程发生的时间可以使用–trace-time。
使用CURL访问dachengge.com,将通信的细节和时间存入result.txt文件中:
curl –trace-ascii result.txt –trace-time dachengge.com
1.4 观察返回结果
默认CURL会把结果输出到STDOUT,可以使用-o,-O或重定向将返回结果保存到文件中:
将结果保存到 result.txt:
curl -o result.txt dachengge.com
curl dachengge.com > result.txt
将结果以原文件名保存:
curl -O dachengge.com/index.php
2 URL
2.1 URL规则
URL(统一资源定位符)用来描述Internet上一个资源详细地址的规范,大家可能看到过很多次这样的地址,比如www.baidu.com,www.dachengge.com,j定义这个规范最权威的标准是RFC 3986。
2.2 主机
主机名称通常由DNS或/etc/hosts文件来解析成一个IP地址,然后CURL进行访问。当然你也可以直接使用CURL访问这个IP地址。比如你使用CURL访问dachengge.com,实际上是访问这个主机对应的IP地址119.10.36.34。当然用于开发或者其它需要(有很多域名主机对应好几个空间,IP地址也不同),你也可以指这个主机的IP地址,使用–resolve 参数,例如:
curl –resolve dachengge.com:80:123.123.123.123 dachengge.com
2.3 端口
每一个CURL支持的协议都是运行在特定的端口上,通常情况下不用端口的问题,除非进行网站的测试,而使用不同的端口,这是可以使用不同的端口,使用的方法是,在网站域名后面家一个端口号,用冒号隔开,例如:
curl http://dachengge.com:80/
如果使用代理服务器时,也可以指定代理服务器的端口号:
curl –proxy http://abc.com:80 http:dachengge.com/
2.4 使用账号和密码
有时有些服务需要HTTP认证,当访问这些网站时需要提供账号和密码,这是你需要在URL里面提供账号密码,或者单独提供:
CURL http://user:password@example.com/
CURL -u user:password http://example.com/
注意,上面讲的认证方式比较传统,如下图所示,现在认证的方式比较多,比如form,cookie,后面会讲到:
3 获取一个页面
3.1 GET方法
最简单、最常用的HTTP请求就是获取一个URL资源,这个URL资源可以是一个页面、图片、文件。客户端发出一个GET请求,服务器根据请求返回要求的文档。例如客户端发出下面的命令:
CURL http://dachengge.com
终端会将从服务器获得的内容(通常是整个HTML文档)显示出来,所有的HTTP返回结果都包含一系列返回头,通常都是隐藏的,如果要显示的话,使用CURL的–include参数(-i)将这些头信息和整个文档一起显示出来。
3.2 头
有时,你也可以只向服务器请求HEAD头,不需要正文,CURL对应的参数是–head(-L),有些情况下,服务器会拒绝HEAD方法,但是其他内容能正常显示。
3.3 一个命令发出多个URL请求
一句CURL命令可以包括一个或多个URL地址,通常情况下都是一个URL,但是你可以指定无数个,没有限制。
CURL a1.dachengge.com a2.dachengge.com
如果使用–data向服务器POST数据时,会向多个URL发送数据:
CURL –data name=value a.dachengge.com a2.dachenge.com
3.4 一个CURL命令包含多个HTTP方法
有些情况下,你需要在一句CURL命令里面向不同的URL地址发出不同的HTTP请求。这是可以使用–next参数,它能将不同的请求隔开,所有–next之前的部分使用相同的方法。
下面的命令是先请求一个HEAD头,然后发出GET请求:
CURL -I dachengge.com –next dachengge.com
先发出POST请求,然后GET:
CURL -d name=value dachengge.com –next dachengge.com/result.txt
4 HTML FORM
4.1 表单概述
表单是一个HTML页面使用各种输入数据的区域组成的,用户可以录入数据,然后点击提交向服务器提交数据的常用方法。服务器收到数据后,根据提交的数据来决定如何向客户端回应,就像向数据库提交查询,然后数据库根据提交的查询关键字返回查询结果。向服务器提交数据的方法有两种:GET和POST方法:
4.2 使用GET方法的表单
HTML中使用GET方法提交数据的页面是这样的:
<form method=”GET” action=”junk.cgi”>
<input type=text name=”birthyear”>
<input type=submit name=press value=”OK”>
</form>
如果对浏览器熟悉的话,上面的代码就会显示成,一个文本框和一个OK按钮。这是填入1905,然后点击“OK“,浏览器就会生成一个新的URL地址,URL会将”junk.cgi?birthyear=1905&press=OK“添加到之前的URL地址后面。如果之前表单页面地址是 “www.hotmail.com/when/birth.html”,在表单上填写1905,点击OK按钮后,随之打开的页面会变成 “www.hotmail.com/when/junk.cgi?birthyear=1905&press=OK”。要使用CURL程序用GET方法提交数据,直接将数据放在ACTION指向的页面(以前面的表单为例):
curl “http://www.hotmail.com/junk.cgi?birthyear=1905&press=OK”
4.3 使用POST方法的表单
GET方法将所有的输入域名称和值都放在URL地址里面,如果能通过值来做某些页面的书签(例如www.abc.com/index.php?id=18保存成书签可以直接访问),GET通常是个好办法,但是如果输入的数据是保密的或者有大量的数据要输入时,会产生一个非常长的URL地址。下面是一个使用POST方法的表单:
<form method=”POST” action=”junk.cgi”>
<input type=text name=”birthyear”>
<input type=submit name=press value=” OK “>
</form>
CURL命令使用POST方法提交和上面相同的数据,就会使这样:
curl –data “birthyear=1905&press=%20OK%20” http://www.example.com/when.cgi
注意,OK前面和后面的%20是空格,使用了urlencode编码,POST方法的Content-Type通常是application/x-www-form-urlencoded。通过POST方法向服务器发送的数据必须被编码,新版本的CURL使用–data-urlencode编码,前面的空格变成%20就是这个道理。
curl –data-urlencode “name=I am Daniel” http://www.example.com
如果在一个命令行里面多次使用–data参数,CURL会将所有–data后面的数据使用&拼接起来。
4.4 文件上传提交
在1995年,他们定义另外一种HTTP提交数据的方法,这种方法在RFC 1867中有描述。这种方法设计得能更好地支持文件上传,假设文件上传的表是这样的:
<form method=”POST” enctype=’multipart/form-data’ action=”upload.cgi”>
<input type=file name=upload>
<input type=submit name=press value=”OK”>
</form>
从encType是上可以看出,将要发送的数据类型是multipart/form-data,即文件类型。通过CURL向服务器传递数据的命令如下:
curl –form upload=@localfilename –form press=OK [URL]
4.5 隐藏域
另外一种HTML传递数据的方法是隐藏,隐藏域的数据已经设置好了,但是在页面上不显示,在传递数据方面,跟其它文本域没有区别。
<form method=”POST” action=”foobar.cgi”>
<input type=text name=”birthyear”>
<input type=hidden name=”person” value=”daniel”>
<input type=submit name=”press” value=”OK”>
</form>
那么,通过CURL传递数据的方法就是:
curl –data “birthyear=1905&press=OK&person=daniel” [URL]
5 更多的HTTP头
5.1 Referer
一个HTTP请求可能包括一个referer域,用来告诉服务器这个请求从哪个URL发起,有很多程序和脚本都检查referer确定这个请求不是从外部或未知的页面发起。使用CURL设置REFERER访问网页:
curl –referer www.abc.com http://www.dachengge.com/
5.2 用户代理
像REFERER域一样,所有的HTTP requests会包含User-Agent域,它用来描述用户使用的是什么样的浏览器,网站的程序员通过判断不同的浏览器类型以显示不同的内容,达到最好的效果。
使用CURL模仿IE访问网站:
curl –user-agent “Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)” [URL]
使用CURL模仿Linux访问网站:
curl –user-agent “Mozilla/4.73 [en] (X11; U; Linux 2.2.15 i686)” [URL]
6 网页跳转
6.1 location 头
当向服务器发出请求时,从服务请返回的可能包含一个提示所访问资源的地址,Location头包含这个信息,CURL不会自动打开这个跳转的地址,只是将Location头跟正文一起显示,让CURL自动打开Location头指向的跳转地址,使用–location参数。例如访问www.sina.com时,会自动跳转到www.sina.com.cn:
curl –location www.sina.com
注意有些页面会新设置cookie,然后再用这个新的cookie跳转,因此像这样的页面不能使用该参数,必须打开第一个页面记录下新的cookie,然后再用这个新的cookie打开第二个页面。
7 Cookies
7.1 Cookies基础
浏览器通过使用Cookie来记录客户端的状态,并向服务器发送。Cookies是键=》值对应的形式,服务器向客户端发送cookies的到期时间和其他一些属性。
很多应用使用Cookies连接服务器,并进行一系列操作,完成一个会话。CURL要是完成这样的操作,就必须保存Cookies。
7.1 Cookies选项
最简单发送Cookies的方法就是向服务器发送请求的同时加上这些数据:
curl –cookie “name=Daniel” http://www.dachengge.com
Cookies像其他HTTP头一样发送,这对于CURL记录这头非常有用,使用–dump-header记,将HEADER和Cookies存在文件里:
curl –dump-header headers_and_cookies www.dachengge.com
如果只记录下Cookies,使用–cookie-jar:
curl –cookie-jar cookieFile http://www.dachengge.com
7.2 自动更新和追踪cookie
如果让curl自动保存新的cookie,且提交请求时再带上新的cookie时,可以将–cookie 和–cookie-jar 指向同一个文件:
curl –include –cookie “cook.txt” –cookie-jar “cook.txt” http://dachengge.com
curl –include –cookie “cook.txt” –cookie-jar “cook.txt” http://abc.dachengge.com
即每行指令中都读取和写入相同的cookie文件,系统会自动更新cookie。
7.2 使用变量保存cookie
上一节讲的使用–cookie和–cookie-jar是利用文件来保存和读取cookie,由于文件操作比较费资源,下面将讨论不使用文件,而是使用变量来保存和读取cookie:
当输入:curl www.baidu.com –head, 大家会看到百度首页的头信息,里面有很多set-cookies,即设置cookie变量。首先将目标网页的头保存,然后用grep查找cookie。。。
8 网络登录和访问注意事项
8.1 网络登录注意事项
现在讨论如何使用CURL登录网页,为了顺利地登录网页,需要看很多脚本和很多次CURL访问,很多服务器使用Cookie来跟踪客户端登录状态。因此,很多网站登录页面设置一个特殊的Cookie,来确定用户是通过登录页面进行登录的,因此必须打开登陆页面,记录Cookie信息,之后再action指向的页面提交登录信息。
有很多登录页面包含很多的js代码,使用这些代码来设置或改变Cookie,防止程序登录。因此需要仔细得阅读登录页面的代码,如果实在读不懂,可以使用HTTP协议软件跟踪所有HTTP请求,了解Cookie的变化。
还有些登录页面,包含隐藏域和随机数,防止程序登录,另外登录时如果使用POST方法是,要用urlencode编码。
8.2 网络访问注意事项
为了使CURL访问网页时跟浏览器访问的一样,就必须注意下面的事项:
*使用–trace-ascii把所有的细节记录下来,分析和研究。
*确定检查和使用Cookie,使用–cookie读取,使用–cookie-jar写入cookie。
*使用user-agent仿冒浏览器。
*使用referer让服务器觉得是合法的访问请求。
*使用POST时,要按照文本域的顺序提交。