libcurl是一个免费且易于使用的客户端URL传输库,是一个轻量级的HTTP编程库,很好使用,curl也是Linux下一个非常著名的下载库,通过这个库,可以很简单的实现文件的下载等操作。当然我们可以用它来实现一个简易的C++爬虫(不是Python才能爬虫的哦=_=)
sudo wget http://curl.haxx.se/download/curl-7.35.0.tar.gz
tar -zxvf curl-7.35.0.tar.gz
./configure --prefix=/usr/local/libcurl //这里可以自行设置路径
make
make install
如上,libcurl库就已经安装好了,非常的方便,当然在编译的时候别忘了加上链接的选项哦
g++ -o spider spider.cc -w -std=c++11 -lcurl //最后一个选项-lcurl必须加上
具体的操作细节,可以看下面的代码就知道了。
这个爬虫要爬的主要信息是新浪新闻首页相应主题下的所有新闻的信息,包括作者,标题和内容
当然如果不需要处理数据的话,只要看spider.hpp 和spider.cc的main函数就可以知道流程了。
spider.hpp
#pragma once
#include
#include
#include
#include
#include
#include
using namespace std;
//ibcurl主要提供了两种发送http请求的方式,分别是Easy interface方式和multi interface方式
//前者是采用阻塞的方式发送单条数据,后者采用组合的方式可以一次性发送多条数据
//Easy interface方式最基本的用法如下
//1、在主线程中调用curl_global_init(CURL_GLOBAL_ALL)初始化
//2、调用curl_easy_init获取一个句柄;
//3、调用curl_easy_setopt函数设置此次传输的一些基本参数,如url地址、http头、cookie信息、发送超时时间等,其中,CURLOPT_URL是必设的选项;
//4、设置完成后,调用curl_easy_perform函数发送数据;
//5、数据发送完毕后,调用curl_easy_cleanup清空句柄;
//6、调用curl_global_cleanup()做清理工作。
class HttpCurl
{
public:
HttpCurl()
:conn(NULL)
{}
~HttpCurl(){
//调用该函数清空句柄
curl_easy_cleanup(conn);
}
bool HttpCurlInit(string& context){
CURLcode code;
//1、在主线程中调用curl_global_init(CURL_GLOBAL_ALL)初始化
code = curl_global_init(CURL_GLOBAL_ALL);
if(CURLE_OK != code){
cout << "Failed to global init default" << "\n";
return false;
}
//2、调用curl_easy_init获取一个句柄;
conn = curl_easy_init();
if(NULL == conn){
cout << "Failed to create CURL" << "\n";
return false;
}
//3、调用curl_easy_setopt函数设置此次传输的一些基本参数
//CURLOPT_WRITEFUNCTION 第三个参数表明的函数将在libcurl接收到数据后被调用,因此函数多做数据保存的功能
//第三个参数回调函数原型为:size_t function( void *ptr, size_t size, size_t nmemb, void *stream );
code = curl_easy_setopt(conn,CURLOPT_WRITEFUNCTION,HttpCurl::Write);
if(CURLE_OK != code){
cout << "Failed to set write" << "\n";
return false;
}
// CURLOPT_WRITEDATA 用于表明CURLOPT_WRITEFUNCTION函数中的第三个参数stream的来源
// 因此调用完该函数以后,收到的数据就被放到了context中
code = curl_easy_setopt(conn,CURLOPT_WRITEDATA,&context);
if(CURLE_OK != code){
cout << "Failed to set write data" << "\n";
return false;
}
return true;
}
bool SetUrl(string& url){
CURLcode code;
//CURLOPT_URL 用于设置访问的url
code = curl_easy_setopt(conn,CURLOPT_URL,url.c_str());
if(CURLE_OK != code){
cout << "Failed to set URL" << "\n";
return false;
}
return true;
}
bool GetHttpResponse(){
CURLcode code;
// curl_easy_perform函数完成curl_easy_setopt指定的所有选项
code = curl_easy_perform(conn);
if(CURLE_OK != code){
cout << "Failed to get response" << "\n";
return false;
}
return true;
}
static size_t Write(void* data,size_t size,size_t nmemb,string& context){
long sizes = size*nmemb;
string temp((char*)data,sizes);
context += temp;
return sizes;
}
private:
CURL* conn;
};
filter.hpp(这个文件主要是用来设置爬取的信息格式,注意需要用到boost库,没安装的可以去看下这个boost库的安装)
#pragma once
#include
#include
using namespace std;
#include
#include
class filter{
public:
//该函数用来设置正则表达式匹配
void SetReg(string reg){
_reg = reg;
}
//该函数将匹配的结果连成一个字符串放在一起
string filterUrlString(string url){
string::const_iterator begin = url.begin();
string::const_iterator end = url.end();
string results;
while(regex_search(begin,end,_what,_reg)){
string result(_what[0].first,_what[0].second);
results += result;
begin = _what[0].second;
}
return results;
}
//该函数将匹配的结果放到vector中
vector filterUrlVector(string url){
string::const_iterator begin = url.begin();
string::const_iterator end = url.end();
vector results;
while(regex_search(begin,end,_what,_reg)){
string result(_what[0].first,_what[0].second);
results.push_back(result);
begin = _what[0].second;
}
return results;
}
private:
boost::regex _reg;
boost::smatch _what;
};
spider.cc(这个源文件用来爬取新浪首页的内容,当然不可能所有的新闻页眉都是可以被我们设置的正则表达式匹配,只是大多是的页面,不匹配的大不了我们不要了嘛=_=)
#include "spider.hpp"
#include "../HTTP_server/cgi/operate.hpp" //这个文件是我自己写的一个数据库交互库,下面在用到的时候会说明
#include "filter.hpp"
#include