转自:http://blog.csdn.net/zengraoli/article/details/11517209
题外话:
话说某大型论坛,每天都有不少网友瞄准00.00发表文章,争取拿到当天第一签。某牛某天兴致大发,在Linux下,利用crond定时在00:00运行一个shell脚本程序来发表文章,于是日日得到第一签,引来不少网友羡慕。不必羡慕,看完这篇文章,稍加揣摩,查查资料,你也可以做到了。
一、curl与libcurl介绍
网上关于curl介绍的通常说法是:
curl是一个利用URL语法在命令行方式下工作的文件传输工具。它支持很多协议:FTP, FTPS, HTTP, HTTPS, GOPHER,TELNET, DICT, FILE 以及 LDAP。curl同样支持HTTPS认证,HTTP POST方法, HTTP PUT方法, FTP上传, kerberos认证, HTTP上传,代理服务器, cookies, 用户名/密码认证, 下载文件断点续传, 上载文件断点续传, http代理服务器管道( proxy tunneling),甚至它还支持IPv6, socks5代理服务器, 通过http代理服务器上传文件到FTP服务器等等,功能十分强大。Windows操作系统下的网络蚂蚁,网际快车(FlashGet)的功能它都可以做到。准确的说,curl支持文件的上传和下载,所以是一个综合传输工具,但是按照传统,用户习惯称curl为下载工具。
curl是使用libcurl实现的,而libcurl提供了各种语言的库,方便开发者使用,由于我只了解C语言,所以下面例子使用C语言API。
在看下面内容之前,请先看懂这个example:http://curl.haxx.se/lxr/source/docs/examples/simple.c看懂之后再看:http://curl.haxx.se/lxr/source/docs/examples/postit2.c。
二、实例
使用libcurl库下载hi百度个人私有日志,首先必须用抓包工具抓取hi百度登陆的几个数据包研究,总结规律,然后用libcurl模拟。
通过对hi百度登陆流程,数据包的观察,登陆过程大致分为3步:
1)打开https://passport.baidu.com/?login页面,百度的服务器会在你的页面写一个sessionid,sessionid存在cookie中;
2)用户输入帐号密码,点击登陆,浏览器会发送帐号密码,还有第一步保存的cookie,到https://passport.baidu.com/?login;这里需要特别注意,如果没有发送第一步保存的cookie,服务器会要你填写验证码,而验证码是图片信息,我们无从获取,所以第一步保存cookie是必须的。
3)服务器验证帐号密码,cookie里面的sessionid,正确则再发送两个sessionid给浏览器,以后浏览器获取页面都会发送这两个sessionid回服务器验证。
了解这些之后,用libcurl c API实现三个小程序来获取一个被我设置为个人私有的页面,这三个小程序最好是写成一个程序来,考虑到为了给初学者一个清晰的思路,用三个小程序对应上面描述的三个步骤,程序代码见附录。
看到这里,也许你会说,何必这么麻烦,我用帐号密码登陆也可以看到自己的私有文章。这里最重要的是演示如何用libcurl模拟网站的登陆过程,登陆之后要做什么就随便你了。如果你是想搞破坏了,也很简单,把下面的程序改成灌水机就可以了,不过建议别这么做,小心被封帐号或IP,当然,你可以申请多个帐号,把你的程序做成木马,用别人的肉机来灌水。但是奉劝一句:出来混早晚要还的,把技术用来"为人民服务"吧!
在结束这篇文章之前,得说明一下,如果你是UNIX类用户,直接用curl就可以方便实现下面的功能,只要几条语句,这也就是开篇说的shell程序的内容了。
附录:
- /*************open_login_page.c***********/
- #include <stdio.h>
- #include <string.h>
- #include <curl/curl.h>
- #include <curl/types.h>
- #include <curl/easy.h>
- int main(int argc, char *argv[])
- {
- CURL *curl;
- CURLcode res;
- struct curl_slist *headerlist=NULL;
- static const char buf[] = "Expect:";
- curl_global_init(CURL_GLOBAL_ALL);
- curl = curl_easy_init();
- headerlist = curl_slist_append(headerlist, buf);
- if(curl)
- {
- curl_easy_setopt(curl, CURLOPT_URL, "https://passport.baidu.com/?login");
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
- curl_easy_setopt(curl, CURLOPT_COOKIEJAR,"cookie_open.txt");//把服务器发过来的cookie保存到cookie_open.txt
- #ifdef SKIP_PEER_VERIFICATION
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
- #endif
- #ifdef SKIP_HOSTNAME_VERFICATION
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
- #endif
- res = curl_easy_perform(curl);
- /* always cleanup */
- curl_easy_cleanup(curl);
- /* free slist */
- curl_slist_free_all(headerlist);
- }
- return 0;
- }
- /********************login_hi_baidu*****************/
- #include <stdio.h>
- #include <string.h>
- #include <curl/curl.h>
- #include <curl/types.h>
- #include <curl/easy.h>
- int main(int argc, char *argv[])
- {
- CURL *curl;
- CURLcode res;
- struct curl_slist *headerlist=NULL;
- static const char buf[] = "Expect:";
- curl_global_init(CURL_GLOBAL_ALL);
- curl = curl_easy_init();
- headerlist = curl_slist_append(headerlist, buf);
- if(curl)
- {
- curl_easy_setopt(curl, CURLOPT_URL, "https://passport.baidu.com/?login");
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
- curl_easy_setopt
- (curl,CURLOPT_POSTFIELDS,"username=s_yqguo&password=&psp_tt=0&safeflg=0&return_method=get&u=http://hi.baidu.com/s%
- 5Fyqguo");//设置帐号密码,其余的信息是页面要求的,抓包即可看见。
- curl_easy_setopt(curl,CURLOPT_COOKIEFILE,"cookie_open.txt");//提交第一步保存的cookie
- curl_easy_setopt(curl,CURLOPT_COOKIEJAR,"cookie_login.txt");//保存登陆后的cookie
- #ifdef SKIP_PEER_VERIFICATION
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
- #endif
- #ifdef SKIP_HOSTNAME_VERFICATION
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
- #endif
- res = curl_easy_perform(curl);
- /* always cleanup */
- curl_easy_cleanup(curl);
- /* free slist */
- curl_slist_free_all(headerlist);
- }
- return 0;
- }
- /************download_private_page.c******************/
- #include <stdio.h>
- #include <string.h>
- #include <curl/curl.h>
- #include <curl/types.h>
- #include <curl/easy.h>
- static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream)
- {
- int written = fwrite(ptr, size, nmemb, (FILE *)stream);
- return written;
- }
- int main(int argc, char *argv[])
- {
- CURL *curl;
- CURLcode res;
- static const char *headerfilename = "head.out";
- FILE *headerfile;
- static const char *bodyfilename = "body.html";
- FILE *bodyfile;
- struct curl_slist *headerlist=NULL;
- static const char buf[] = "Expect:";
- curl_global_init(CURL_GLOBAL_ALL);
- curl = curl_easy_init();
- headerlist = curl_slist_append(headerlist, buf);
- if(curl)
- {
- //拉取私有页面
- curl_easy_setopt(curl, CURLOPT_URL, "http://hi.baidu.com/s_yqguo/blog/item/c4e99e58d7ec9d86800a18a2.html");
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
- headerfile = fopen(headerfilename,"w");
- if (headerfile == NULL)
- {
- curl_easy_cleanup(curl);
- curl_global_cleanup();
- curl_slist_free_all(headerlist);
- printf("open head.out file failed!\n");
- return -1;
- }
- bodyfile = fopen(bodyfilename,"w");
- if (bodyfile == NULL)
- {
- curl_easy_cleanup(curl);
- curl_global_cleanup();
- curl_slist_free_all(headerlist);
- printf("open body.html file failed!\n");
- return -1;
- }
- curl_easy_setopt(curl,CURLOPT_WRITEHEADER, headerfile);
- curl_easy_setopt(curl,CURLOPT_WRITEDATA,bodyfile);
- curl_easy_setopt(curl,CURLOPT_COOKIEFILE,"cookie_login.txt");//把第二步保存的cookie发送给服务器验证
- #ifdef SKIP_PEER_VERIFICATION
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
- #endif
- #ifdef SKIP_HOSTNAME_VERFICATION
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
- #endif
- res = curl_easy_perform(curl);
- /* always cleanup */
- curl_easy_cleanup(curl);
- /* free slist */
- curl_slist_free_all(headerlist);
- curl_global_cleanup();
- if(headerfile != NULL)
- fclose(headerfile);
- if(bodyfile != NULL)
- fclose(bodyfile);
- }
- return 0;
- }