在进行网页抓取和模拟登陆的开发,curl必须是首选的工具,由于它强大的功能,也提供了多个平台的支持。最近使用curl进行模拟登陆https网站,遇到了一些问题,问题的真相真是不好找,因为本身对网络方面的东西也不太熟悉,后来经过调试,还是找到原因了。
curl下载:http://curl.haxx.se/download.html
另外帮助文档的问题,可以下载curl源码,里面就有提供完整的文档,很详细,如果要使用curl开发,使用里面的文档已经非常清楚。
我遇到以下几个问题:
1.curl登陆https网站失败(最终确认是url编码与socket长连接的问题。)
2.获取的网页源码与浏览器访问的源码有点区别
1.登陆https网站,在不使用证书的情况下,要设置:
2.curl抓取的网页代码与浏览器打开的不一致,这主要是user-agent的设置问题,如果一定要使用浏览器的格式,那么可以直接将某个浏览器的user-agent的值拿来使用,这样就模仿浏览器访问网页了。我这里使用的是火狐浏览器的user-agent:
3.url编码
如果是post操作,那么提交的的表单域要转换成url编码,有些人不熟悉url编码,其实只是把某些特殊的字符转换成通用的格式。
比如:'='转换成"%3D"
如果函数库没有提供,可以自己根据url编码表写一个转换函数。
4.长连接
设置到CURLOPT_HTTPHEADER中,即可添加进去。
5.在curl遇到奇怪的问题,最好要打开调试选项,而且可以结合火狐浏览器的httpfox插件
6.在这里分享一个现成的curl的post操作:
7.调试函数可以这么写,这是在网上找到的:
curl下载:http://curl.haxx.se/download.html
官网提供了多个平台的软件和动态库的下载,这里我使用Qt开发,所以使用了Windows平台下的mingw编译版本:http://curl.haxx.se/gknw.net/7.28.1/dist-w32/curl-7.28.1-devel-mingw32.zip
另外帮助文档的问题,可以下载curl源码,里面就有提供完整的文档,很详细,如果要使用curl开发,使用里面的文档已经非常清楚。
我遇到以下几个问题:
1.curl登陆https网站失败(最终确认是url编码与socket长连接的问题。)
2.获取的网页源码与浏览器访问的源码有点区别
1.登陆https网站,在不使用证书的情况下,要设置:
curl_easy_setopt(m_pCurl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(m_pCurl, CURLOPT_SSL_VERIFYPEER, 0L);
2.curl抓取的网页代码与浏览器打开的不一致,这主要是user-agent的设置问题,如果一定要使用浏览器的格式,那么可以直接将某个浏览器的user-agent的值拿来使用,这样就模仿浏览器访问网页了。我这里使用的是火狐浏览器的user-agent:
curl_easy_setopt(m_pCurl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 5.1; rv:17.0) Gecko/20100101 Firefox/17.0");
3.url编码
如果是post操作,那么提交的的表单域要转换成url编码,有些人不熟悉url编码,其实只是把某些特殊的字符转换成通用的格式。
比如:'='转换成"%3D"
如果函数库没有提供,可以自己根据url编码表写一个转换函数。
4.长连接
用户可以在curl默认的http头添加或修改自己想要的选项,我这里要添加长连接选项:Connection: keep-alive:
struct curl_slist *list;
list = curl_slist_append(list, "Connection: keep-alive");
curl_easy_setopt(m_pCurl, CURLOPT_HTTPHEADER, list);
设置到CURLOPT_HTTPHEADER中,即可添加进去。
5.在curl遇到奇怪的问题,最好要打开调试选项,而且可以结合火狐浏览器的httpfox插件
curl_easy_setopt(m_pCurl, CURLOPT_DEBUGFUNCTION, CurlDebug);//打印完整的调试信息
curl_easy_setopt(m_pCurl, CURLOPT_VERBOSE, 1);//打印调试信息
6.在这里分享一个现成的curl的post操作:
bool CCurl::Post(const QString &actionUrl, const QString &fieldsInfo, QString &htmlStr)
{
CURLcode code;
struct curl_slist *list;
list = curl_slist_append(list, "Connection: keep-alive");
curl_easy_setopt(m_pCurl, CURLOPT_URL, actionUrl.toLatin1().data());
curl_easy_setopt(m_pCurl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(m_pCurl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(m_pCurl, CURLOPT_COOKIEJAR, m_CookiesFileName.toAscii().data());
curl_easy_setopt(m_pCurl, CURLOPT_COOKIEFILE, m_CookiesFileName.toAscii().data());
curl_easy_setopt(m_pCurl, CURLOPT_WRITEFUNCTION, WriteToMem);
curl_easy_setopt(m_pCurl, CURLOPT_WRITEDATA, &htmlStr);
curl_easy_setopt(m_pCurl, CURLOPT_POSTFIELDS, fieldsInfo.toLatin1().data());
curl_easy_setopt(m_pCurl, CURLOPT_POST, 1L);
curl_easy_setopt(m_pCurl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(m_pCurl, CURLOPT_HTTPHEADER, list);
curl_easy_setopt(m_pCurl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 5.1; rv:17.0) Gecko/20100101 Firefox/17.0");
//curl_easy_setopt(m_pCurl, CURLOPT_DEBUGFUNCTION, CurlDebug);//打印完整的调试信息
//curl_easy_setopt(m_pCurl, CURLOPT_VERBOSE, 1);//打印调试信息
code = curl_easy_perform(m_pCurl);
if (CURLE_OK != code)
{
qDebug() << "curl_easy_perform: " << curl_easy_strerror(code);
curl_slist_free_all(list);
return false;
}
curl_slist_free_all(list);
return true;
}
7.调试函数可以这么写,这是在网上找到的:
int CCurl::CurlDebug(CURL *pcurl, curl_infotype itype, char * pData, size_t size, void *)
{
if(itype == CURLINFO_TEXT)
{
qDebug() << "[TEXT]:" << pData;
}
else if(itype == CURLINFO_HEADER_IN)
{
qDebug() << "[HEADER_IN]:" << pData;
}
else if(itype == CURLINFO_HEADER_OUT)
{
qDebug() << "[HEADER_OUT]:" << pData;
}
else if(itype == CURLINFO_DATA_IN)
{
qDebug() << "[DATA_IN]:" << pData;
}
else if(itype == CURLINFO_DATA_OUT)
{
qDebug() << "[DATA_OUT]:" << pData;
}
return 0;
}