C++ socket网络爬虫(1)(一)

2014-11-24 10:47:40 · 作者: · 浏览: 2
C++写的socket网络爬虫,代码会在最后一次讲解中提供给大家,同时我也会在写的同时不断的对代码进行完善与修改
我首先向大家讲解如何将网页中的内容,文本,图片等 下载到电脑中。
image
我会教大家如何将百度首页上的这个百度标志图片(https://www.cppentry.com/upload_files/article/49/1_jh8yv__.gif)抓取下载到电脑中。
image
程序的部分代码如下,讲解在代码的下面,下载链接在最后给出,
int main()
{
string url = "www.baidu.com";
string name = "/img/bdlogo.gif";
int port = 80;
int client_socket = makeSocket(url,port);//1
string request = "GET " + name + " HTTP/1.1\r\nHost:" + url + "\r\nConnection:Close\r\n\r\n";//2
if (send(client_socket, request.c_str(), request.size(), 0) == SOCKET_ERROR)//3
{
cout << "send error" << endl;
}
fstream file;
string fileName = FileName(name);//4
file.open(fileName, ios::out | ios::binary);//5
char buf[1024];
::memset(buf, 0, sizeof(buf));//6
int n = 0;
n = recv(client_socket, buf, sizeof(buf)-sizeof(char), 0);//3
char* cpos = strstr(buf, "\r\n\r\n");//7
file.write(cpos + strlen("\r\n\r\n"), n - (cpos - buf) - strlen("\r\n\r\n"));//7
while ((n = recv(client_socket, buf, sizeof(buf)-sizeof(char), 0)) > 0)//7
{
try
{
file.write(buf, n);
}
catch (...)
{
cerr << "ERROR" << endl;
}
}
file.close();
closesocket(client_socket);
system("pause");
return 0;
一、main函数
1、makeSocket(url,port)
int makeSocket(string host,int port)函数是我自己编写的,接受两个参数,一个是域名或主机名,第二个是所使用的端口号,返回一个用于创建socket的int型数据,将在这一页的二.makeSocket中进行讲解
2、string request = "GET " + name + " HTTP/1.1\r\nHost:" + url + "\r\nConnection:Close\r\n\r\n";
这个是http的请求报头,有很多的信息,这里只对这句话中使用到的进行讲解
GET 请求获取Request-URI所标识的资源;
name 所标识的资源;
HTTP/1.1 表示请求的HTTP协议版本;
Host:url 指定被请求资源的Internet主机和端口号,通常从HTTP URL中提取出来的,
比如 我们在 浏览器中输入http://baidu.com/index. html浏览器发送的请求消息中,就会包含Host请求报头域,如下:
Host:www.baidu.com
此处使用缺省端口号80,若指定了端口号,则变成:Host:www.baidu.com:port
Connection:Close Connection字段用于设定是否使用长连接,在http1.1中默认是使用长连接的,即Connection的值为Keep-alive,如果不想使用长连接则需要明确指出connection的值为close
Connection:Close表明当前正在使用的tcp链接在请求处理完毕后会被断掉。以后client再进行新的请求时就必须创建新的tcp链接了,即必须从新创建socket
更多关于http协议的内容可以查考http://blog.csdn.net/gueter/article/details/1524447 HTTP协议详解
注意最后一定要以一个单独的\r\n作为结束标志
3.send/recv
send用于向服务端发送消息
recv/send函数原型如下
int recv(SOCKET s,char FAR * buf,int len,int flags)/int send(SOCKET s,const char FAR * buf,int len,int flags);
第一个参数表示代表对方的socket,
第二个参数为接收读取的信息的字符串
第三个参数为该字符串的大小
第四个参数可以用来控制读写操作
详情可以参照http://www.cnblogs.com/magicsoar/p/3587351.html 中的讲解1
4 FileName(name)
自己编写的string FileName(string dir)函数,由于 windows中文件的名字中不允许含有/
所以FileName函数用于将dir中的所有/替换为_
string FileName(string dir)
{
string search = "/";
int pos = 0;
while ((pos = dir.find(search, pos)) != string::npos) {
dir.replace(pos, search.size(), "_");
pos++;
}
return dir;
}
如string FileName(“img/bdlogo.gif”)返回_img_bdlogo.gif
5 file.open(fileName, ios::out | ios::binary)r45
io